TCP三次握手的意义

大家去面试的时候,经常都让简单介绍TCP的三次握手。上半年我也去面试了一下,问了十多个人,基本都只能简单说出三次握手的SYN,ACK-SYN,ACK的发送顺序。不过基本没有人能完成说出三次握手的关键所在。

三次握手的功能主要实际包括几种:
1. 接触和通信。
2. 序列号的交换。client和server端把自己的初始序列号isn(一个随机数)告诉对方。
3. MSS协商,协商发送报文的最大长度。
4. 交换其他的参数。比如窗口比例因子(Window Scale Factor)等等

发表在 net | TCP三次握手的意义已关闭评论

ospf的dr、bdr

ospf协议中是有多种网络类型:
1. 点到点网络(p2p)
2. 广播网络(broadcast)
3. 非广播多路访问(nbma)
4. 点到多点(p2mp)
5. 虚链路(virtual links)

其中只有广播类型和非广播多路访问是有DR,BDR的。其他三种网络类型都是没有DR,BDR的。比如P2P的

ospf_dr

对于广播类型和非广播多路访问类型的OSPF,都是需要靠DR(BDR)来做LSA的floodding。比如有路由器R1,R2,R3,R4,R5。如果R1选举为了DR,R2是BDR,那么实际R2,R3,R4,R5都只与R1形成邻接关系。R1-5将会继续发hello包到224.0.0.5这个组播地址。更新数据包的发送是R3-R5会以组播的方式发送到组播地址224.0.0.6(只有R1 R2监听这个地址),DR收到后再使用组播发到224.0.0.5更新整个区域的LSA。

发表在 net | ospf的dr、bdr已关闭评论

snat dnat测试

今天同事问了个dnat的问题,就是在linux服务器上把某个端口的流量dnat到上面跑的某个kvm虚拟机上没有正常工作,简单看了下就是ip_forward没有打开。。
想着自己也很多没有搞过这些了,简单试试snat+dnat。基本的结构是
目的使用192.168.100.17做代理服务器,专门做SNAT+DNAT,练习NAT的使用。

192.168.125.135(client)–>192.168.100.17(NAT机器)–> 192.168.128.26(DNS服务器)
可以看到这几个IP都不在同一个24掩码的vlan内,所以没有办法把NAT机器设置成DNS机器的网关。所以配置上更加复杂一点,不过也便于理解nat的工作流程。实际就是在prerouting和postroute的对包的操作了。

1. 先在 192.168.100.17上设置DNAT,让从192.168.125.135进来的dns查询包的目的IP修改为192.168.128.26
[bash]
#iptables -t nat -A PREROUTING -i bond0 -p udp –dport 53 -j DNAT –to-destination 192.168.128.26:53
[/bash]

2. 192.168.100.17上设置SNAT,把上面的包在经过路由表后,出去前把source ip改了。
[bash]
#iptables -t nat -A POSTROUTING -o bond0 -p udp -d 192.168.128.26 –sport 53 -j SNAT –to-source 192.168.100.17
[/bash]

发表在 net | snat dnat测试已关闭评论

igb Detected Tx Unit Hang

公司大量的服务器使用了intel的网卡,主要是intel I350/82580/82576。 各个版本的igb驱动都出现过detected tx unix hang的报错。
大部分是老版本igb的bug,更新到新版后基本都解决了。不过最近发现有几台I350(4端口)的升级了驱动还是存在这样的报错。
[text]
Detected Tx Unit Hang in Quad Port Adapters http://downloadmirror.intel.com/20927/eng/e1000.htm
In some cases ports 3 and 4 don’t pass traffic and report ‘Detected Tx Unit Hang’ followed by
‘NETDEV WATCHDOG: ethX: transmit timed out’ errors. Ports 1 and 2 don’t show any errors and will pass traffic.
This issue MAY be resolved by updating to the latest kernel and BIOS. The user is encouraged to run an
OS that fully supports MSI interrupts. You can check your system’s BIOS by downloading the Linux
Firmware Developer Kit that can be obtained at http://www.linuxfirmwarekit.org/
[/text]
intel的文档是说4端口的网卡因为3,4端口没有流量,所以有”detected tx unix hang”的提示,可以通过更新BIOS解决。不过我仔细看了demesg的内容,显示出现detected tx unix hang的是eth0和eth1。今天尝试了修改各种参数,比如gro,tso之类的都关闭了,增加了TX ring的大小,甚至连tx-checksumming也关闭了。不过最后还是有这样的报错。
[text]
[ 3181.339388] igb 0000:02:00.0: Detected Tx Unit Hang
[ 3181.339390] Tx Queue <7>
[ 3181.339390] TDH <28c>
[ 3181.339391] TDT <28c>
[ 3181.339392] next_to_use <28c>
[ 3181.339392] next_to_clean <b2>
[ 3181.339393] buffer_info[next_to_clean]
[ 3181.339394] time_stamp <1002bfb38>
[ 3181.339394] next_to_watch <ffff88183fa00b20>
[ 3181.339395] jiffies <1002c0074>
[ 3181.339396] desc.status <1b8001>
[ 3424.144387] igb 0000:02:00.1: Detected Tx Unit Hang
[ 3424.144388] Tx Queue <7>
[ 3424.144389] TDH <e39>
[ 3424.144389] TDT <e39>
[ 3424.144390] next_to_use <e39>
[ 3424.144391] next_to_clean <8b3>
[ 3424.144391] buffer_info[next_to_clean]
[ 3424.144392] time_stamp <1002fa71c>
[ 3424.144392] next_to_watch <ffff8818226e8b30>
[ 3424.144393] jiffies <1002fb60d>
[ 3424.144394] desc.status <1b8001>
[/text]
后来咨询了硬件团队的同学,他们说之前在hadoop集群内遇到过类似的问题,最终通过新增vm.min_free_kbytes=81920内核参数解决。

参考:
http://kernel.taobao.org/index.php/Kernel_Documents/mm_sysctl

===
这个问题现在发现还是存在,设置了这个内核参数没有起到作用。原因待继续排查。。。。。

发表在 System | igb Detected Tx Unit Hang已关闭评论

iptables使用tee模块镜像流量

一般的流量镜像需要在交换机上做,实际上iptables也有个tee模块做流量镜像。在OpenWrt里使用也比较简单。
1. 把tee模块安装上加载进去(需要依赖ipv6模块)
[bash]
opkg install kmod-ipt-tee

2.把某个源IP的包镜像发到指定的IP
iptables -t mangle -A PREROUTING -s 192.168.3.224 -j TEE –gateway 192.168.3.100

3. 把某个目的IP的包镜像到指定的IP
iptables -t mangle -A POSTROUTING -d 192.168.3.224 -j TEE –gateway 192.168.3.100

4. 删除规则
iptables -t mangle -F

5. 也可以把整个网段的都镜像
root@wan:/etc/config# iptables -t mangle -A PREROUTING -s 192.168.3.0/24 -j TEE –gateway 192.168.3.100
root@wan:/etc/config# iptables -t mangle -A POSTROUTING -d 192.168.3.0/24 -j TEE –gateway 192.168.3.100
[/bash]
这样当192.168.3.224这个IP有通信的时候,流量都会被镜像到192.168.3.100这个机器上面,可以在上面直接抓包查看。

tee

上图是抓包手机 微博和易讯客户端打开的的DNS查询。

发表在 net, OpenWrt | iptables使用tee模块镜像流量已关闭评论

使用memtester测试内存

最近有几个新的服务器,经常有一堆内存的报错。并且是服务上线后才发现的,dmesg里能看到很多错误信息,但是带外直接看sel log又没有异常。尝试了下使用memtester来测试。
使用比较简单,直接编译安装后,放screen运行。
Usage: memtester [-p physaddrbase] [B|K|M|G] [loops]
[bash]
# ./memtester 7G 10
测试7G内存,循环10次
[/bash]
虽然最终测试的结果表明我的机器内存没有啥大问题,但是触发了几次CE,然后才在ilo的界面上看到换掉的内存条位置,再保修解决。

发表在 System | 使用memtester测试内存已关闭评论

adjtimex使用

今天遇到一个ntp的同步问题。服务器上配置好了ntpd,在启动前也手动进行过同步,但是过段时间ntpq查询发现服务器即便能选出同步服务器,但是系统的时间偏差越来越大。
服务器上实际有2个时钟,一个是主板电池驱动的硬件时间(RTC或者CMOS时间),另外就是系统时间。服务器启动时会从RTC里读取一次时间,之后便靠中断来计时。可以设置ntpd同步后讲时间写回RTC.


语法:adjtimex [OPTION]… 主要参数说明:
-p, –print   输出内核时间变量的值
-t, –tick val    设置内核时钟计数间隔(微秒)
-f, –frequency newfreq   设置系统时钟偏移量
-c, –compare[=count]     比较系统时钟和CMOS时钟
-i, –interval tim    设置时钟比较间隔时间 (sec)
-l, –log[=file]  将当前时间记录到文件中
–host timeserver     查询时间服务器
-u, –utc     将CMOS时钟设置成UTC

在服务器上先比较一下系统时间和CMOS时间


# adjtimex --compare
                                      --- current ---   -- suggested --
cmos time     system-cmos  error_ppm   tick      freq    tick      freq
1381503971     1.751318
1381503981     1.721794    -2952.4  10000  -1573016
1381503991     1.692179    -2961.5  10000  -1573016   10029   2456959
1381504001     1.662619    -2956.0  10000  -1573016   10029   2097584
1381504011     1.633055    -2956.4  10000  -1573016   10029   2122584
1381504021     1.603491    -2956.4  10000  -1573016   10029   2122584
1381504031     1.573928    -2956.3  10000  -1573016   10029   2117896
1381504041     1.544361    -2956.7  10000  -1573016   10029   2142896

然后使用
# adjtimex -t 10029
修改一下tick,重新手动同步后,再启动ntpd发现时间终于正常了。

发表在 OS | adjtimex使用已关闭评论

使用dnspython解析zone文件生成反解记录

今天试了下使用dnspython来解析zone文件,然后把IP->Domain信息输出来。按照PTR格式输出到zone文件里面。


<br />#!/usr/bin/env python2.7
import dns.zone
import dns.ipv4
import os.path
import sys
import string
import re
zonedir='/home/work/dns/var/named/zone/'
tempdir='/home/work/dns/script/'
master_zones=("zone1.xxx.com","zone2.xxx.com")
ptr_zones=("10.rev","172.rev")
class PTR:
    def  __init__(self,zones):
        self.new_serial=dict()
        self.reverse_map=dict()
        for zonefile in zones:
            filename=zonedir+zonefile
            zone = dns.zone.from_file(filename,os.path.basename(filename),relativize=False)
            for (name, ttl, rdata) in zone.iterate_rdatas('SOA'):
                serial=str(rdata).split()[2]
                if serial &gt; 0:
                    self.new_serial[zonefile]=int(serial)+1
                    if len(sys.argv) ==2 :
                        self.new_serial[zonefile]=int(sys.argv[1])
                else:
                    print "read old ptr zone file:%s err" % zonefile
                    sys.exit(2)

    def load_master_zone(self,zones):
        for zonefile in zones:
            filename=zonedir+zonefile
            zone = dns.zone.from_file(filename,os.path.basename(filename),relativize=False)
            for (name, ttl, rdata) in zone.iterate_rdatas('A'):
                match=re.search(r'\*\.',str(name))
                if match:
                    print "ignore *.xxx domain"
                    continue
                l = self.reverse_map.get(rdata.address)
                if l is None:
                    self.reverse_map[rdata.address] = []
                self.reverse_map[rdata.address].append(name)
    def dump_ptr_zone(self,zones):
        fd=dict()
        for zone in zones:
            file=tempdir+zone
            fd[zone]=open(file,"w")
            headtxt='''$TTL   86400
@  IN SOA   dns1.xxx.com. pm.xxx.com.  (
             %s; Serial
             60  ; Refresh
             80  ; Retry
             604800   ; Expire
              6400 )  ; Minimum
@                       NS      din-1
@                       NS      din-2
din-1      A       172.x.x.x
din-2      A       172.x.x.x\n''' %self.new_serial[zone]
            fd[zone].write(headtxt)
        keys = self.reverse_map.keys()
        ipreg=re.compile("(\d+)\.(\d+)\.(\d+)\.(\d+)")
        keys.sort(lambda a1, a2: cmp(dns.ipv4.inet_aton(a1), dns.ipv4.inet_aton(a2)))
        for ip in keys:
            match=ipreg.search(ip)
            if not  match:
                continue
            ip1=match.group(1)          
            ip2=match.group(2)          
            ip3=match.group(3)          
            ip4=match.group(4)
            ptrzone="%s.rev"%ip1
            fd_out=fd.get(ptrzone)
            if  fd_out is not None:
                v = self.reverse_map[ip]
                v.sort()
                domains = map(str, v)
                for domain in domains:
                    line="%s.%s.%s\tPTR\t%s\n" %(ip4,ip3,ip2,domain)
                    fd_out.write(line)
        for zone in zones:
            fd[zone].close()
    def __del__(self):
        pass

ptr=PTR(ptr_zones)
ptr.load_master_zone(master_zones)
ptr.dump_ptr_zone(ptr_zones)
发表在 python | 使用dnspython解析zone文件生成反解记录已关闭评论

处理libc链接被误删

最近有同学找到我,说是libc的一个链接被误删了.在libc的一些链接被删除后,ssh就不能登陆了,因为基本所有的动态链接的程序都是需要使用libc

[text]

pm@debian:/ $ ldd /usr/sbin/sshd |grep libc.so
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fca3ea2e000)

[/text]

另外重启也是不能登陆系统的,因为/sbin/init也是需要使用libc.so….

[text]pm@debian:/ $ ldd /sbin/init|grep libc.so
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007faee32df000)

[/text]

解决的办法只有单独有livecd或者有条件PXE进系统去把分区挂载起来,然后单独把链接恢复.

 

发表在 OS | 处理libc链接被误删已关闭评论

qugga配置ospf

这两年ospf这个内部网关协议在互联网公司的链路负载均衡上出现的频率越来越高,BAT公司都是用OSPF+LVS做负载均衡。连小米这样的公司也开始这样玩了。ospf的配置实际是比较简单的,主要是一般就网工比较了解这个,其他部门的人都这些都没有任何概念,觉得很生疏。简单贴2个配置文件。

quagga实际是个套件,里面有zebra,ospfd,ripd,bgpd等等。其中zebra是ip路由管理进程,可以去更新kernel的路由、更新本地接口的地址或者在把一个的路由协议的路由表重分发到其他重分发到其他的路由协议,比如把ospfd里的发到bgpd里去。ospfd、ripd、bgpd是各自负责ospd,rip,bgp协议的守候进程。所以一般我们在本地服务器上配置ospf会涉及2个配置文件,一个是zebra的zebra.conf,另外一个是ospfd的ospfd.conf。服务器的上联模式可以选择单上联或者双上联,具体的细节配置需要根据实际的硬件条件(主要是看上联交换机,千兆上联的交换机一般比较屌丝,LSA的支持可能也不够完善,最好使用单上联的模式);默认路由可以本地配置死,也可以就默认通过ospfd从上联交换机学习默认路由,我一般比较推荐千兆上联直接配死。

架设服务器有4个网卡,eth0,eth1做bond连本地的内网接入交换机,eth2单上联到专门配置ospf的交换机。eth2和上联交换机的互联IP是:192.168.20.100/30这个网段,本地使用192.168.20.102这个互联地址,交换机上配置192.168.20.101.本地可以宣告的地址是192.168.200.0/24内的任意地址。

zebra.conf


hostname "XXXX"
password xxxx
enable password xxxxx
log file /var/log/zebra.log
log syslog
interface lo
interface bond0
   link-detect
interface eth2
   link-detect #配置link-detect的好处是链路短掉后上层交换机马上能感知,否则只能等ospf的hello超时才会把这个链路标记为不可用。可以缩短链路故障后的影响时间
interface eth3

ospfd.conf


hostname XXXX
password xxxx
enable password xxxx
log file /var/log/ospf.log
interface bond0
interface eth3
interface eth2
 ip ospf network point-to-point
 ip ospf message-digest-key 1 md5 PASSWORDXXX
 ip ospf hello-interval 1
 ip ospf dead-interval 3
interface lo

router ospf
 ospf router-id YOU_LOCAL_IP
 network 192.168.20.102/30  area 0.0.0.102
 network 192.168.200.0/24 area 0.0.0.102
 area 0.0.0.102 authentication message-digest
line vty

ospfd.conf里需要在interface里配置好网络类型,验证的密码,hello-interval和dead-interval时间。router ospf里需要把互联地址的网段配在network里,也要把想宣告的网段配置在里面。ospfd会把在这个网段内的接口分配后面指定的area里。

这样配置好后先起zebra,再起ospfd,然后在loopback地址上添加一个192.168.200.0/24内的32位掩码的IP,就可以对外宣告出去了(当然,前提是交换机也得做好配置)。

hello-interval和 dead-interval一般默认的时间是10s、40s。这个需要和交换机的配置一致,否则不能建立邻居。启动后一是可以自己看ospfd.log,另外也可以telnet 127.0.0.1 2604去show ip ospf route/neighbor/database 看响应的状态。

发表在 net | qugga配置ospf已关闭评论