Netfilter策略路由和uRPF

简介:
在Linux中,往往会出现一些奇怪的现象,如果你仅仅知道一些皮毛,那么这些现象将会让你抓耳挠腮,因为Linux往往遵循RFC建议而有时却不会保持持久的大众化实现,毕竟,Linux并不是一个人搞定的,特别是网络协议栈这一方面。uRPF这个概念很多人都知道,Linux的实现却很不一致,在Linux实现中,它和策略路由的点点滴滴值得说一番,我们分为以下4个关键点来说明,当然这4点并不是全部关于uRPF的:

1.策略路由和OUTPUT链

Linux的Netfilter实现5个HOOK点,其中OUTPUT点在路由之后,那么如果我们将如下的路由:
route add -net 192.168.188.0/24 gw 192.168.40.254
移植到策略路由:
ip rule add $标签1 tab new
ip route add 192.168.188.0/24 via 192.168.40.254 table new
route del -net  192.168.188.0/24
iptables -t mangle -A OUTPUT -XXX -j MARK --set-mark $标签1
那么当我们从本机发包到192.168.188.0/24的时候,得到的结果将是“路由不可达”。这是因为Linux的基于标签的策略路由是为“过路包”设计的,在本机发包进入任何Netfilter钩子点之前首先要经过IP路由,也就是说OUTPUT链在IP路由之后,此时任何的打标签策略都还没有被应用,因此就会出现上述的奇怪现象。

2.CONNMARK target和MARK target

在Linux Netfilter中,有CONNMARK和MARK两个target,其作用都是set-mark,那么这两个target有何不同呢?很简单,CONNMARK是为一个“连接”即conntrack打上一个mark,而MARK仅仅是为一个packet打上一个mark,对于CONNMARK,如果想让后续的包或者返回包也被打上mark,不必再进行一次新的iptables规则匹配,只需要restore-mark即可,而对于MARK,则不能这么做,因此它是不依赖ip_conntrack的。
        因此,考虑以下现象:
路由:
ip rule add $标签1 tab new
ip route add 192.168.188.0/24 via 192.168.40.254 table new
route del -net  192.168.188.0/24
iptables规则:
iptables -t mangle -A PREROUTING -i $内网口 -XXX -j MARK --set-mark $标签1
rp_filter配置:
sysctl -w net.ipv4.conf.$所有网卡.rp_filter=1
访问192.168.188.0/24,将发现返回包无法经过网关,为何呢?很简单,rp_filter为1,显然为严格uRPF,此时返回包的反向路由必须被查找到且和策略路由的结果一致,然而策略路由是无法被命中的,因此返回包没有命中任何iptables打标签的规则而没有被打标签,进而不命中策略路由...,如果将iptables中的MARK改为CONNMARK呢?也不行,还缺少一条:
iptables -t mangle -A PREROUTING -j CONNMARK restore-mark
才行,因此请注意,始终将上述规则放在所有规则的靠前的位置且在其后加上RETURN target的规则,可以:第一,免除很多基于mark的iptables规则查找;第二,可以避免由于uRPF而导致的奇怪问题。

3.标签策略路由和NOTRACK target

如果还是出现了奇怪的问题,那么看一下是不是NOTRACK target导致的呢?我们知道raw表是所有规则的最前面的,因此如果在raw表中被NOTRACK了,那么就别指望后面的任何mark规则起作用了,所有的基于mark的策略路由也将无效,更隐蔽的是uRPF验证失败导致的包不可达将很难被发现。

4.路由cache与rp_filter

在IP路由查找的时候,首先要查找路由cache,在Linux的实现中,查找路由cache的过程不涉及任何的uRPF(在ip_route_input_XXX中没有任何fib_validate_source的调用),因此如果系统中有反向包的路由cache,即使你设置了rp_filter为严格uRPF,并且还故意配置NOTRACK以及基于mark的正向包策略路由,那还是可以正常通讯的。


 本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1268962


相关文章
|
域名解析 Linux Shell
CentOS 7 执行 yum 命令失败问题的排查方法
本文主要为大家讲解CentOS 7系统中执行yum命令失败等常见问题的排查方法。
5439 0
CentOS 7 执行 yum 命令失败问题的排查方法
|
缓存 JavaScript 前端开发
Dockerfile全面指南:从基础到进阶,掌握容器化构建的核心工具
Dockerfile 是容器化开发中的关键工具。理解并掌握其使用方式,不仅能提高开发效率,还能让你的应用具备更强的可移植性和灵活性。通过优化配置和合理安排构建步骤,可以打造更轻量、更高效的容器镜像。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
KVM 虚拟化
KVM的热添加技术之网卡管理
文章详细介绍了如何在KVM虚拟机中进行网卡的热添加和热移除操作,包括查看环境、添加和移除网卡的命令,以及如何指定不同的虚拟网卡模型,同时提供了一些操作时的注意事项和永久配置的方法。
447 3
KVM的热添加技术之网卡管理
|
SQL 关系型数据库 MySQL
SQL中,可以使用 `ORDER BY` 子句来实现排序功能
【10月更文挑战第26天】SQL中,可以使用 `ORDER BY` 子句来实现排序功能
1713 6
|
Web App开发 前端开发 JavaScript
前端必备的浏览器调试技巧
【7月更文挑战第18天】 Chrome开发者工具是前端调试的关键,包括快捷键Ctrl+Shift+I/Cmd+Option+I打开它,DOM和CSS调试如编辑元素、样式,JS调试如断点、条件断点和监视变量,网络请求分析,性能评估如Lighthouse和性能面板,及截图、模拟设备等实用技巧,助力开发者提升效率。
486 1
|
监控 Linux 测试技术
edac是检测什么的,和centos内存条损害检测工具
【6月更文挑战第1天】edac是检测什么的,和centos内存条损害检测工具
919 2
|
Android开发
Android 获取Wifi开关状态、控制Wifi开关
Android 获取Wifi开关状态、控制Wifi开关
688 0
|
弹性计算 虚拟化 异构计算
阿里云gpu云服务器最新收费标准与优惠价格表参考
阿里云gpu云服务器最新收费标准与优惠价格表参考
1037 0
|
负载均衡 算法 Linux
深入理解Linux内核进程CPU负载均衡机制(下)
深入理解Linux内核进程CPU负载均衡机制
echarts多种特殊柱状图表实现的方式
这里是对echarts特殊柱状图表实现的方式记录
668 0

热门文章

最新文章

下一篇
开通oss服务