主题
接口地址伪装
第 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 # 指定内外侧 VRFnat44 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 addresstext
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 nattext
n nat44-ed-out2in-slowpath no translation errorno translation 就是这个症状的签名 —— 包走进了 out2in 分支但查不到会话。
看到 no translation 先想三件事
- 内外侧配反了(本节的情况)
- 外部主机主动连进来,但没有对应的静态映射 —— 这是正常拒绝,不是故障
- 会话已经老化,但对端还在发包 —— 见会话老化
恢复:
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 |
下一篇:用独立地址池扩容。