Skip to content

uRPF:不用维护名单的防欺骗

有状态 ACL 那一篇结尾讲了个坏消息: VPP 的 macip ACL(IP+MAC 绑定防欺骗)在三层接口上不工作。

这一篇讲三层场景下的正解。而且它比 macip 更好用 —— 不需要维护任何名单

源地址欺骗为什么是 NAT 的问题

伪造源地址通常被当作安全话题,但它对 NAT 有很具体的伤害。 实验里可以直接看到:

关掉 uRPF,用一个不属于本网段的地址发包

bash
./labctl reset base
./labctl apply base 16
./labctl verify base 16
text
── 2) 关掉 uRPF:伪造地址畅通无阻,而且 NAT 会为它建会话 ──
  NAT 为伪造地址 192.0.2.99 建的会话数:1
✓ 确认:没有 uRPF 时,伪造流量会被正常翻译并转发

三个后果:

text
  · 伪造流量占用会话表条目和端口配额
    —— 第 2 章辛苦规划的容量被它白白吃掉

  · DET44 的可追溯性失效
    —— 第 4 章那套"一条命令反查用户"的前提是源地址可信。
       源地址能伪造的话,反查出来的"内网地址"本身就是假的

  · 你的 NAT 成了反射放大的跳板
    —— 攻击者用受害者的地址做源,回包全打到受害者身上,
       而日志指向的是伪造源

原理:这个源地址能不能从这个接口回去

uRPF(Unicast Reverse Path Forwarding)的判据一句话就说完:

text
  收到一个包 →  拿它的**源地址**去查路由表
              →  看查出来的出接口是不是**收到它的那个接口**

对得上说明源地址合理(去和回走同一条路),对不上说明可疑。

不需要任何名单。 路由表本来就在那儿,uRPF 只是反过来用一次。

三种模式

bash
set urpf [ip4|ip6] [rx|tx] [off|strict|loose] <> [table <>]
text
  ┌────────┬──────────────────────────────────────────────┐
  │ 模式    │ 判据                                          │
  ├────────┼──────────────────────────────────────────────┤
  │ off    │ 不检查                                        │
  │ strict │ 到源地址的路由**必须指回收到它的这个接口**        │
  │ loose  │ 到源地址**有路由就行**,方向不管                 │
  └────────┴──────────────────────────────────────────────┘

实验用两个伪造地址把差别测出来:

text
  源地址          VPP 路由表里的情况              off    strict   loose
  ─────────────  ────────────────────────────  ─────  ──────  ──────
  192.0.2.99     完全没有路由                    放行    拦下     拦下
  203.0.113.50   有路由,但方向是外网口 eth2      放行    拦下     放行

第二行是区分 strict 和 loose 的关键:地址本身是可路由的, 但它出现在了错误的接口上。strict 认为这不合理,loose 觉得无所谓。

什么时候用哪个

strict 会在非对称路由的网络里误伤合法流量

非对称路由是指"进来的接口和回去的接口不是同一个"。 这在多出口、BGP 多归属的网络里是正常现象,不是故障。

strict 模式会把这类合法流量全部丢掉。

text
  ✓ strict 适合                        ✓ loose 适合
  ──────────────────────────────      ──────────────────────────────
  接入侧 / 用户侧接口                   骨干、对等互联侧
  用户网段是确定的、单一路径的            多出口、BGP 多归属
  典型:宽带接入、企业内网汇聚            典型:运营商边界路由器

  这也是 BCP 38 / RFC 2827 的建议:
  **在最靠近源头的地方做严格检查**,越往骨干越宽松。

它在 feature arc 上的位置很讲究

bash
./labctl vppctl base show interface features host-eth1
text
ip4-unicast:
  ip4-rx-urpf-strict          ← uRPF 在最前面
  ip4-sv-reassembly-feature
  nat-pre-in2out

uRPF 排在所有东西前面,连分片重组和 NAT 都在它后面。

这个顺序是有道理的:伪造流量在消耗任何处理资源之前就被丢掉 —— 不重组、不查会话表、不分配端口。对抗洪泛时这一点很关键。

对照第 9 章的顺序表,完整的入向次序是:

text
  ip4-rx-urpf-*  →  ip4-sv-reassembly  →  policer-input  →  acl-plugin-in  →  nat-pre-*

计数器

bash
./labctl vppctl base show errors | grep -i urpf
text
  1  ip4-rx-urpf-strict  uRPF Drop  error

节点名里直接带着模式(strict / loose),所以看计数器就知道 当前生效的是哪种模式 —— 不用另外去查配置。

没有 show urpf 命令

bash
vppctl show urpf        # unknown input

想确认某个接口开没开、开的是哪个模式,只能看 feature arc:

bash
vppctl show interface features <> | grep urpf

和 macip ACL 的对照

text
  ┌──────────────┬────────────────────────┬──────────────────────────┐
  │              │ macip ACL              │ uRPF                     │
  ├──────────────┼────────────────────────┼──────────────────────────┤
  │ 判据          │ IP 和 MAC 的绑定名单     │ 路由表反查                │
  │ 需要维护      │ **每台主机一条规则**     │ 不需要                    │
  │ 主机变动      │ 要改名单                │ 无感                      │
  │ 三层接口      │ **不工作**(本教程实测) │ 正常                      │
  │ 防护粒度      │ 精确到单台主机           │ 精确到网段                 │
  └──────────────┴────────────────────────┴──────────────────────────┘

uRPF 的粒度粗一些 —— 它拦不住"同网段内主机 A 冒充主机 B", 因为两者的源地址都能从这个接口回去。

要防同网段内的冒充,正确的位置是交换机的端口安全 (port security / DHCP snooping + IP source guard),而不是路由器。 每一层管好自己那一层。

小结

解决什么源地址欺骗,不需要维护任何名单
命令set urpf ip4 rx strict|loose|off <接口>
strict路由必须指回本接口;适合接入侧
loose有路由就行;适合多出口、非对称路由的骨干侧
位置feature arc 最前面,比 NAT 和重组都早
计数器ip4-rx-urpf-strict / uRPF Drop,节点名自带模式
对 NAT 的意义保护会话表容量;保住 DET44 溯源的可信前提
管不了的同网段内互相冒充 —— 那是交换机端口安全的事

第 8 章到此结束。ACL 这一块的全貌:

text
  基础     有序规则 + 隐式 deny,计数器是诊断第一站
  有状态   permit+reflect,会话查找先于规则匹配
  转发     ABF,用 ACL 匹配结果选下一跳
  防欺骗   uRPF,路由表反查,零维护
  不可用   macip(三层接口上分类表匹配不到)

实验环境基于 netlab + containerlab + VPP 26.06