强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

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 表详解,将学习如何修改数据包的元数据。