2017-06-23 23:08
-----
通过 echo 1 > /proc/sys/net/ipv4/ip_forward 开启 ip_forward 之后,是否对于目的IP可达的报文都会转发呢?不是!开启 ip_forward 的主机在转发报文前还会检查该报文的源IP是否也可达,这个是通过如下实验得出的。(还需要找个时间把源码找出来验证下)
实验环境及拓扑如下:
6A 为 CentOS6,内核 2.6.32
7A 和 7B 为 CentOS 7,内核 3.10.0
vmware 上 “仅主机模式“ 建立两个虚拟网络 192.168.20.0/24 (vmnet2) 和192.168.10.0/24 (vmnet1)
实验过程中 iptables 为空,且 未启用 selinux
各主机interface ip 通过 DHCP 获得,如下:
6A 上 interface ip 为 192.168.20.131/24
7B 上 interface ip 为 192.168.20.129/24 和 192.168.10.130/24
7A 上 interface ip 为 192.168.10.129/24
各主机上配置如下:
6A:
ip route add default via 192.168.20.129 //添加默认路由
7B:
echo 1 > /proc/sys/net/ipv4/ip_forward //开启转发功能
7A:
ip route add default via 192.168.10.130 //添加默认路由
ip add add 1.1.1.1/32 dev lo:0 //添加 loopback IP
测试过程:
7A 上 ping 192.168.20.131,结果正常,没有问题,因为 ICMP request 报文的源地址是 7A 的 interface ip。但若执行 ping -I 1.1.1.1 192.168.20.131 指明使用 1.1.1.1 为源IP发送 ICMP request,则无法 ping 通。在 vmnet1 上抓包,发现 ICMP request ,但在 vmnet2 上抓包,没有发现转发过来的 ICMP request。
在 7B 上通过 ip route add 1.1.1.1 via 192.168.10.129 添加到 7A 上 loopback 的路由后,再在 7A 上执行 ping -I 1.1.1.1 192.168.20.131 则可以 ping 通。由此推测 Linux 主机开启 ip_forward 后,若要转发某个报文,不仅仅要求该报文目的IP可达,源IP也要可达才行。可能是协议栈的设计者考虑到对于7B来说若发送方(本例中的1.1.1.1)不可达的情况下将报文转发给6A,该报文的响应报文到达7B后也是要丢弃的(因为1.1.1.1作为目的IP不可达),不如提前就丢弃。
备注:需要找个时间看看协议栈源码是否在转发前确实做了源IP的检查