SNAT小虚惊一场

最近有点着迷iptables,各种用法都想试试

虚拟机里一个内网IP,一个float IP

root@iptables:~# ip a
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0:  mtu 1400 qdisc pfifo_fast state UP qlen 1000
    link/ether fa:16:3e:a8:79:61 brd ff:ff:ff:ff:ff:ff
    inet 10.10.38.115/21 brd 10.10.39.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fea8:7961/64 scope link
       valid_lft forever preferred_lft forever
3: eth1:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether fa:17:00:13:01:14 brd ff:ff:ff:ff:ff:ff
    inet 115.115.115.187/21 brd 115.115.119.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::f817:ff:fe13:114/64 scope link
       valid_lft forever preferred_lft forever

路由规则

root@iptables:~# ip r
0.0.0.0/1 via 115.115.112.1 dev eth1
default via 10.10.32.1 dev eth0
......

添加一条源地址转换规则

root@iptables:~# iptables -t nat -A POSTROUTING -s 10.10.38.115/21 -j SNAT --to-source 115.115.115.187
root@iptables:~# iptables -t nat -vnL POSTROUTING --line-number
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 SNAT       all  --  *      *       10.10.32.0/21       0.0.0.0/0            to:115.115.115.187

这里内网网关只有内网才能通,外网却是没法通的,此时已经将源IP地址为该内网IP的包,源IP snat成了外网IP,而没有这条路由规则,虚拟机内部应该是没法通内网网关的,但是

root@iptables:~# ping 10.10.32.1
PING 10.10.32.1 (10.10.32.1) 56(84) bytes of data.
64 bytes from 10.10.32.1: icmp_req=1 ttl=62 time=0.371 ms
64 bytes from 10.10.32.1: icmp_req=2 ttl=62 time=0.172 ms
64 bytes from 10.10.32.1: icmp_req=3 ttl=62 time=0.172 ms
64 bytes from 10.10.32.1: icmp_req=4 ttl=62 time=0.146 ms
64 bytes from 10.10.32.1: icmp_req=5 ttl=62 time=0.114 ms

看到大吃一惊,先抓内网网卡的包

root@iptables:~# tcpdump -i eth0 icmp -en
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
21:32:54.943565 fa:16:3e:a8:79:61 > fa:16:3e:92:36:49, ethertype IPv4 (0x0800), length 98: 115.115.115.187 > 10.10.32.1: ICMP echo request, id 21802, seq 1, length 64
21:32:55.942572 fa:16:3e:a8:79:61 > fa:16:3e:92:36:49, ethertype IPv4 (0x0800), length 98: 115.115.115.187 > 10.10.32.1: ICMP echo request, id 21802, seq 2, length 64
21:32:56.941563 fa:16:3e:a8:79:61 > fa:16:3e:92:36:49, ethertype IPv4 (0x0800), length 98: 115.115.115.187 > 10.10.32.1: ICMP echo request, id 21802, seq 3, length 64
21:32:57.940958 fa:16:3e:a8:79:61 > fa:16:3e:92:36:49, ethertype IPv4 (0x0800), length 98: 115.115.115.187 > 10.10.32.1: ICMP echo request, id 21802, seq 4, length 64
21:32:58.940950 fa:16:3e:a8:79:61 > fa:16:3e:92:36:49, ethertype IPv4 (0x0800), length 98: 115.115.115.187 > 10.10.32.1: ICMP echo request, id 21802, seq 5, length 64

可以看到只有request,没有reply,继续再抓外网网卡的包

root@iptables:~# tcpdump -i eth1 icmp -en
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
21:32:42.263175 3c:8c:40:08:37:39 > fa:17:00:13:01:14, ethertype IPv4 (0x0800), length 98: 10.10.32.1 > 115.115.115.187: ICMP echo reply, id 21800, seq 1, length 64
21:32:43.261973 3c:8c:40:08:37:39 > fa:17:00:13:01:14, ethertype IPv4 (0x0800), length 98: 10.10.32.1 > 115.115.115.187: ICMP echo reply, id 21800, seq 2, length 64
21:32:44.261128 3c:8c:40:08:37:39 > fa:17:00:13:01:14, ethertype IPv4 (0x0800), length 98: 10.10.32.1 > 115.115.115.187: ICMP echo reply, id 21800, seq 3, length 64
21:32:45.261134 3c:8c:40:08:37:39 > fa:17:00:13:01:14, ethertype IPv4 (0x0800), length 98: 10.10.32.1 > 115.115.115.187: ICMP echo reply, id 21800, seq 4, length 64
21:32:46.261066 3c:8c:40:08:37:39 > fa:17:00:13:01:14, ethertype IPv4 (0x0800), length 98: 10.10.32.1 > 115.115.115.187: ICMP echo reply, id 21800, seq 5, length 64

看到这里,reply都在这里,原来是eth0=>gw=>eth1的节奏,仔细想想也是对的,eth0上的包通过snat源地址变成了外网地址,而namespace里网关本身也是通过snat能够访问外网的因此能够回ping包,所以表面上看好像还能够到网关,实际上reply和request走的是不同的路线

也许你要问,我的根据是什么,答案就是MAC地址

eth0网卡上源MAC地址其实是内网网卡的,可以对比ip a的结果;eth1网卡上目的MAC地址是外网网卡的,这样就肯定了上面的说法,除此之外,两个10.10.32.1的MAC地址不一致,原因就是request里对应的目的MAC地址是namespace里ha的,而reply里的源MAC地址就属于ha经过SNAT之后的qg所有 

 

发表评论