rp_filter和fwmark base 策略路由

  • 前提:

先说下网络环境, 这边架了个tunnel, 之前无论是全部走tunnel 还是部分目标IP走tunnel都没有问题, 实现如下

ip rule add from 10.4.224.100 table routeTableName

ip route add $line via 172.16.172.1 dev tunnel (table routeTableName)

  • 新的需求: 根据部分协议,比如TCP来走这个路由, 实现办法是

iptables -t mangle -A PREROUTING -s 10.4.224.100/32 -d 10.0.0.0/8 -p tcp -m tcp -j MARK --set-xmark 3

ip rule add from 10.4.224.100 fwmark 3 table tun

在这个路由表使用的策略路由则不生效了, 相同的语句导致无法访问网络了

ip route add $line dev tunnel table tun

  • 听包看看:

在tunnel的对端服务器能看到对端回包后后续传输失败了

在本地linux 网关的tunnel听包可以看到回包也过来了

在本地linux 网关的内网听包能看到只有客户端的发包没有收到回包

那么问题就发生在tunnel 到 内网网卡这一段, 包要么是路由不对,要么是被drop了, 由于之前是可以直接访问的, 那么路由的可能性很小

  • 问题定位检测:

使用如下方式确认回包是否被drop了,配置:

sysctl -w net.ipv4.conf.default.log_martians=1
sysctl -w net.ipv4.conf.all.log_martians=1

发现有如下的检测日志:

IPv4: martian source 10.4.224.100 from 122.13.86.120, on dev tunnelX
IPv4: martian source 10.4.224.100 from 122.13.86.120, on dev tunnelX

这里由于是reverse path filter, 原理是把源和目标调换确认该设备接口是否是最佳接口, 显然回包被认为是不合适的包, 被过滤掉了

  • 问题解决:

问题就简单了, 设置rp_filter即可

sysctl -w net.ipv4.conf.default.rp_filter=2

sysctl -w net.ipv4.conf.all.rp_filter=2

  • 问题解析:

那么问题来了, 为什么原来的简单策略路由就可以, 加了–set-mark 3后, 基于fwmark的就不行呢?

从听包可以看到原有的策略路由是可以正常返回的, 包括tunnel和内网网卡

推测很大可能是因为我们使用了 ip rule add from 10.4.224.100/32 table routeTableName的方式能让rp_filter检测到回程数据包的reverse path是合理的

而rp_filter大概率是无法识别到fmwark的策略路由的, 检测的时候发现回包数据不合理被drop了

如何确认以上这番推测是否合理呢? 这里做了个测试, 从tunnel对端的机器使用tunnel接口ping 10.4.224.100

ping 10.4.224.100 -I tunnelX
PING 10.4.224.100 (10.4.224.100) from 172.16.172.1 tunnelX: 56(84) bytes of data.
^C
--- 10.4.224.100 ping statistics ---
77 packets transmitted, 0 received, 100% packet loss, time 77858ms

查看本地linux的日志可以看到数据包被drop了

Mar 18 09:37:25 gw kernel: IPv4: martian source 10.4.224.100 from 172.16.172.1, on dev tunnelX
Mar 18 09:37:25 gw kernel: IPv4: martian source 10.4.224.100 from 172.16.172.1, on dev tunnelX

由于是reverse path 校验嘛, 给它加个路由

ip route add 172.16.0.0/16 dev tunnelX table myRouteTable

于是, 通了

ping 10.4.224.100 -I tunnelX
PING 10.4.224.100 (10.4.224.100) from 172.16.172.1 tunnelX: 56(84) bytes of data.
64 bytes from 10.4.224.100: icmp_seq=1 ttl=62 time=2.22 ms
64 bytes from 10.4.224.100: icmp_seq=2 ttl=62 time=37.9 ms

至于为什么ping值这么飘忽…因为这个是wifi的IP啊, 我去毒打wifi管理员了



  • 背景资料:

关于rp_filter的问题可以参考本站这个链接:

/usr/share/doc/kernel-doc-2.6.32/Documentation/networking/ip-sysctl.txt rp_filter -

INTEGER 0 - No source validation. 不检测源

1 - Strict mode as defined in RFC3704 Strict Reverse Path Each incoming packet is tested against the FIB and if the interface is not the best reverse path the packet check will fail. By default failed packets are discarded.

严格检测模式

2 - Loose mode as defined in RFC3704 Loose Reverse Path Each incoming packet's source address is also tested against the FIB and if the source address is not reachable via any interface the packet check will fail.

松散检测模式, 只要有一个设备接口有这个地址就可以

Current recommended practice in RFC3704 is to enable strict mode to prevent IP spoofing from DDos attacks. If using asymmetric routing or other complicated routing, then loose mode is recommended. The max value from conf/{all,interface}/rp_filter is used when doing source validation on the {interface}. Default value is 0. Note that some distributions enable it in startup scripts.

  • 参考资料:

https://blog.csdn.net/dog250/article/details/7947705

发表评论