Skip to content

接口地址伪装

第 2 章开始,每一篇的结构都一样:这个特性解决什么问题 → 怎么配 → 实测验证 → 什么时候不该用它

这一篇讲最基础的形态:直接借用出接口自己的地址来做转换。

解决的问题

你只有一个公网地址,而且这个地址就配在设备的出接口上(家用宽带、云主机的弹性 IP 都是这样)。 你不想、也没法再单独规划一段地址池。

配置

应用配置

bash
./labctl reset base
./labctl apply base 01

三条命令:

bash
vppctl nat44 plugin enable
vppctl nat44 add interface address host-eth2
vppctl set interface nat44 in host-eth1 out host-eth2

逐条解释

nat44 plugin enable

启用 NAT44-ED 插件。可以带参数调容量:

bash
nat44 plugin enable sessions 1000000        # 每线程会话上限,默认 64512
nat44 plugin enable inside-vrf 10 outside-vrf 20   # 指定内外侧 VRF

nat44 add interface address host-eth2

host-eth2 这个接口加入地址池 —— 注意加的是接口,不是具体地址。 这带来一个实用的好处:接口地址变了,NAT 自动跟随

云上的弹性 IP 重新绑定、宽带 DHCP 续约拿到新地址,都不需要动 NAT 配置。 如果写死成 nat44 add address 203.0.113.1,地址一变就得手工改。

set interface nat44 in host-eth1 out host-eth2

VPP NAT 模型的核心。给接口贴"内侧 / 外侧"标签,NAT 节点据此决定包走哪个分支:

text
  包从 host-eth1(in)进来   →  nat-pre-in2out  →  nat44-ed-in2out    改源地址
  包从 host-eth2(out)进来  →  nat-pre-out2in  →  nat44-ed-out2in    查表还原目的地址
  包从没贴标签的接口进来      →  不经过 NAT 节点,正常路由

和 iptables 的思维差异

iptables 里"哪些流量做 NAT"是靠规则匹配(-s 10.0.0.0/8 -o eth0 -j MASQUERADE)。 VPP 里是接口先贴标签,然后所有从该接口进来的流量都进 NAT 处理弧。

想只对部分内网流量做 NAT?不能靠 NAT 配置实现,得用 ACL 或策略路由先分流。 这个模型更死板,但推理起来简单 —— 不会出现"规则顺序写反了"这类问题。

验证

跑自检

bash
./labctl verify base 01

通了

text
PING 203.0.113.11 (203.0.113.11): 56 data bytes
64 bytes from 203.0.113.11: seq=0 ttl=63 time=0.217 ms
64 bytes from 203.0.113.11: seq=1 ttl=63 time=0.168 ms
64 bytes from 203.0.113.11: seq=2 ttl=63 time=0.098 ms

3 packets transmitted, 3 packets received, 0% packet loss

配置 NAT 之前这里是 100% 丢包,因为 s1 没有回内网的路由。现在 s1 的路由表一个字都没改, 变的只是它收到的包长什么样。

外网看到的是什么

text
  内网真实来源            外网看到的来源
  ─────────────────────   ─────────────────────
  10.10.0.11 (h1)         203.0.113.1:39637
  10.10.0.12 (h2)         203.0.113.1:45381

两台主机共用一个地址,靠端口区分。这就是 NAPT。

配置检查

bash
./labctl vppctl base show nat44 interfaces
./labctl vppctl base show nat44 interface address
text
NAT44 interfaces:
 host-eth1 in
 host-eth2 out
NAT44 pool address interfaces:
 host-eth2

三个必看点

  • show nat44 interfaces 里 in / out 都在,且没配反
  • show nat44 interface address 里有出接口
  • 「你是谁」服务返回的地址是出接口地址,不是内网地址

排错:配反了会怎样

这是新手最常见的错误,值得亲手制造一次。

把内外侧配反

bash
./labctl vppctl base set interface nat44 in host-eth1 out host-eth2 del
./labctl vppctl base set interface nat44 in host-eth2 out host-eth1
ssh chenzhong@192.168.49.182 \
  'docker exec clab-natbase-h1 ping -c 2 -W 2 203.0.113.11'

结果是不通。因为现在 h1 的包从 host-eth1 进来,而 host-eth1 被标成了 out, 于是走 out2in 分支:VPP 拿这个包去会话表里查"有没有对应的内网主机",查不到,丢弃。

bash
./labctl vppctl base show errors | grep -i nat
text
  n  nat44-ed-out2in-slowpath   no translation   error

no translation 就是这个症状的签名 —— 包走进了 out2in 分支但查不到会话。

看到 no translation 先想三件事

  1. 内外侧配反了(本节的情况)
  2. 外部主机主动连进来,但没有对应的静态映射 —— 这是正常拒绝,不是故障
  3. 会话已经老化,但对端还在发包 —— 见会话老化

恢复:

bash
./labctl reset base && ./labctl apply base 01

什么时候不该用接口地址伪装

text
  ✓ 适合                            ✗ 不适合
  ────────────────────────────      ────────────────────────────────
  只有一个公网地址                   用户多,一个地址的端口撑不住
  地址是动态的(DHCP / 云弹性 IP)    需要按租户/VRF 分配不同地址
  小型网关、实验环境                 需要 twice-NAT(源和目的都要改)
  配置越简单越好                     需要地址池的负载分担

最主要的限制是端口容量。一个地址约 64512 个可用端口,按人均 100 条并发会话算, 大概撑几百个用户。超过这个规模就要上地址池

另一个限制容易被忽略:转换地址和设备管理地址是同一个。 抓包时你会看到 NAT 后的业务流量和设备自己的管理流量(SSH、SNMP、路由协议) 混在同一个地址上,排障时要额外分辨。地址池能把这两类流量分开。

小结

命令nat44 add interface address <出接口>
优点配置最简单;接口地址变化时自动跟随
缺点容量受限于单地址端口数;与管理流量混用同一地址
典型场景家用网关、云主机单弹性 IP、实验环境
常见错误内外侧标签配反 → no translation

下一篇:用独立地址池扩容

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