文章有截图,若看不清楚,可把页面放大200%进行查看。
环境:测试一个ac下挂ap,ap下的抓包文件传出时,出现问题:
ac的wan口ip是192.168.186.167/24,gw是192.168.186.1,下挂ap的ip是192.168.202.199/24,ac上开子接口192.168.202.1/24,ac上开nat功能。tftp服务器在pc192.168.186.118/24上,和ac的wan口在同一网段。
开始以为是ap的对应目录和文件没有读写权限,chmod 777进行修改后,问题依旧。
root@IIIoT:/# chmod 777 /tmp
root@IIIoT:/# tftp -p -l /tmp/staonline3.pcap 192.168.186.118
tftp: server error: (768) Access to /tmp/staonline3.pcap denied
root@IIIoT:/# cd /tmp
root@IIIoT:/tmp# ls -l staonline3.pcap
-rw-r--r-- 1 root root 2010 Sep 29 17:16 staonline3.pcap
root@IIIoT:/tmp# chmod 777 staonline3.pcap
root@IIIoT:/tmp# tftp -p -l /tmp/staonline3.pcap 192.168.186.118
tftp: server error: (768) Access to /tmp/staonline3.pcap denied
root@IIIoT:/tmp# tftp -p -l /tmp/staonline3.pcap 192.168.186.118
tftp: server error: (768) Access to /tmp/staonline3.pcap denied
root@IIIoT:/tmp# tftp: server error: (768) Access to /tmp/staonline3.pcap denied
问题还在,决定在tftp服务器pc上和ap上同时抓包,对比查看。tftp的usb网卡接ap同一网段的接口,ap的抓包传到usb网卡的ip上,这样不经过ac的nat功能。
root@IIIoT:~# tcpdump -any -nne -w testtftp.pcap
tcpdump: invalid data link type -nne
root@IIIoT:~# tcpdump -i any -nne -w testtftp.pcap
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
^C894 packets captured
896 packets received by filter
0 packets dropped by kernel
root@IIIoT:~# ls -l *pcap
-rw-r--r-- 1 root root 85651 Sep 26 18:45 staonline.pcap
-rw-r--r-- 1 root root 111110 Sep 29 20:24 testtftp.pcap
root@IIIoT:~# tftp -pl testtftp.pcap 192.168.202.202 传出ap上抓包文件
ap上抓包文件显示如下:只有客户端发出write请求消息,没有后续消息
tftp服务器上抓包显示如下:
tftp服务器发出ack,收到ac发来的destnation port unreachable的消息。
查看icmp的目标不可达消息
发现源地址ac的wan口地址,而目标地址是tftp服务器的地址,而且ttl是64,表示是ac直接发出,而不是经过转接的icmp消息。
对应ap的抓包,ack并没有收到,而且也没有icmp消息发出,据此判断ac直接回的目标端口不可达。
原因分析,ac没有端口alg功能,对tftp协议,后续消息会改变端口发来,而ac的conntrack记录表的五元组里没有对应的表项,导致ac直接回icmp端口不可达项。
conntrack和nat的原理:
数据进入路由器的处理流程:
数据入站,要先查conntrack表里是否有对应的连接记录,没用的话要创建一个新的记录。有的话,符合reply的要进行对应处理。
内网收包:
- 数据包进入Hook(例如ip_nat_out)函数后,进行规则匹配
- 如果所有match都匹备,则进行SNAT模块的动作,即snat的target模块
- 源地址转换的规则一般是…… -j SNAT –to X.X.X.X,SNAT用规则中预设的转换后地址X.X.X.X,修改连接跟踪表中的reply tuple(原因:当数据包进入连接跟踪后,会建立一个tuple以及相应的reply tuple,而回程应答的数据包,会查找与之匹配的reply tuple,——对于源地址转换而言,应答包中的目的地址,将是转换后的地址,而不是真实的源地址,所以,为了让应答的数据包能找到对应的reply tuple,很自然地,NAT模块应该修改reply tuple中的目的地址为snat之前的源地址,以使应答数据包能找到属于自己最终目的地址)
- 接着,修改数据包的来源的地址,将它替换成reply tuple中的相应地址,即规则中预设的地址,将其发送出去
- 对于回来的数据包,应该能在状态跟踪表中,查找与之对应的reply tuple,也就能顺藤摸瓜地找到原始的tuple中的信息,将应答包中的目的地址改回来,这样,整个数据传送就得以顺利转发了
一个路由器的conntrack范例:
路由器的内网接口ip是192.168.100.3,wan口是pppoe接口,获得ip是219.145.1.240,访问外网要用pppoe获得ip进行snat转换。用内网的设备192.168.209.201进行访问。
这个范例里记录内网收到的一个访问路由器自己的内网接口ip地址,另一个访问外网的网页443端口,都生成的reply回包的期望源ip和目的ip,以及协议类型和状态,是否snat和dnat的类型,收发的包数等信息。出包,进行snat转换,把源地址转换为路由器wan口地址后发出,同时记录conntrack表项的reply值。
wan口收到回包查询conntrack表项,符合reply表项,而且有snat记录的表项,要先进行转换,把目的地址改成source里的源地址,然后进行路由判断,发现是内网地址,符合转发forward条件,就再次进行路由判断后,由内网接口发出。
对应该例,conntrack表里
udp
source:192.168.202.199:42850 > 192.168.186.118:69
reply : 192.168.186.118:69 > 192.168.186.167:42850
但ftp服务器192.168.186.118的ack消息用的是udp协议:
source:192.168.186.118:50767 > 192.168.186.167:42850
这在conntrack表里查不到,就建立一个新记录,目的ip是ac的wan口地址,路由判断后是input处理,ac上没用打开42850这个端口,就按output链处理,发出端口不可达消息。
测试一下,关闭ac的nat功能,发现重新测试,文件传送成功。