路由、防火墙与 NAT:用真实连接定位拦截点

验证:未记录
适用版本
未记录
验证范围
尚未登记验证记录。

目标:分别证明“有路由”“允许转发”“地址转换”三件事。需要 Linux 的 nftables、conntrack、iproute2、curl、Python 3;Ubuntu 安装:sudo apt-get install -y nftables conntrack iproute2 curl python3。

1. 先建立已通的网络#

下载 lab.sh、filter.nft、nat.nft。若基础实验还存在,先 sudo bash lab.sh cleanup。

sudo bash lab.sh connected
sudo ip netns exec lr-app curl --noproxy '*' --fail --max-time 3 http://10.20.0.10:8080/health

应用 10.10.0.10 → 路由器 10.10.0.1 / 10.20.0.1 → 后端 10.20.0.10:8080。connected 模式已加双向路由并开启实验路由器转发。

2. 有路由,但 FORWARD 可以拒绝#

sudo ip netns exec lr-router nft -c -f filter.nft
sudo ip netns exec lr-router nft -f filter.nft
sudo ip netns exec lr-router nft -a list table inet route_lab
sudo ip netns exec lr-app curl --noproxy '*' --fail --max-time 3 http://10.20.0.10:8080/health
# 插入一条优先丢弃规则,模拟发布规则错误。
sudo ip netns exec lr-router nft insert rule inet route_lab forward tcp dport 8080 counter drop
sudo ip netns exec lr-app curl --noproxy '*' --connect-timeout 2 --max-time 3 http://10.20.0.10:8080/health
sudo ip netns exec lr-router nft -a list chain inet route_lab forward

第二次 curl 应超时,新增 drop 规则计数增加;ip route get 仍正确。复制该条 drop 的实际 handle,仅删除它后重试:

export DROP_HANDLE='REPLACE_HANDLE_FROM_PREVIOUS_OUTPUT'
sudo ip netns exec lr-router nft delete rule inet route_lab forward handle "$DROP_HANDLE"
流量 常见过滤链
发给路由器自身服务 INPUT
路由器本机程序发出 OUTPUT
经路由器去另一台主机 FORWARD;放行 INPUT 不会放行它

配套规则默认拒绝转发,仅允许应用到后端 8080 的新连接和 established,related 回包。路由器不是云安全组;多张 nft base chain 同时存在时,一处 accept 也不保证后续链不会 drop。nftables 手册

3. SNAT:后端没有回程,为什么还能成功#

SNAT(Source NAT,源地址转换)改变源地址;DNAT(Destination NAT,目标地址转换)改变目标地址。NAT 不是访问授权,仍要通过过滤链。

sudo ip -n lr-db route del 10.10.0.0/24 via 10.20.0.1
# 此时原始路由方式应超时,后端不知道怎么回复 10.10.0.10。
sudo ip netns exec lr-app curl --noproxy '*' --connect-timeout 2 --max-time 3 http://10.20.0.10:8080/health
sudo ip netns exec lr-router nft -c -f nat.nft
sudo ip netns exec lr-router nft -f nat.nft
sudo ip netns exec lr-app curl --noproxy '*' --fail --max-time 3 http://10.20.0.10:8080/health
sudo ip netns exec lr-router conntrack -L -p tcp

预期恢复成功:后端看到的来源变成 10.20.0.1,这个地址直连可达;回包经 conntrack 反向转换,再回到应用。代价是后端失去原始网络源地址;有条件时优先设计正确回程,不为掩盖错误随意加 NAT。

SNAT 适合已知固定出口地址;masquerade 使用出口接口地址,常用于动态地址。一个连接建立后,后续包使用已记录的映射;修改 NAT 规则不会立刻改写已有连接。排障使用新连接,必要时只删除精确匹配的演练连接,禁止全局 conntrack -F。

4. DNAT:请求目的不同,过滤时看到什么#

# nat.nft 已提供 10.10.0.1:18080 → 10.20.0.10:8080。
sudo ip netns exec lr-app curl --noproxy '*' --fail --max-time 3 http://10.10.0.1:18080/health
sudo ip netns exec lr-router nft list table ip route_nat

预期成功。DNAT 位于 prerouting,随后按转换后的目的选路;FORWARD 规则匹配的是 10.20.0.10:8080,不是外部入口的 18080。本例也做 SNAT,保证后端回复经过同一路由器。路由器本机发起的请求走 OUTPUT,不会自动经过同样的 prerouting DNAT;这也是“外部通、本机不通”的常见原因。

需要逐包追踪时,仅对本例地址添加 meta nftrace set 1 规则,再运行 nft monitor trace;不要在生产上追踪全部流量或输出业务载荷。

5. 恢复#

sudo ip netns exec lr-router nft delete table ip route_nat
sudo ip netns exec lr-router nft delete table inet route_lab
sudo ip -n lr-db route add 10.10.0.0/24 via 10.20.0.1
sudo ip netns exec lr-app curl --noproxy '*' --fail --max-time 3 http://10.20.0.10:8080/health
sudo bash lab.sh cleanup

关闭 NAT 后用新连接验证直接路由恢复;命名空间清理同时移除本实验 conntrack。Docker/Kubernetes 主机可能由平台管理 iptables/nftables,先看 iptables -V 与 nft list ruleset,不要混用管理工具或清空其规则。

搜索文档

输入关键词,搜索所有文档。

↑ ↓ 选择 · Enter 打开 · Esc 关闭