iptables 完全指南 / 第 05 章:NAT 表详解
第 05 章:NAT 表详解
本章目标:掌握 NAT(Network Address Translation,网络地址转换)的原理与配置,包括 SNAT、DNAT、MASQUERADE 及端口映射。
5.1 NAT 基础概念
5.1.1 什么是 NAT
NAT 是一种在数据包经过路由器时修改 IP 地址头部的技术。它解决了 IPv4 地址不足的问题,同时也提供了网络隐藏功能。
NAT 转换过程
内网主机 NAT 网关 外网服务器
10.0.0.100 ─────────→ eth1: 10.0.0.1 8.8.8.8
eth0: 203.0.113.1
数据包(发送):
┌─────────────────────────────────────────────────────────┐
│ 源 IP: 10.0.0.100 ──SNAT──→ 源 IP: 203.0.113.1 │
│ 目的 IP: 8.8.8.8 目的 IP: 8.8.8.8 │
└─────────────────────────────────────────────────────────┘
数据包(回复):
┌─────────────────────────────────────────────────────────┐
│ 源 IP: 8.8.8.8 源 IP: 8.8.8.8 │
│ 目的 IP: 203.0.113.1 ──DNAT──→ 目的 IP: 10.0.0.100 │
└─────────────────────────────────────────────────────────┘
5.1.2 NAT 类型对比
| 类型 | 全称 | 方向 | 操作 | 典型用途 |
|---|---|---|---|---|
| SNAT | Source NAT | 出站 | 修改源地址 | 内网主机访问外网 |
| DNAT | Destination NAT | 入站 | 修改目的地址 | 外网访问内网服务 |
| MASQUERADE | 伪装 | 出站 | 动态 SNAT | 拨号网络、动态 IP |
| REDIRECT | 重定向 | 本地 | 重定向到本机端口 | 透明代理 |
5.1.3 NAT 表的链分布
| 链 | 支持的 NAT 操作 | 说明 |
|---|---|---|
PREROUTING | DNAT、REDIRECT | 入站数据包的目的地址转换 |
OUTPUT | DNAT、REDIRECT | 本机发出的数据包的目的地址转换 |
POSTROUTING | SNAT、MASQUERADE | 出站数据包的源地址转换 |
重要:NAT 表只处理每个连接的第一个数据包(NEW 状态)。连接建立后,后续数据包根据连接跟踪(conntrack)记录自动进行地址转换,无需再次匹配 NAT 规则。
5.2 SNAT(源地址转换)
5.2.1 工作原理
SNAT 将数据包的源 IP 地址替换为 NAT 网关的公网地址,使内网主机能够访问外网。
┌──────────────┐ ┌─────────────────┐ ┌──────────────┐
│ 内网主机 │ │ NAT 网关 │ │ 外网服务器 │
│ 10.0.0.100 │────→│ 203.0.113.1 │────→│ 8.8.8.8 │
│ │ │ │ │ │
│ 发送: │ │ SNAT 转换: │ │ 看到的是: │
│ src: 10.0.0.100 │ 10.0.0.100 → │ │ src: 203.0.113.1
│ dst: 8.8.8.8 │ │ 203.0.113.1 │ │ dst: 8.8.8.8 │
└──────────────┘ └─────────────────┘ └──────────────┘
5.2.2 配置 SNAT
# 前提:启用 IP 转发
echo 1 > /proc/sys/net/ipv4/ip_forward
# SNAT:将内网 10.0.0.0/24 的出站流量源地址替换为 203.0.113.1
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j SNAT --to-source 203.0.113.1
# 多地址 SNAT(负载均衡)
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 \
-j SNAT --to-source 203.0.113.1-203.0.113.10
5.2.3 SNAT 参数说明
| 参数 | 说明 |
|---|---|
--to-source | 指定替换后的源地址 |
-s | 匹配源地址(内网网段) |
-o | 匹配出接口(公网接口) |
-t nat | 操作 nat 表 |
5.2.4 业务场景:企业内网出口
# 场景:企业有 203.0.113.1-203.0.113.4 四个公网 IP
# 内网 10.0.0.0/16 需要通过这些 IP 访问互联网
# 启用转发
sysctl -w net.ipv4.ip_forward=1
# SNAT 规则
iptables -t nat -A POSTROUTING -s 10.0.0.0/16 -o eth0 \
-j SNAT --to-source 203.0.113.1-203.0.113.4
# 配合 filter 表
iptables -A FORWARD -i eth1 -o eth0 -s 10.0.0.0/16 -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -P FORWARD DROP
5.3 DNAT(目的地址转换)
5.3.1 工作原理
DNAT 将数据包的目的 IP 地址替换为内网服务器的地址,使外网用户能够访问内网服务。
┌──────────────┐ ┌─────────────────┐ ┌──────────────┐
│ 外网用户 │ │ NAT 网关 │ │ 内网 Web 服务器│
│ 203.0.113.50 │────→│ 203.0.113.1 │────→│ 10.0.0.10 │
│ │ │ │ │ │
│ 请求: │ │ DNAT 转换: │ │ 看到的是: │
│ dst: 203.0.113.1 │ 203.0.113.1 → │ │ src: 203.0.113.50
│ port: 80 │ │ 10.0.0.10 │ │ dst: 10.0.0.10│
└──────────────┘ └─────────────────┘ └──────────────┘
5.3.2 配置 DNAT
# 将发往 203.0.113.1:80 的流量转发到内网 10.0.0.10:80
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 \
-j DNAT --to-destination 10.0.0.10:80
# 配合 FORWARD 链允许转发
iptables -A FORWARD -i eth0 -o eth1 -p tcp --dport 80 \
-d 10.0.0.10 -j ACCEPT
5.3.3 DNAT 参数说明
| 参数 | 说明 |
|---|---|
--to-destination | 指定替换后的目的地址和端口 |
-i | 匹配入接口(公网接口) |
--dport | 匹配目的端口 |
5.3.4 端口映射
# 将公网 8080 端口映射到内网 80 端口
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 \
-j DNAT --to-destination 10.0.0.10:80
# 将公网 3306 端口映射到内网数据库服务器
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 3306 \
-j DNAT --to-destination 10.0.0.200:3306
# 多端口映射
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 \
-j DNAT --to-destination 10.0.0.10:80
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8443 \
-j DNAT --to-destination 10.0.0.10:443
5.3.5 业务场景:Web 服务器集群入口
#!/bin/bash
# 将公网流量转发到内网的 Web 服务器
# 启用转发
sysctl -w net.ipv4.ip_forward=1
# DNAT:HTTP → Web Server 1
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 \
-j DNAT --to-destination 10.0.0.10:80
# DNAT:HTTPS → Web Server 1
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 \
-j DNAT --to-destination 10.0.0.10:443
# DNAT:SSH(高端口) → 管理服务器
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 2222 \
-j DNAT --to-destination 10.0.0.5:22
# FORWARD 链:允许已建立的连接
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# FORWARD 链:允许外网访问内网 Web
iptables -A FORWARD -i eth0 -o eth1 -p tcp --dport 80 -d 10.0.0.10 -j ACCEPT
iptables -A FORWARD -i eth0 -o eth1 -p tcp --dport 443 -d 10.0.0.10 -j ACCEPT
iptables -A FORWARD -i eth0 -o eth1 -p tcp --dport 22 -d 10.0.0.5 -j ACCEPT
# FORWARD 链:允许内网访问外网
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
# 默认拒绝转发
iptables -P FORWARD DROP
# SNAT:内网出站
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 \
-j SNAT --to-source 203.0.113.1
5.4 MASQUERADE(伪装)
5.4.1 与 SNAT 的区别
| 特性 | SNAT | MASQUERADE |
|---|---|---|
| IP 地址 | 固定指定 | 自动使用出口接口的 IP |
| 性能 | 更高 | 略低(每次需查询接口 IP) |
| 适用场景 | 固定 IP 的服务器 | 拨号网络、DHCP、动态 IP |
| 配置复杂度 | 需要知道公网 IP | 不需要知道公网 IP |
5.4.2 配置 MASQUERADE
# 使用 MASQUERADE(适用于拨号网络或动态 IP)
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o ppp0 -j MASQUERADE
# 使用 MASQUERADE(适用于 DHCP 获取 IP 的云服务器)
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o eth0 -j MASQUERADE
5.4.3 业务场景:家用路由器
#!/bin/bash
# 家用 Linux 路由器脚本
# 启用转发
sysctl -w net.ipv4.ip_forward=1
# WAN 接口(连接互联网,DHCP 获取 IP)
WAN="eth0"
# LAN 接口(连接局域网)
LAN="eth1"
# 内网网段
LAN_NET="192.168.1.0/24"
# 允许内网访问外网(MASQUERADE)
iptables -t nat -A POSTROUTING -s $LAN_NET -o $WAN -j MASQUERADE
# FORWARD 规则
iptables -A FORWARD -i $LAN -o $WAN -j ACCEPT
iptables -A FORWARD -i $WAN -o $LAN -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -P FORWARD DROP
5.5 REDIRECT(重定向)
5.5.1 工作原理
REDIRECT 将数据包的目的地址重定向到本机,常用于透明代理。
# 将所有 HTTP 流量重定向到本机的 3128 端口(Squid 代理)
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 \
-j REDIRECT --to-port 3128
# 本机产生的 HTTP 流量也重定向
iptables -t nat -A OUTPUT -p tcp --dport 80 \
-j REDIRECT --to-port 3128
5.6 NAT 的连接跟踪依赖
5.6.1 NAT 与 conntrack 的关系
新连接的第一个包:
┌─────────────────────────────────────────────────┐
│ 1. PREROUTING(raw 表) │
│ 2. PREROUTING(mangle 表) │
│ 3. PREROUTING(nat 表) ← DNAT 在这里 │
│ 4. 路由决策 │
│ 5. FORWARD(mangle 表) │
│ 6. FORWARD(filter 表) │
│ 7. POSTROUTING(mangle 表) │
│ 8. POSTROUTING(nat 表) ← SNAT 在这里 │
│ │
│ conntrack 在步骤 3 和步骤 8 记录 NAT 映射关系 │
└─────────────────────────────────────────────────┘
后续数据包(ESTABLISHED 状态):
┌─────────────────────────────────────────────────┐
│ conntrack 自动查找已有记录,执行相同的 NAT 转换 │
│ 不再经过 nat 表的规则匹配 │
└─────────────────────────────────────────────────┘
5.6.2 验证 conntrack 记录
# 查看所有连接跟踪记录
conntrack -L
# 查看 NAT 相关的连接跟踪记录
conntrack -L -p tcp
# 监控新建连接
conntrack -E
5.7 完整 NAT 网关配置
#!/bin/bash
# ═══════════════════════════════════════════════════════
# 完整 NAT 网关脚本
# ═══════════════════════════════════════════════════════
# 网络参数
WAN_IF="eth0"
LAN_IF="eth1"
LAN_NET="10.0.0.0/24"
WAN_IP="203.0.113.1"
# ─────────────── 系统配置 ───────────────
# 启用 IP 转发
sysctl -w net.ipv4.ip_forward=1
# ─────────────── 清空规则 ───────────────
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -X
# ─────────────── NAT 规则 ───────────────
# SNAT:内网出站
iptables -t nat -A POSTROUTING -s $LAN_NET -o $WAN_IF \
-j SNAT --to-source $WAN_IP
# DNAT:公网 80 → 内网 Web 服务器
iptables -t nat -A PREROUTING -i $WAN_IF -p tcp --dport 80 \
-j DNAT --to-destination 10.0.0.10:80
# DNAT:公网 443 → 内网 Web 服务器
iptables -t nat -A PREROUTING -i $WAN_IF -p tcp --dport 443 \
-j DNAT --to-destination 10.0.0.10:443
# DNAT:公网 2222 → 内网 SSH 服务器
iptables -t nat -A PREROUTING -i $WAN_IF -p tcp --dport 2222 \
-j DNAT --to-destination 10.0.0.5:22
# ─────────────── FORWARD 规则 ───────────────
# 允许已建立的连接
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 允许内网出站
iptables -A FORWARD -i $LAN_IF -o $WAN_IF -j ACCEPT
# 允许外网访问内网 Web 服务器
iptables -A FORWARD -i $WAN_IF -o $LAN_IF -p tcp -m multiport \
--dports 80,443 -d 10.0.0.10 -j ACCEPT
# 允许外网 SSH 到管理服务器
iptables -A FORWARD -i $WAN_IF -o $LAN_IF -p tcp --dport 22 \
-d 10.0.0.5 -j ACCEPT
# 默认策略
iptables -P FORWARD DROP
# ─────────────── INPUT 规则 ───────────────
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i $LAN_IF -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -P INPUT DROP
echo "NAT gateway configured successfully."
5.8 注意事项
⚠️ NAT 与 conntrack 的绑定:NAT 依赖连接跟踪表,如果 conntrack 表满了,新的 NAT 连接将无法建立。需要根据并发连接数调整
nf_conntrack_max。
# 查看当前 conntrack 限制
sysctl net.netfilter.nf_conntrack_max
# 增大 conntrack 表
sysctl -w net.netfilter.nf_conntrack_max=262144
echo "net.netfilter.nf_conntrack_max = 262144" >> /etc/sysctl.conf
⚠️ DNAT 不影响本机:DNAT 在 PREROUTING 链生效,只影响从外部进入的数据包。本机进程发出的到自身公网 IP 的连接不受 DNAT 影响。如果需要本机也能通过公网 IP 访问内网服务,需要在 OUTPUT 链也添加 DNAT 规则。
⚠️ SNAT 与 MASQUERADE 的选择:如果出口 IP 是固定的,优先使用 SNAT;如果是动态 IP(如 DHCP),使用 MASQUERADE。
5.9 扩展阅读
| 资源 | 说明 |
|---|---|
| RFC 3022 - Traditional NAT | NAT 标准文档 |
man iptables-extensions | NAT 相关扩展的手册 |
| conntrack-tools 文档 | 连接跟踪管理工具 |
本章小结
| NAT 类型 | 链 | 参数 | 用途 |
|---|---|---|---|
| SNAT | POSTROUTING | --to-source | 内网出站源地址替换 |
| DNAT | PREROUTING | --to-destination | 外网入站目的地址替换 |
| MASQUERADE | POSTROUTING | 无需参数 | 动态 SNAT |
| REDIRECT | PREROUTING/OUTPUT | --to-port | 重定向到本机端口 |
下一章:第 06 章:mangle 表详解,将学习如何修改数据包的元数据。