nginx反向代理https网站配置

有老同事前段时间问我,为何最近几年都没怎么更新博客了。我说这两年实在是太忙了,虽然做的事情还是比较多,但是真的是很少有自己的时间静下来写一下blog。

回到主题,我们有时需要在一些特殊的内网环境访问多个https的网站,但是又没有集中的NAT网关。这个时候可以利用nginx做一个集中的代理。代理HTTP的时候是很简单的,简单配置一下proxy_pass到特定的HTTP地址或者是upstream就行,但是如果目标的网站是多个https的,则因为我们没有证书无法简单实现。

幸运的时随着各种客户端对https sni的支持,可以使用TCP模式的代理来支持这种场景,基于对SSL SNI的识别去选择upstream。一个简单的示例如下:


map $ssl_preread_server_name $selected_upstream {
    dockerauth.dockerhub.com upstream_dockerauth;
    reg.dockerhub.com upstream_reg;
    dauth.dockerhub.com  upstream_dauth;
    default  upstream_dauth;
}
upstream upstream_dockerauth { dockerauth.dockerhub.com :443; }
upstream upstream_reg { server reg.dockerhub.com:443; }
upstream upstream_dauth { server dauth.dockerhub.com:443; }

server {
    listen 0.0.0.0:443;
    proxy_pass $selected_upstream;
#   proxy_pass $ssl_preread_server_name:443;
    ssl_preread on;
    }

发表在 nginx | nginx反向代理https网站配置已关闭评论

通过iptables做VXLAN的vni过滤

背景

有需要要对vxlan的流量做过滤,只允许特定vxlan id的流量访问。

方案调研

通过iptables支持各种策略过滤,但是并没原生的任何插件可以直接支持vxlan报文过滤。后来就想到了2个方案

  1. U32模块本身支持取报文的特定字段做匹配,因此就想到了使用U32。
  2. 现在7U的服务器上的iptables是支持bpf的,可以支持使用’-m bpf –bytecode’ 添加编译好的字节码做过滤。

但实际上使用bpf需要单独弄一个工具去生成这个二进制的代码,长期的维护性不是太好,所以虽然最终2个方案都走通了 还是支持选了u32.

我们都知道一个IP报文 里 IP 头是20字节,TCP是20字节,UDP是8个字节,VXLAN是8字节。vxlan的包头如下

,VXLAN报文本身是封装在UDP报文内,因此一个针对vxlan报文简单的U32匹配可以按下面的逻辑来生产

20 ip+ 8 UDP + 1 VXLAN flags +3 Reserved =32的位置就是VNID左边,因此下面的表达式就可刚好是VNID的区域

-p udp -m udp -m u32 –u32 “32>>8=xxxx”

考虑到可能IP头有option,因此也有一个改进的版本

–u32 “0>>22&0x3C@12>>8=xxx”

详细的原因可以参考:https://netfilter.org/documentation/HOWTO/netfilter-extensions-HOWTO-3.html

参考:

  1. https://oswalt.dev/2014/03/mtu-considerations-for-vxlan/
  2. https://ask.wireshark.org/question/10372/sniffing-vxlan-traffic/
  3. https://support.huawei.com/enterprise/en/doc/EDOC1100004365/f95c6e68/vxlan-packet-format
  4. https://man7.org/linux/man-pages/man8/iptables-extensions.8.html
  5. https://netfilter.org/documentation/HOWTO/netfilter-extensions-HOWTO-3.html

发表在 net | 通过iptables做VXLAN的vni过滤已关闭评论

阿里云ODPS做IP段转换的python UDF

单个IP转成十进制

“`
from odps.udf import annotate
@annotate(“string->bigint”)
class ip2int(object):
  defevaluate(self, ip):
    try:
      returnreduce(lambda x, y:(x << 8) + y,map(int, ip.split(‘.’)))
    except:
      return 0
“`

一个IP段的网络地址和广播地址转成十进制

“`

from odps.udf import annotate
import ipaddress
@annotate(“string->string”)
class ipnet2range(object):
    defevaluate(self, ip):
        try:
               net=ipaddress.ip_network(ip)
               returnstr(int(net.network_address)) +’,’+ str(int(net.broadcast_address))
         except:
                ipaddr=ipaddress.IPv4Interface(ip)
                net=ipaddr.network
                returnstr(int(net.network_address)) +’,’ + str(int(net.broadcast_address))

“`

 

参考
1.https://help.aliyun.com/document_detail/97075.html?spm=a2c4g.11186623.2.21.7c582098UhsRjh#concept-q25-ygl-5fb
2. https://help.aliyun.com/document_detail/97075.html?spm=a2c4g.11186623.4.4.47804662WwU7Py

发表在 python | 阿里云ODPS做IP段转换的python UDF已关闭评论

GPS授时服务器DIY

国内外厂商制造的高精度时钟服务器实际都是基于x86服务器,加装铷钟和GPS接收模块构成。树莓派流行起来后,网上也有配套的模块,让大家可以制造一个小巧的时钟服务器。实际这淘宝上有很多USB接口的GPS接收模块,产品特性:
GPS+GLONASS双模定位
内置FLASH,USB供电
自适应1200-921600波特率
1Hz输出,NMEA-0183协议输出。
NTPD是业内对各种GPS接受器支持的最好的,绝大部分GPS接受模块实际都是使用标准的NMEA协议从/dev/gps输出。

测试的配置如下:


# For more information about this file, see the man pages
# ntp.conf(5), ntp_acc(5), ntp_auth(5), ntp_clock(5), ntp_misc(5), ntp_mon(5).
logfile /var/log/ntp.log
driftfile /var/lib/ntp/drift
# Permit time synchronization with our time source, but do not
# permit the source to query or modify the service on this system.
restrict default nomodify notrap nopeer noquery

# Permit all access over the loopback interface.  This could
# be tightened as well, but to do so would effect some of
# the administrative functions.
restrict 127.0.0.1
restrict ::1

# Hosts on local network are less restricted.
#restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap

# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
server 127.127.20.1 mode 17 minpoll 4 maxpoll 4
fudge  127.127.20.1 stratum 0 refid GPS  flag1 1 flag2 0 flag3 1
server 127.127.1.1 minpoll 4 maxpoll 4
fudge  127.127.1.1 stratum 1 refid LCK
#

# Enable public key cryptography.
#crypto

includefile /etc/ntp/crypto/pw

# Key file containing the keys and key identifiers used when operating
# with symmetric key cryptography.
keys /etc/ntp/keys

# Specify the key identifiers which are trusted.
#trustedkey 4 8 42

# Specify the key identifier to use with the ntpdc utility.
#requestkey 8

# Specify the key identifier to use with the ntpq utility.
#controlkey 8

# Enable writing of statistics records.
#statistics clockstats cryptostats loopstats peerstats

# Disable the monitoring facility to prevent amplification attacks using ntpdc
# monlist command when default restrict does not include the noquery flag. See
# CVE-2013-5211 for more details.
# Note: Monitoring will not be disabled with the limited restriction flag.
disable monitor
发表在 NTP, System | GPS授时服务器DIY已关闭评论

salt定义内核参数

salt的states语句支持直接定义内核参数,比较方便。需要注意的时对于7U的机器得指定config: /etc/sysctl.conf。


net.core.rmem_max:
sysctl.present:
- value: 67108864
- config:  /etc/sysctl.conf
net.core.rmem_default:
sysctl.present:
- value: 33554432
- config:  /etc/sysctl.conf
发表在 OS | salt定义内核参数已关闭评论

GPS报文格式说明

格式如下

00225s

+000000004

0599992.512TDC

0004990.716LST0004989.71FIS

$GNGGA,060633.000,3119.3559,N,12135.9948,E,1,22,0.6,51.2,M,0.0,M,,*4A

$GNRMC,060633.000,A,3119.3559,N,12135.9948,E,0.00,203.12,160419,,,A*71

$SYS,041619,060634,0,0,1,0,1,0,0,1,2,1,0,

+000000004
[root@centos1 dev]# cat /dev/gps1 |grep GNGGA
$GNGGA,085318.00,3016.36039,N,12006.35748,E,1,12,0.99,37.4,M,7.1,M,,43
$GNGGA,085319.00,3016.36042,N,12006.35743,E,1,12,1.04,37.4,M,7.1,M,,
40
$GNGGA,085320.00,3016.36044,N,12006.35739,E,1,11,1.14,37.4,M,7.1,M,,43
$GNGGA,085321.00,3016.36051,N,12006.35748,E,1,11,1.07,37.6,M,7.1,M,,
40
$GNGGA,085322.00,3016.36057,N,12006.35755,E,1,12,1.06,37.7,M,7.1,M,,4A
$GNGGA,085323.00,3016.36062,N,12006.35764,E,1,12,0.97,37.8,M,7.1,M,,
49
$GNGGA:GPGGA(时间、定位质量)
UTC时间,纬度,纬半球,经度,经半球,定位质量标,卫星数量,水平精确度,天、地水准高度,差分GPS数据等, *, 校验和, 回车、换行
$GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,M,<10>,M,<11>,<12>xx
$GPGGA:起始引导符及语句格式说明(本句为GPS定位数据);
<1> UTC时间,格式为hhmmss.sss;
<2> 纬度,格式为ddmm.mmmm(第一位是零也将传送);
<3> 纬度半球,N或S(北纬或南纬)
<4> 经度,格式为dddmm.mmmm(第一位零也将传送);
<5> 经度半球,E或W(东经或西经)
<6> GPS状态, 0初始化, 1单点定位, 2码差分, 3无效PPS, 4固定解, 5浮点解, 6正在估算 7,人工输入固定值, 8模拟模式, 9WAAS差分
<7> 使用卫星数量,从00到12(第一个零也将传送)
<8> HDOP-水平精度因子,0.5到99.9,一般认为HDOP越小,质量越好。
<9> 海拔高度,-9999.9到9999.9米
M 指单位米
<10> 大地水准面高度异常差值,-9999.9到9999.9米
M 指单位米
<11> 差分GPS数据期限(RTCM SC-104),最后设立RTCM传送的秒数量,如不是差分定位则为空
<12> 差分参考基站标号,从0000到1023(首位0也将传送)。
* 语句结束标志符
xx 从$开始到
之间的所有ASCII码的异或校验
维度: dd+mm/60+mmmm/600000
维度: ddd+mm/60+mmmm/600000
位置定位页面 http://www.gpsspg.com/maps.htm

$GNRMC,091655.00,A,3016.36112,N,12006.35204,E,0.042,,200419,,,A6E
$GNRMC,091656.00,A,3016.36112,N,12006.35203,E,0.038,,200419,,,A
67

$GNRMC,095554.000,A,2318.1327,N,11319.7252,E,000.0,005.7,081215,,,A*73
(1) UTC 时间, hhmmss(时分秒)【095554.000】
(2) 定位状态, A=有效定位, V=无效定位【A】
(3) 纬度 ddmm.mmmmm(度分)【2318.1327】
(4) 纬度半球 N(北半球)或 S(南半球)【N】
(5) 经度 dddmm.mmmmm(度分)【11319.7252】
(6) 经度半球 E(东经)或 W(西经)【E】
(7) 地面速率(000.0~999.9 节)【000.0】
(8) 地面航向(000.0~359.9 度,以真北方为参考基准)【005.7】
(9) UTC 日期, ddmmyy(日月年)【081215】
(10) 磁偏角(000.0~180.0 度,前导位数不足则补 0)【】
(11) 磁偏角方向, E(东)或 W(西)【】
(12) 模式指示(A=自主定位, D=差分, E=估算, N=数据无效)【A】

GPS Fix Data Sentence(PGRMF)GPS定位信息
$PGRMF,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>,<13>,<14>,<15>*hh
<1> GPS周数(0~1023)
<2> GPS秒数(0~604799)
<3> UTC日期,ddmmyy(日月年)格式
<4> UTC时间,hhmmss(时分秒)格式
<5> GPS跳秒数
<6> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输)
<7> 纬度半球N(北半球)或S(南半球)
<8> 经度dddmm.mmmm(度分)格式(前面的0也将被传输)
<9> 经度半球E(东经)或W(西经)
<10> 模式,M=手动,A=自动
<11> 定位类型,0=没有定位,1=2D定位,2=3D定位
<12> 地面速率(0~1851公里/小时)
<13> 地面航向(000~359度,以真北为参考基准)
<14> PDOP位置精度因子(0~9,四舍五入取整)
<15> TDOP时间精度因子(0~9,四舍五入取整)
解析参考

https://blog.csdn.net/qq_32384313/article/details/77745386
https://blog.csdn.net/MakeWorks/article/details/77639883

发表在 NTP | GPS报文格式说明已关闭评论

salt里定义账号和公钥

salt可以支持账号的增加以及ssh的公钥管理


user_add:
user.present:
- uid: 1000
- name: myuser
- groups:
- myuser
group_add:
group.present:
- gid: 1000
- name: myuser
- require_in:
- user: user_add
user_sshkey:
ssh_auth.present:
- user: myuser
- names:
- 'ssh-rsa XXXXXX'
- 'ssh-rsa yyyyyy'
- require:
- user:  user_add
发表在 System | salt里定义账号和公钥已关闭评论

当前常见2款MTK OpenWrt路由器的对比

去年双11趁着电信活动,把家里的宽带升级到了200Mbps,然后之前家里用的一个是用了三四年的网件 3700V4就成为瓶颈了,主要存在的问题是
1. WIFI 5G最多只能到140M
2. 有线接上,NAT能力只有180M左右,桥接可以到200+,原因是AR8327不支持HWNAT。
作为一个Openwrt的忠实用户,替换路由的第一要素是能得到OpenWrt原生支持的设备,以便配置802.11r,满足无缝漫游的需求。
再要综合考虑满足全千兆,无线支持802.11AC,驱动完善,而且价格还不贵的路由器实际就很少了。
当前低价位的路由器主要还是螃蟹芯片和MTK为主,尤其是MTK7621AT的路由器非常多。对比了当前的新3(newifi D2)和友华WR1200JS后,还是选择了新3。

WR1200JS

  1. CPU MTK7621AT 16M 128MB
  2. 5G芯片 MT7612EN 功放芯片 SKY85717-21,它集成了PA与LNA
  3. 2.4G MT7603EN,只有PA,无LNA
  4. 闪存 16M
  5. 内存 128M

newifi D2

  1. CPU MTK7621AT
  2. 5G芯片 MT7612EN 功放芯片RTC5638H 集成PA和LNA
  3. 2.4G MT7603EN 无PA,无LNA
  4. 闪存 16M
  5. 内存512M
    主要的原因还是新3内存大太多了,然后实际的做工用料比较足。实际使用的效果也还不错,虽然说2.4G容易出问题,不过5G是比较稳定的。
    PS:没选K2P是因为Openwrt官网的版本驱动不支持MT7615DN。
发表在 OpenWrt | 当前常见2款MTK OpenWrt路由器的对比已关闭评论

你所不知道的GPS周数轮转

背景

GPS的时间是基于GPS时间起点(UTC 1980-01-06 00:00:00 ),用经历过一个周数和周内秒数定义的。表述这个周数使用的是一个10bit的字段,因此每过1024周就会出现一次翻转事件。GPS在1999年8月21日出现过周数翻转,今年是在2019年4月6日出现周数翻转。针对此类重点的事件,如果出现问题,会导致公司的整个授时体系的时间回退到1980年,存在所有业务受影响可能性。因此我在前期做了比较多的分析工作。一方面同多家GPS授时服务器的厂商确认是否会有影响,另外一方面自己从相关的文献和代码上确认实际受影响的概率。最终确认这个事件对现在的授时体系100%无影响。

技术原理分析

GPS授时服务器,俗称原子钟。实际的结构是由一个x86服务器(主板上接有铷原子钟或恒温晶振),外接一个可接收GPS/北斗/Galileo信号的天线组成。设备就放在机房的工机具区域,蘑菇头天线置于机房外(绝大部分是置于房顶)。设备上电后,一般几分钟就可以收到4个以上的卫星信号,完成位置锁定和时间同步。开机一段时间后内置的原子钟会被GPS信号驯服,最终趋于一个稳定频率,使得当GPS信号断掉后,还能保持非常高的授时精度。当前世面上设备的常用原子钟的主流精度是年偏差不超过±3ms。
GPS的授时服务器内的天线模块,通过解析GPS的L1NAV报文,计算出对应的位置&时间等信息。GPS接收器把原始报文经过一系列的计算后,使用NMEA-0183协议把相应的信息通过串口输出。针对串口输出报文中的GAGGA和GARMC数据做解析,就可以计算出当前的时间和日期。具体的报文是如下格式:


$GBGGA,105804.00,3016.36015,N,12006.34368,E,1,10,1.53,14.3,M,7.1,M,,*4A
$GBRMC,105805.00,A,3016.36016,N,12006.34352,E,0.120,,210419,,,A,V*1D

其中GBGGA的第二列表示现在是10:58:04,GBRMC的210419表示现在是19年4月21日。
整条链路实际上是
GPS–(广播)–>接收天线模块—-(芯片处理输出NMEA-0183报文)—-> NTPD处理
我们逐个分析可能出问题的环境:
1. 接收天线不能正确处理周数轮转,这个只能找厂商确认。
2. NTPD在根据报文做处理时,处理错误,这个可以自己从代码里去判断(实际上已经经历过一次周数轮转了,应该不会有问题)。

针对NTPD本身的时间处理,因为NMEA的报文里只有2位的年数和时间,那么当原子钟第一次启动时,其实是需要做判断才能知道这个时间到到底是2019年还是3019年的。NTPD在启动初始化NMEA设备时(也就是GPS接收天线在linux系统中注册的串口设备),会获取到软件编译的时间。而这个时间被NTPD作为额外一个参数传入做关键的判断(如果把编译的时间设置为1980年之前,则会使用1980)。具体的转换函数代码如下


int32_t
ntpcal_periodic_extend(
int32_t pivot,
int32_t value,
int32_t cycle
)
{
uint32_t diff;
char     cpl = 0; /* modulo complement flag */
char     neg = 0; /* sign change flag       */

/* make the cycle positive and adjust the flags */
if (cycle &amp;lt; 0) {
        cycle = - cycle;
        neg ^= 1;
        cpl ^= 1;
    }
    /* guard against div by zero or one */
    if (cycle &amp;gt; 1) {
/*
* Get absolute difference as unsigned quantity and
* the complement flag. This is done by always
* subtracting the smaller value from the bigger
* one.
*/
if (value &amp;gt;= pivot) {
diff = int32_to_uint32_2cpl(value)
- int32_to_uint32_2cpl(pivot);
} else {
diff = int32_to_uint32_2cpl(pivot)
- int32_to_uint32_2cpl(value);
cpl ^= 1;
}
diff %= (uint32_t)cycle;
if (diff) {
if (cpl)
diff = (uint32_t)cycle - diff;
if (neg)
diff = ~diff + 1;
pivot += uint32_2cpl_to_int32(diff);
}
}
return pivot;
}

比如如果软件的编译时间是2015年,从GPS报文获取到的时间是19,一个世纪100年,因此调用该函数的时候传入的参数如下:
ntpcal_periodic_extend(2015,19,100),最终可以计算出准确的年份是2019年。

在服务器运行的过程中,遇到周数轮转时是如何处理的呢,实际上NTPD自身的时间是以1900年1月1日0时为起点计算的,
反正就是从NMEA报文里获取的时间戳,和周数根本没关系。根本就不受所谓的轮转影响,只是内部有部分UTC/GPS时间转换的函数,在遇到GPS的周数轮转后,做了相应的±1024的操作。例如下面这个把GPS时间转换成NTP时间的函数:


void
gpstolfp(
u_int weeks,
u_int days,
unsigned long  seconds,
l_fp * lfp
)
{
if (weeks &amp;lt; GPSWRAP)
{
weeks += GPSWEEKS;
}

lfp-&amp;gt;l_ui = (uint32_t)(weeks * SECSPERWEEK + days * SECSPERDAY + seconds + GPSORIGIN); /* convert to NTP time */
lfp-&amp;gt;l_uf = 0;
}

那么接收模块能否支持周数轮转呢,厂商把设备放实验室,通过模拟器输出对应的信号,观察机器相应的反应即可。我们使用的设备厂商是做了相关的测试,因此确认这方面是没风险的。

针对此种轮转事件,唯一出问题的风险点在于20年前的设备,主板上电池坏掉了,关机后重启系统只能有一个BIOS的默认时间,这时即便时收取到卫星信号,按照前面说的算法,是无法计算出正确的时间的(接收模块不能计算出准确时间,而且NTPD也不能处理这种异常)。

北斗

当此次GPS周数轮转后,国内的媒体除了一个劲地转发一些毫无技术分析的文章时,也有把北斗单独做了赞扬。主要的原因是北斗使用13bit存储周数,需要100多年才会翻转一次。其实2004年GPS也有升级的CNAV报文是使用13bit存储周数(目前大部分设备还是使用L1NAV)。
不过NMEA协议是为了在不同的GPS(全球定位系统)导航设备中建立统一的RTCM(海事无线电技术委员会)标准,由美国国家海洋电子协会(NMEA-The National Marine Electronics Associa-tion)制定的一套通讯协议。市面上你能买到民用的设备,虽然可以接受北斗的信号,但是你从设备串口读取出来的都是NMEA-0183的报文,和GPS的没有差异,还是会存在初次转成4位年数的问题。唯一值得庆幸的时,北斗是在21世纪才开始做的导航系统,这2位数字还能用个80年。

北斗报文


$GBRMC,175829.00,A,3016.36276,N,12006.35248,E,0.271,,200419,,,A,V*1D
$GBGGA,175829.00,3016.36276,N,12006.35248,E,1,08,1.28,48.6,M,7.1,M,,*4E
$GBGGA,175830.00,3016.36276,N,12006.35247,E,1,08,1.28,48.8,M,7.1,M,,*47
$GBRMC,175831.00,A,3016.36281,N,12006.35248,E,0.088,,200419,,,A,V*18
$GBGGA,175831.00,3016.36281,N,12006.35248,E,1,08,1.28,49.0,M,7.1,M,,*48
$GBRMC,175832.00,A,3016.36283,N,12006.35256,E,0.080,,200419,,,A,V*1E
$GBGGA,175832.00,3016.36283,N,12006.35256,E,1,08,1.28,49.4,M,7.1,M,,*42

GPS报文


$GNGGA,060633.000,3119.3559,N,12135.9948,E,1,22,0.6,51.2,M,0.0,M,,*4A

$GNRMC,060633.000,A,3119.3559,N,12135.9948,E,0.00,203.12,160419,,,A*71

参考文档

  1. https://en.wikipedia.org/wiki/GPS_signals#Time
发表在 NTP | 你所不知道的GPS周数轮转已关闭评论

IPTV单线复用

由于老房子弱电箱到客厅电视后面只有一根网线,所以我也遇到许多人都有的单线复用场景。之前是直接网上买了2个转接头,把8芯网线拆成2个4芯网线来使用。不过问题就是局域网内只有100M的带宽。双11看电信搞活动,花了之前100M宽带一半的钱把家里的宽带升级到了200M。就想着通过vlan隔离来把单线复用配置一下。

基本的方案其实很简单,首先需要明白从光猫的LAN口和ITV口出来的包都是不带VLAN tag的,因此把ITV的口接到交换机上,把从这个口进入的报文打个VLAN tag,再在电视机后面放个openwrt路由器把这个vlan解出来,桥接到一个lan口即可。大致的网络拓扑如下:

弱电箱里使用了水星的支持VLAN的交换机,配置如下

openwrt路由器上简单设置一下软交换,把对应的vlan和一个lan口桥接在一起,lan口选择untag。

发表在 OpenWrt | IPTV单线复用已关闭评论