使用quagga配置BGP

BGP相对OSPF来说在骨干网络上使用的比较多,是目前域间路由协议的事实标准。通常在服务器上直接使用BGP的场景不多(内部网络大家都倾向使用OSPF这类IGP)。其实BGP的配置也很简单,从以下的拓扑来看4个机器的BGP配置 各路由配置文件 R1 配置 ! log file /var/log/quagga/zebra.log log file /var/log/quagga/bgpd.log ! password bgp ! interface eth0 ipv6 nd suppress-ra link-detect ! interface eth1 ipv6 nd suppress-ra no link-detect ! interface lo no link-detect ! interface tunl0 ipv6 nd suppress-ra no link-detect ! router bgp 65000 bgp router-id 10.1.0.5 redistribute connected metric 121 neighbor 10.1.0.4 remote-as 65000 neighbor 10.1.0.4 password DOCKER neighbor 10.1.0.4 next-hop-self distance bgp 250 200 150 exit ! access-list all permit any ! ip forwarding ipv6 forwarding ! line vty ! end ...

February 23, 2017 · 5 min · pm

TCP Over IP Anycast适用场景

Anycast在国内应用现状 Anycast本身是个古老的技术,但是在国内互联网公司内都使用的不多。其原因如下:1. 普通的互联网服务的高可用可以通过DNS层切换,业务恢复时间最短可以控制在5分钟内,满足国内绝大部分企业的需求了。2. Anycast实施的网络接入要求比较高,国内企业具备有自己BGP网络的屈指可数。在公有云业务发展起来之前,国内大规模使用BGP网络为主营业务提供服务除了阿里之外别无二家,鹅厂和熊厂长期以来还是用智能DNS配合多线机房的静态带宽来提供服务。究其原因主要还是BGP带宽的成本比较高,中小企业根本没有人力与财力与大运营商在多个城市做BGP接入。 anycast在国外的应用其实在几年前也不多,主要的应用范围还是在DNS这类使用UDP的无状态的业务上。因此之前国外使用Anycast的场景主要是以下几种:1. 各厂商承建的13组 ROOT DNS server。2. 各DNS GTLD Server。3. 国外的互联网巨头(Google,facebook,MS,Akamai,Amazon)的DNS server4. 国外流行的DNS服务厂商,比如NSone,DYN之类的5. 国外的新兴CDN厂商(微软Azure、Cloudflare、MaxCDN等)的Cache server。 国内使用anycast的主要场景:1. BAT的这类有数十个IDC以上的公司的内部基础服务。2. 各运营商内部的DNS的跨城部署(绝大部分是各省份内部) 总结一下,之前绝大部分anycast都是用在UDP的业务,少量CDN公司的Cache 节点使用了Anycast。 TCP业务的Anycast实施难点 从anycast的RFC内可以看到,只推荐使用anycast应用在无状态的业务上。对于HTTP之类的使用TCP的业务都不推荐部署。主要是在IP报文在被路由转发时,当存在ECMP(等价路由)的时候只是机械的按每个IP包随机丢到多个下一跳中的一跳,可能导致TCP连接都无法建立。一般情况下公网上的路由,只有宣告方触发或者中途链路异常时才会做变化,对于常规的非长连接业务其实都是无影响的。 TCP 业务实施Anycast的关键因素 这两年,随着移动业务的快速发展,各手机APP都在不断优化自己的使用体验。因为国内之前长期大量移动网络用户还停留在2/3G网络,无线业务的网络条件查,通过传统的DNS查询几十个域名对用户体验影响巨大。慢慢地大家开都搞起了HTTPDNS,绕过ISP的DNS,走HTTP批量做域名的查询。然后大家又发现鸡生蛋 蛋生鸡的问题出来了,HTTPDNS自己的访问绕不过DNS。因此这两年腾讯、阿里云提供的HTTPDNS又开始把服务地址改成Anycast地址了。这也算是国内第一批有状态业务的Anycast部署。TCP业务部署Anycast的参考几方面:1. 自己是否具备BGP网络。2. 自己使用真的有那么高的业务要求、或者是不想走DNS。3. 多点宣告后广域网内各地是否稳定优选到”就近点“(一般情况下BGP路由在各地优选是固定就行)。4. 接入层的交换机能支持一致性hash(一般是根据源IP/源端口/目标IP/目标端口/协议做hash,目前入门的3层交换机都支持)。5. 单个业务的request/response时间,一般HTTP请求的业务都是适用的,相反一些push类的长连接业务不适用。6. 各区域是否在大部分时候路由到固定节点,这块有论文做过研究,大部分anycast CDN的路由在几个月维护时才动一次,然后恢复原状。

February 22, 2017 · 1 min · pm

单个域名的RR记录上限

前几天同事反馈有个2000多个域名指向了自己的一台服务器,但是查询对应机器的PTR记录时发现只有1700多个。dig -x 查询了一下发现确实只有1700多个,检查了对应的zone文件内PTR记录是有2000多个的。偶然发现dig返回的MSG SIZE到了65519 在RFC1035中提到了DNS的几个限制:labels 63 octets or lessnames 255 octets or lessTTL positive values of a signed 32 bit number.UDP messages 512 octets or less整个UDP的消息被限制在512,不过随着后来EDNS0扩展协议(rfc2671),UDP的报文是可以到4096的(最大可以到65535)。在查询同事提供的PTR记录时,请求本身被TC置位走了TCP,因次这个UDP的限制无关的。DNS的限制实际在协议上 All RRs have the same top level format shown below: 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / / / NAME / | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | CLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TTL | | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | RDLENGTH | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| / RDATA / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ where: NAME an owner name, i.e., the name of the node to which this re source record pertains. TYPE two octets containing one of the RR TYPE codes. CLASS two octets containing one of the RR CLASS codes. TTL a 32 bit signed integer that specifies the time interval that the resource record may be cached before the source of the information should again be consulted. Zero values are interpreted to mean that the RR can only be used for the transaction in progress, and should not be ...

February 21, 2017 · 2 min · pm

startssl证书CA被吊销

近期证书到期,到startssl上续了一个证书,部署上死活不行。搜了一下才发现startssl的ca因为沃通倒签证书、私自颁发github证书,CA被Mazilla,Chrome都去除了。。腾讯云上申请了1个免费的ssl证书搞定。

January 11, 2017 · 1 min · pm

ntp支持的外部时钟源

公司先后采购过多种GPS授时服务器。之前一直不是太明白ntpd是如何使用外接的这些硬件。这两年树莓派比较流行,也有很大人利用外接的扩展件让树莓派成为一级时钟源。其中关键的ntp.conf配置如下 [一级时钟源](http://www.satsignal.eu/ntp/Raspberry-Pi-NTP.html)driftfile /var/lib/ntp/ntp.drift ```bash # coarse time ref-clock, not really needed here as we have LAN & WAN servers server 127.127.28.0 minpoll 4 maxpoll 4 fudge 127.127.28.0 time1 +0.350 refid GPS stratum 15 # Kernel-mode PPS ref-clock for the precise seconds server 127.127.22.0 minpoll 4 maxpoll 4 fudge 127.127.22.0 refid PPS # LAN servers ```bash server 192.168.0.3 minpoll 5 maxpoll 5 iburst prefer server 192.168.0.2 minpoll 5 maxpoll 5 iburst server 192.168.0.7 minpoll 5 maxpoll 5 iburst ...

January 9, 2017 · 6 min · pm

控制linux时钟速度的几个参数

1. tick 用户态下内核时钟计数间隔,默认都是100HZ。因此单个tick代表了10^4 us。 可以设置每个tick代表的时钟长度,因此把tick增加1(即增加为10001us)的影响是每天时间慢8.64s(24小时的tick被提前消耗完) 24*3600*100*10001/10^6-24*3600=8.64s。 2. ppm 百万分之一秒,1个PPM增加 24*360*(10^6+1)/10^6-24*3600=0.0864s。 PPM 增加500,每天的时间慢500*0.0864=43.2s 假设服务器现在标准的PPM为 A,为了让系统24小时快1s。则ppm的调整为A- 1*10^6/3600/24=A-11.574074。 处理闰秒如果想让时钟在一天内慢1s,则可以用ntptime -f把frequency改为服务器当前的值+11.574 ubuntu@ip-172-31-23-155:~/ntp-4.2.8p9$ ntptime ntp_gettime() returns code 0 (OK) time dc1e24a0.5e832b98 Mon, Jan 9 2017 15:02:56.369, (.369189989), maximum error 73959 us, estimated error 101 us, TAI offset 0 ntp_adjtime() returns code 0 (OK) modes 0x0 (), offset 75.601 us, frequency 18.063 ppm, interval 1 s, maximum error 73959 us, estimated error 101 us, status 0x2001 (PLL,NANO), time constant 5, precision 0.001 us, tolerance 500 ppm, ...

January 9, 2017 · 3 min · pm

ntpq输出说明

以一个阿里云VM上的输出为例 [root@CentOS ~]# ntpq -pn remote refid st t when poll reach delay off set jitter ============================================================================== 127.127.1.0 .LOCL. 10 l - 64 0 0.000 0.000 0.000 #2001:4860:4806: 71.79.79.71 2 u 1012 1024 357 280.158 -15.630 3.135 #2001:4860:4806: 71.79.79.71 2 u 816 1024 377 262.399 -24.971 2.702 #2001:4860:4806: 71.79.79.71 2 u 708 1024 377 364.687 -13.306 4.368 #2001:4860:4806: 71.79.79.71 2 u 606 1024 377 381.816 -28.115 3.897 *182.92.12.11 10.137.38.86 2 u 327 1024 377 0.245 0.810 0.792 ...

January 4, 2017 · 2 min · pm

DNS解析时间与访问量 TTL的关系

大家在维护DNS的时候会有一个烦恼,很难平衡几个点1. 域名的平均解析时间要很短– 因为网站访问的时候所有得请求都需要依赖DNS解析,如果网站的访问量小,用户每次请求时需要先等递归DNS递归,整体的时间会很长。2. 机房故障的时候切换要快– 有多IDC的人都会面临一个问题,单个IDC故障的时候希望能尽快通过DNS将流量切换到另外的一个IDC,这个时候需要TTL短。3. DNS的部署成本– 正常网站的dns其实都不大的,如果没有攻击,4个机器跑个bind也能支撑国内BAT的一起的DNS解析。– 如果我们希望DNS的解析效果好,就需要在部署位置、接入网络等各方面想办法优化,成本也是指数增加。 不同频率的DNS解析任务来统计DNS的解析时长,可以分析一下网站访问量,域名TTL和用户侧平均DNS解析耗时之间的一些关系。 上图是相同TTL的域名,在访问频率不同的场景下的对比,可以看出随着监控域名的解析频率从1分钟下降到5分钟一次后,DNS的解析时间从66ms增加到85ms。 再从相同监控频率,不同TTL的解析这个维度来看 随着TTL从60s提升到120s,DNS的平均解析时间从66ms下降到59ms。再看看当TTL提升到600s的时候,DNS的平均解析时间下降到 47ms左右。 基于以上场景对比,我们可以有结论:1. TTL适当增加,DNS的延迟可以大幅下降。2. 网站访问量的增加,DNS延迟也可以有大幅下降。 DNS在用户终端的平均解析时间其实很难对比,也不存在完美的最佳实践。对一般中小企业,建议:1. DNS的TTL 300-600S,如果访问量不是很大,不建议TTL下降到120以下。2. 机房切换的容忍时间5-10分钟。

December 28, 2016 · 1 min · pm

使用线程安全的strtok_r

最近改写一个dns-flood的程序为多线程模式,发现每个线程中生成的随机数字经常是一样 。 [dns-flood](https://github.com/nickwinn/dns-flood)void nameformat(char *name, char *QS) { char *bungle, *x; char elem[128]; *QS = 0; bungle = malloc(strlen(name) + 3); strcpy(bungle, name); x = strtok(bungle, "."); while (x != NULL) { if (snprintf(elem, 128, "%c%s", strlen(x), x) == 128) { puts("String overflow."); exit(1); } strcat(QS, elem); x = strtok(NULL, "."); } free(bungle); } 该函数是在构造DNS请求报文中被调用,通过传入指针name将字符串复制到QS指向的地址内。debug发现QS经常打印出来和name不一样,查了发现strtok不是线程安全的,改用strtok_r后终于OK了。 void nameformat_r(char *name, char *QS) { char *bungle, *x; char elem[128]; char *flag; *QS = 0; bungle = malloc(strlen(name) + 3); strcpy(bungle, name); x = strtok_r(bungle, ".", &flag); while (x != NULL) { if (snprintf(elem, 128, "%c%s", strlen(x), x) == 128) { puts("String overflow."); exit(1); } strcat(QS, elem); x = strtok_r(NULL, ".", &flag); } free(bungle); }

December 28, 2016 · 1 min · pm

dnspython读取dnszone所有记录

需求 有时需要从zone文件里解析DNS的数据,做一些分析。可以利用dnspython库做zone的解析处理。简单写一个如下 #!/usr/bin/env python import dns.zone import dns.ipv4 import os.path import sys import os import string import re zonefile=sys.argv[1] name=sys.argv[2] class LOAD_ZONES: def __init__(self,zonefile,name): self.types=("A","CNAME","TXT","SOA","MX","NS","PTR") self.record=dict() self.zonefile=zonefile self.name=name for type in self.types: self.record[type]=dict() try: zoneload= dns.zone.from_file(f=self.zonefile,origin=self.name,check_origin=False,relativize=False) for type in self.types: for (name, ttl, rdata) in zoneload.iterate_rdatas(type): dname=str(name) l = self.record[type].get(dname) if l is None: self.record[type][dname] = set() if type == “A”: self.record[type][dname].add( ("%s-%s") % (ttl,rdata.address ) ) else: self.record[type][dname].add( ("%s-%s") % (ttl,rdata.to_text().lower()) ) except dns.zone.NoSOA: print “%s no soa” % self.zonefile except dns.zone.NoNS: print “%s no ns” % self.zonefile def dump_record(self): for type in self.types: for k in self.record[type].keys(): print k,type,self.record[type][k] def del(self): pass ...

December 27, 2016 · 1 min · pm