别再死记硬背了!5分钟用生活场景理解Linux iptables的SNAT和DNAT
刚接触Linux网络配置时,看到满屏的iptables规则是不是头皮发麻?尤其是SNAT和DNAT这两个长得像双胞胎的术语,手册里的解释总是绕来绕去。今天我们就用快递收发、酒店前台这些生活场景,把这两个核心概念揉碎了讲明白。
1. 为什么需要NAT?从快递地址说起
想象你住在一个封闭小区(内网),所有住户的门牌号都是192.168开头的私有号码。某天你想给外面的朋友(公网)寄快递,但快递公司规定:只接收公网地址的包裹。这时候小区物业(网关)站出来说:"把包裹给我,我帮你换成小区对外的统一地址(公网IP)再寄出"——这就是NAT(网络地址转换)的日常版。
NAT的三大刚需场景:
- 解决IPv4地址枯竭(一个公网IP供整个小区使用)
- 隐藏内网结构(外部看不到你家具体门牌号)
- 绕过网络限制(某些服务只允许特定IP访问)
小知识:全球IPv4地址在2019年就已全部分配完毕,NAT技术让互联网多撑了20年
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. SNAT:让内网设备上网的"寄件人代填服务"
继续用快递类比,SNAT(Source NAT)就是物业的寄件人代填服务。当你的包裹经过网关时,物业会把寄件人地址从"192.168.1.10"改成"小区统一公网地址",这样回邮时快递会先到物业,再由物业转交给你。
经典SNAT命令拆解:
bash复制iptables -t nat -A POSTROUTING \
-s 192.168.1.0/24 \ # 来自内网网段
-o eth0 \ # 从外网网卡发出
-j SNAT \ # 执行SNAT操作
--to-source 203.0.113.1 # 替换为这个公网IP
参数避坑指南:
-t nat:指定nat表(默认filter表不处理地址转换)POSTROUTING:在路由决策之后修改源地址(重要!)-o eth0:必须指定出口网卡,否则可能影响内网通信
动态IP用户可以用这个简化版:
bash复制iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
3. DNAT:把外部请求转发到内网的"快递分拣中心"
DNAT(Destination NAT)则像酒店的前台分拣服务。当外人给酒店总机(公网IP)打电话时,前台根据分机号把电话转接到具体房间(内网服务器)。对应到网络场景,就是把访问公网IP:80的请求,转发到内网服务器的192.168.1.100:80。
端口转发经典示例:
bash复制iptables -t nat -A PREROUTING \
-d 203.0.113.1 \ # 目标为公网IP
-p tcp --dport 80 \ # 访问80端口
-j DNAT \ # 执行DNAT操作
--to-destination 192.168.1.100:8080 # 转到内网服务器的8080端口
关键区别点:
- DNAT在
PREROUTING链处理(路由决策前修改目标地址) - 通常需要配合SNAT使用(确保返回包能正确路由)
4. 高频问题排查指南
现象1:内网能上网但外网无法访问内网服务
- 检查顺序:
sysctl net.ipv4.ip_forward是否为1- DNAT规则是否在PREROUTING链
- 是否有对应的SNAT或MASQUERADE规则
现象2:NAT规则不生效
- 快速诊断命令:
bash复制iptables -t nat -L -n -v # 查看规则命中计数器 tcpdump -i eth0 port 80 # 抓包观察流量走向
规则持久化技巧:
bash复制# 保存当前规则
iptables-save > /etc/iptables.rules
# 开机自动加载
echo "iptables-restore < /etc/iptables.rules" >> /etc/rc.local
chmod +x /etc/rc.local
5. 进阶:一个真实案例的全流程配置
假设我们要实现:
- 内网192.168.1.0/24通过网关上网
- 外网可通过gateway.example.com:5000访问内网192.168.1.100的SSH
完整配置步骤:
-
开启IP转发:
bash复制echo 1 > /proc/sys/net/ipv4/ip_forward -
配置SNAT:
bash复制
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE -
配置DNAT:
bash复制
iptables -t nat -A PREROUTING \ -d 203.0.113.1 -p tcp --dport 5000 \ -j DNAT --to-destination 192.168.1.100:22 -
允许转发流量:
bash复制
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT iptables -A FORWARD -i eth0 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCEPT
测试时发现外网连接超时?可能是忘了放行5000端口:
bash复制iptables -A INPUT -p tcp --dport 5000 -j ACCEPT
