作为IP路由的一种补充,uRPF(单播反向路径转发)可谓非常有用,它认证了IP数据报的源地址,在一定程度了保护了网络的安全,比如有效防止了洪泛攻击。然而直到Linux内核的2.6的高版本版本,Linux只能实现严格的uRPF,这是由fib_validate_source函数来完成的,具体配置在/proc/sys/net/ipv4/conf/$dev/rp_filter,对于Cisco上很简单的松散的uRPF,Linux却无能为力,kernel 2.6的高版本可以为/proc/sys/net/ipv4/conf/$dev/rp_filter设置3个值,分别为不检查,严格uRPF,松散uRPF。kernel 3.3增加了rpfilter机制,将uRPF从协议栈移到了Netfilter,使得Linux可以在协议栈之外实现严格/松散uRPF,然而即便如此,对于VRF(虚拟路由转发),Linux还是没有实现,不过在rpfilter的基础上,这个VRF的实现应该很简单。
        反向路由查找并非那么简单,因为需要考虑策略路由的问题,这一切从何道来呢?rpfilter技术作用在Netfilter的PREROUTING这个HOOK点上,这是合理的,因为必须在标准路由之前进行反向路径查询,以保证没有任何数据从被拒绝的反向路径发出,这里主要是为了禁止ICMP包的回发,然而在PREROUTING这个点上,目标网卡是不知道的,因此也就不能像标准路由中的fib_validate_source那样设置flowi4的iif,既然rpfilter的目的只是裁决一下反向路径的出口,那么其入口就是无关紧要的了,并且我们知道,本机loopback口的通信是可信的,那么就将反向路径查询中的flowi4的iif设置成loopback即可,然而这还有问题,那就是策略路由的问题了,如果我们不查找策略路由表,就会漏掉在策略路由表中的条目而导致正向包被丢弃,而如果想查找策略路由表,由于我们将iif设置成了loopback,就可能会因为rule的iif不匹配而错过:

static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,                            struct flowi *fl, int flags) {          int ret = 0;          if (rule->iifindex && (rule->iifindex != fl->flowi_iif))                  goto out;          if (rule->oifindex && (rule->oifindex != fl->flowi_oif))                  goto out;          if ((rule->mark ^ fl->flowi_mark) & rule->mark_mask)                  goto out;          ret = ops->match(rule, fl, flags); out:          return (rule->flags & FIB_RULE_INVERT) ? !ret : ret; }

策略路由中的FIB_RULE_INVERT标志和rpfilter中的XT_RPFILTER_INVERT标志是相互独立的两个取反标志,然而代表的含义基本一致,这可以让我们配置出各种组合,也就是说,你可能需要单独的配置一些针对正方向策略路由的反方向策略路由,是不是有点VRF的意思啊!
        rpfilter的核心代码如下:

1.match函数:

static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) {        const struct xt_rpfilter_info *info;        const struct iphdr *iph;        struct flowi4 flow;        bool invert;         info = par->matchinfo;        invert = info->flags & XT_RPFILTER_INVERT;         if (par->in->flags & IFF_LOOPBACK)                return true ^ invert;         iph = ip_hdr(skb);        if (ipv4_is_multicast(iph->daddr)) {                if (ipv4_is_zeronet(iph->saddr))                        return ipv4_is_local_multicast(iph->daddr) ^ invert;                flow.flowi4_iif = 0;        } else {                flow.flowi4_iif = dev_net(par->in)->loopback_dev->ifindex;        }         flow.daddr = iph->saddr;        flow.saddr = rpfilter_get_saddr(iph->daddr);        flow.flowi4_oif = 0;        flow.flowi4_mark = info->flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0;        flow.flowi4_tos = RT_TOS(iph->tos);        flow.flowi4_scope = RT_SCOPE_UNIVERSE;         return rpfilter_lookup_reverse(&flow, par->in, info->flags) ^ invert; }

2.路由查找以及结果判断逻辑:

static bool rpfilter_lookup_reverse(struct flowi4 *fl4,                                const struct net_device *dev, u8 flags) {        struct fib_result res;        bool dev_match;        struct net *net = dev_net(dev);        int ret __maybe_unused;         if (fib_lookup(net, fl4, &res))                return false;         if (res.type != RTN_UNICAST) {                if (res.type != RTN_LOCAL || !(flags & XT_RPFILTER_ACCEPT_LOCAL))                        return false;        }        dev_match = false; #ifdef CONFIG_IP_ROUTE_MULTIPATH        for (ret = 0; ret < res.fi->fib_nhs; ret++) {                struct fib_nh *nh = &res.fi->fib_nh[ret];                 if (nh->nh_dev == dev) {                        dev_match = true;                        break;                }        } #else        if (FIB_RES_DEV(res) == dev)                dev_match = true; #endif        if (dev_match || flags & XT_RPFILTER_LOOSE)                return FIB_RES_NH(res).nh_scope <= RT_SCOPE_HOST;        return dev_match; }

虽然基于Netfilter的rpfilter比内置的源地址判断更合理,但是由于Linux协议栈以及Netfilter本身的机制,还是有一些副作用的。

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

Netfilter的rpfilter技术-Linux的uRPF相关推荐

  1. 防火墙软件Netfilter之包过滤技术(转)

    防火墙软件Netfilter之包过滤技术(转)[@more@] 如果您不知道什么是IP地址.网络地址.网络掩码.路由或者DNS,那么,请先阅读相关的网络基础书籍. 1.什么是包过滤(Packet Fi ...

  2. 小女生的Linux技术~~~Linux常识~~21-30

    小女生的Linux技术~~~Linux常识~~21-30 Q21 如何查看当前用户的系统行为? A: 使用命令w查看当前用户的系统行为, w root Q22 如何查看曾经登录系统的用户名 ? A:使 ...

  3. Linux请求调页技术,linux零页技术.doc

    linux零页技术 Linux 中的零拷贝技术,第 1 部分 概述 黄 晓晨, 软件工程师, IBM 黄晓晨,IBM system Z 自动化技术支持软件工程师. 冯 瑞, 软件工程师, IBM 冯瑞 ...

  4. 小女生的Linux技术~~~Linux常识~~

    小女生的Linux技术~~~Linux常识~~1-10 任. http://linuxgirl.blog.51cto.com/1910230/372798 Q1 Linux的开发者是谁?--A:芬兰大 ...

  5. 百利而无一害的技术——Linux

    我相信绝大多数人都是先接触windows系统环境的,无论是在家里还是在学校上计算机课程的时候,按开机键后都会首先进入windows系统的.还记得小时候学习了一些电脑的基本知识,打字,还有打字游戏之类的 ...

  6. 网卡绑定技术linux c,Linux多网卡绑定

    为什么要使用多网卡绑定技术呢?我们知道如果使用一块网卡进行网络数据传输时其速度是有限的,即使是千兆网卡,其速度也是有限制的,我们为了提高带宽,我们可以将多块物理网卡绑定成一块逻辑网卡,这样网卡的速率就 ...

  7. linux目录隐藏技术,Linux环境下的高级隐藏技术

    摘要:本文深入分析了Linux环境下文件.进程及模块的高级隐藏技术,其中包括:Linux可卸载模块编程技术.修改内存映象直接对系统调用进行修改技术,通过虚拟文件系统proc隐藏特定进程的技术. 隐藏技 ...

  8. linux 端口限速技术,linux下如何实现对每个IP进行限制带宽??

    linux下如何实现对每个IP进行限制带宽?? (2011-09-01 01:03:54) 标签: 杂谈 linux下如何实现对每个IP进行限制带宽??redhat linux服务器,最近发现单位的网 ...

  9. 云计算底层技术--linux上的虚拟网络设备

    Linux 用户想要使用网络功能,不能通过直接操作硬件完成,而需要直接或间接的操作一个 Linux 为我们抽象出来的虚拟网络设备来完成. 一个常见的情况是,系统里装有一个硬件网卡,Linux 会在系统 ...

  10. rhel系统启动过程_技术|Linux 开机引导和启动过程详解

    你是否曾经对操作系统为何能够执行应用程序而感到疑惑?那么本文将为你揭开操作系统引导与启动的面纱. 理解操作系统开机引导和启动过程对于配置操作系统和解决相关启动问题是至关重要的.该文章陈述了 GRUB2 ...

最新文章

  1. 在CentOS 6.3 64bit上安装tsar并监控Apache Traffic Server
  2. redis 常用配置
  3. arm服务器配置信息,ARM板 web服务器交叉编译及配置
  4. 嘿,老李,又在写 BUG 呢?
  5. python画不出来图是什么原因-完美解决ARIMA模型中plot_acf画不出图的问题
  6. 感知器 Perceptron
  7. 算法学习之路|称量硬币(模拟)
  8. mysql批量更新后返回id_如何批量插入Mysql并取得各自的递增ID
  9. php document.write,在JS中有关document.write()的用法(详细教程)
  10. NgRx 和 Angular CLI 版本不一致的错误
  11. 在新的固态硬盘只装ubuntu16.04系统,重启后无启动项解决方案
  12. javascript高级程序设计 学习笔记 第五章 上
  13. 计算机辅助外文文献,计算机辅助设计建筑CAD论文中英文对照资料外文翻译文献.doc...
  14. 修改linux下默认的python版本
  15. JSP三大指令、七大动作、九大对象
  16. 1121: [POI2008]激光发射器SZK
  17. Ubuntu安装酷的桌面监控陈程序Conky
  18. listview 刷新某一个item
  19. 【转】中国人唯一不认可的成功——就是家庭的和睦,人生的平淡
  20. 投身数字化,助力智能化

热门文章

  1. python将数据写入txt文本文件
  2. html语言中下拉表单,html实现下拉菜单
  3. 基于C++的菜鸟驿站
  4. IIS 部署的网站无法启动
  5. CAN波特率计算公式
  6. 执行力强的人九个特点
  7. 如何批量将多个 Txt、Json、Html 以及记事本等文本文档快速合并成一个文档
  8. Ribbon界面开发(C++)
  9. 分享2个java j2ee培训的ppt
  10. 内存卡 android 刷机教程,怎样用卡刷包刷机?安卓手机通用刷机包卡刷教程