snat管“出去”、dnat管“进来”,二者分别作用于postrouting链和prerouting链,配合ip转发与forward放行规则,才能实现内网访问外网及外网安全访问内网服务的闭环控制。

用 iptables 的 SNAT 和 DNAT 实现精细化网络访问控制,关键不在堆命令,而在理清数据流向、明确角色边界、按需设限。核心是:SNAT 管“出去”,DNAT 管“进来”,两者配合才能形成闭环策略。
先搞懂数据包在哪条链上被改
SNAT 只能在 nat 表的 POSTROUTING 链 生效——这是数据包即将离开本机前的最后一站,此时源地址才被替换;DNAT 只能在 nat 表的 PREROUTING 链(入站第一站)或 OUTPUT 链(本机发起的出站)生效——目的地址必须在路由决策前就确定好。错放链或表,规则直接无效。
常见误区:
- 把 SNAT 写进 INPUT 或 FORWARD 链 → 不生效
- 把 DNAT 写进 POSTROUTING 链 → 目的地址已路由完成,改了也白改
- 没开 IP 转发(
net.ipv4.ip_forward=1)→ 即使规则写了,包也过不去
SNAT:不是只做“上网伪装”,还能做流量分层出口
基础 SNAT 是让整个内网共用一个公网 IP 上网,但生产中常需更细粒度控制:
-
按源网段区分出口 IP:财务网段(192.168.10.0/24)走专线 IP
203.0.113.10,研发网段(192.168.20.0/24)走云服务器 IP203.0.113.20 -
按协议/端口分流:HTTP/HTTPS 流量走主线路,SSH 管理流量强制走带宽保障线路(指定不同
--to-source) -
动态环境用 MASQUERADE:ADSL 或云主机 DHCP 获取公网 IP 时,用
-j MASQUERADE替代固定--to-source,自动适配变化的出口地址
示例命令:
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j SNAT --to-source 203.0.113.10iptables -t nat -A POSTROUTING -s 192.168.20.0/24 -o eth1 -j SNAT --to-source 203.0.113.20
DNAT:不只是端口映射,更是服务入口的精细调度
DNAT 的价值远超“把 80 映射到 192.168.1.100:8080”。它可支撑真实业务逻辑:
- 多实例负载分担:同一公网 IP 的 80 端口,按连接哈希或轮询转发到不同后端(需配合 conntrack 或第三方模块)
- 灰度发布控制:将 5% 的外网请求(如特定 User-Agent 或来源地域)DNAT 到测试服务器,其余走生产
- 协议剥离与重定向:HTTPS 请求 DNAT 到反向代理(如 Nginx),由其终止 SSL 并转发 HTTP 到内网 Web 服务
-
安全隔离跳转:把所有对
203.0.113.50:2222的 SSH 请求 DNAT 到跳板机192.168.1.200:22,禁止直连业务服务器
示例命令:
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 2222 -j DNAT --to-destination 192.168.1.200:22iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination 192.168.1.50:443
必须配套的底层支撑和验证动作
光写 SNAT/DNAT 不够,缺了这些,策略就是纸老虎:
-
FORWARD 链放行规则同步更新:DNAT 后目标变了,但 FORWARD 默认 DROP,必须显式允许新流向,例如:
iptables -A FORWARD -i eth0 -o eth1 -d 192.168.1.50 -p tcp --dport 443 -j ACCEPT -
连接跟踪(conntrack)合理配置:高并发场景下调整
net.netfilter.nf_conntrack_max和超时值,避免连接表溢出丢包 -
日志+抓包双验证:用
iptables -j LOG打标记日志,再用tcpdump -i eth0 port 80在对应接口抓包,确认地址是否真被改写、包是否走到预期路径 -
规则持久化:Ubuntu 用
iptables-persistent,CentOS 7 用service iptables save或iptables-save > /etc/sysconfig/iptables,否则重启即失效











