主题
EI 的完整行为画像
第 1 章已经把 EI 和 ED 最核心的差异实测出来了: 会话粒度和过滤行为。这一篇补齐剩下的部分 —— EI 独有的端口分配算法和每用户配额, 以及它们为什么是选 EI 的实际理由。
先回顾核心差异
text
┌──────────────┬────────────────────────┬────────────────────────┐
│ │ nat44-ed(端点相关) │ nat44-ei(端点无关) │
├──────────────┼────────────────────────┼────────────────────────┤
│ 会话键 │ 内网端 + 外网端(5 元组)│ 只有内网端(3 元组) │
│ 一个内网端口 │ 每个目的一条会话 │ 一条会话服务所有目的 │
│ 访问两个目的 │ │ │
│ 外部主机换源 │ 丢弃 │ 送达 │
│ 端口打进来 │ │ │
│ P2P 打洞 │ 不可行,需中继 │ 可行 │
│ 端口利用率 │ 高(同端口可对多目的复用)│ 低(一端口对所有目的占用)│
└──────────────┴────────────────────────┴────────────────────────┘这些差异都能在实验里复现:
bash
./labctl apply base 04 && ./labctl verify base 04命令不通用,每条都多一个 ei
这是上手 EI 时第一个绊脚石。两套插件的命令完全平行但互不通用:
| 用途 | nat44-ed | nat44-ei |
|---|---|---|
| 启用插件 | nat44 plugin enable | nat44 ei plugin enable |
| 地址池 | nat44 add address ... | nat44 ei add address ... |
| 接口地址 | nat44 add interface address ... | nat44 ei add interface address ... |
| 内外侧划分 | set interface nat44 in X out Y | set interface nat44 **ei** in X out Y |
| 静态映射 | nat44 add static mapping ... | nat44 ei add static mapping ... |
| 看会话 | show nat44 sessions | show nat44 ei sessions |
| 删会话 | nat44 del session ... external-host ... | nat44 ei del session ...(不需要 external-host) |
最容易踩的是接口那条
用 ED 的写法去配 EI,报错信息很不友好:
text
set interface nat44: add host-eth1 failed它不会告诉你"你应该加个 ei"。正确写法:
bash
vppctl set interface nat44 ei in host-eth1 out host-eth2删会话那一行的差异不是巧合
ED 删会话必须带 external-host,EI 不用 —— 因为EI 的会话键里压根没有外网端。 这个细节可以反过来当作判断依据:如果你不确定手上这台设备在跑哪个插件, 试一条不带 external-host 的 del session 就知道了。
EI 独有能力之一:端口分配算法
ED 的端口分配是写死的(保留优先,冲突才换)。EI 允许换算法:
bash
vppctl nat44 ei addr-port-assignment-alg <算法名> [参数]
vppctl show nat44 ei addr-port-assignment-algVPP 26.06 上实测可用的只有两个:
text
default 默认,端口保留优先
port-range <起> - <止> 把外部端口限定在指定范围文档里常提到的 map-e 在 26.06 上不可用
试这两个都会被拒:
text
nat44 ei addr-port-assignment-alg: unknown input 'map-e'
nat44 ei addr-port-assignment-alg: unknown input 'random'另外注意 port-range 必须带参数,光写算法名也会报 unknown input。
port-range 实测
应用配置
bash
./labctl reset base
./labctl apply base 08
./labctl verify base 08bash
vppctl nat44 ei addr-port-assignment-alg port-range 1024 - 2047text
NAT address and port: port-range
start-port 1024 end-port 2047连五次,看外部端口:
text
实测到的外部端口:1887 1330 1769 1844 1283
✓ 全部落在 1024-2047 内什么时候需要限制端口范围
text
✓ 和上游防火墙 / ACL 配合
只放行这一段端口,缩小暴露面
✓ 多台 NAT 设备共用同一个公网地址
各自分一段,互不冲突 —— 这是把一个地址切给多台设备用的办法
✓ 便于识别
抓包和日志里一眼认出"这是我们 NAT 出去的流量"代价是可用端口大幅减少
1024-2047 只有 1024 个端口。按人均 100 条并发会话算, 一个地址只够十来个用户 —— 而不限制时是几百个。
范围切得越窄,能撑的用户越少。这个账必须提前算, 不然上线后会以 out of ports 的形式爆出来。
EI 独有能力之二:每用户会话配额
这是 EI 在共享环境里最有价值的能力,ED 完全没有对应功能。
对比两个插件的启用参数就一目了然:
text
ED: nat44 plugin enable [sessions <n>] [inside-vrf <id>] [outside-vrf <id>]
^^^^^^^^^^^^ 只有全局上限
EI: nat44 ei plugin enable [sessions <n>] [users <n>] [user-sessions <n>]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
还能限制"每个用户占多少"为什么这很重要
ED 只有一个全局的会话上限。这意味着:
一个人可以把全楼的网搞坏,而且很难定位到是谁。
EI 的 user-sessions 给每个内网主机划了独立配额,一个人再狠也只能占自己那份。
实测
bash
vppctl nat44 ei plugin enable users 10 user-sessions 3让 h1 发 10 条不同源端口的流:
text
h1 发 10 条不同源端口的流(配额是 3)
NAT44 sessions:
-------- thread 0 vpp_main: 3 sessions --------
10.10.0.11: 3 dynamic translations, 0 static translations
✓ h1 只建成了 3 条会话,配额生效再让 h2 也发 10 条,验证配额是按用户独立的:
text
h2 也发 10 条流
NAT44 sessions:
-------- thread 0 vpp_main: 6 sessions --------
10.10.0.11: 3 dynamic translations, 0 static translations
10.10.0.12: 3 dynamic translations, 0 static translations
✓ h2 同样拿到 3 条 —— 配额按用户独立计算两个主机各占 3 条,互不影响。
被配额挡下的会话不记任何计数器
show errors 里看不到配额拒绝。这和会话表满(maximum sessions exceeded) 或端口耗尽(out of ports)都不一样 —— 那两个有明确的错误计数。
排查"某个用户老是连不上"时,只能对比:
bash
./labctl vppctl base show nat44 ei sessions看那个用户的 N dynamic translations 是不是正好卡在配额值上。
users 和 user-sessions 要一起规划
bash
nat44 ei plugin enable users 10 user-sessions 3
^^ ^^
最多几个用户 每人几条会话users 是用户表的容量。超过这个数量的新用户会被拒绝 —— 注意是拒绝新用户,不是挤掉老用户。所以 users 要按内网主机总数留足余量。
总容量粗算:users × user-sessions,且不能超过 sessions 全局上限。
EI 的会话表长什么样
EI 的会话显示是按用户聚合的,和 ED 的平铺列表完全不同:
bash
./labctl vppctl base show nat44 ei sessionstext
NAT44 sessions:
-------- thread 0 vpp_main: 6 sessions --------
10.10.0.11: 3 dynamic translations, 0 static translations
10.10.0.12: 3 dynamic translations, 0 static translations想看每条会话的细节要加 detail:
bash
./labctl vppctl base show nat44 ei sessions detailtext
10.10.0.11: 3 dynamic translations, 0 static translations
i2o 10.10.0.11 proto udp port 23456 fib 0
o2i 203.0.113.1 proto udp port 22324 fib 0
index 0
last heard 1502.54
total pkts 4, total bytes 230
dynamic translation对比 ED 的会话少了两样东西:
- 没有
external host—— 这就是端点无关的字面含义 - 没有 i2o / o2i flow 的 match+rewrite 明细 —— EI 的改写规则由键直接推导, 不需要预先算好存下来
还有一个好处:show nat44 ei addresses 会显示每个地址的端口占用:
text
NAT44 pool addresses:
203.0.113.1
tenant VRF independent
0 busy other ports
0 busy udp ports
0 busy tcp ports
0 busy icmp portsED 的 show nat44 addresses 没有这几行。想在 ED 下判断"哪个池地址快满了" 只能靠间接手段 —— 这是第 2 章提过的 ED 可观测性短板, 在 EI 这里不存在。
超时是同一套
EI 和 ED 共用同一组超时配置:
bash
vppctl show nat timeouts # 注意不是 show nat44 ei timeoutstext
udp timeout: 300sec
tcp-established timeout: 7440sec
tcp-transitory timeout: 240sec
icmp timeout: 60sec(show nat44 ei timeouts 也能看,显示同样的值。) 调整方式和第 2 章讲的完全一样。
小结
| EI 独有 | 说明 |
|---|---|
| 端口分配算法 | port-range <起> - <止>;26.06 上 map-e / random 不可用 |
| 每用户会话配额 | users N user-sessions M,防止单用户吃光会话表 |
| 每地址端口占用可见 | show nat44 ei addresses 带 busy ports 统计 |
| 会话高可用 | 见下一篇 |
| P2P 打洞可行 | 见第 1 章 |
| EI 的代价 | 说明 |
|---|---|
| 端口利用率低 | 一个外部端口一旦被占,对所有目的都被占 |
| 安全性弱 | 外部主机换源端口能打进来 |
| 功能少 | 没有 twice-NAT、负载均衡映射、VRF 多租户表 |
下一篇:会话高可用 —— EI 最有分量的独有能力。