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

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 类型对比

类型全称方向操作典型用途
SNATSource NAT出站修改源地址内网主机访问外网
DNATDestination NAT入站修改目的地址外网访问内网服务
MASQUERADE伪装出站动态 SNAT拨号网络、动态 IP
REDIRECT重定向本地重定向到本机端口透明代理

5.1.3 NAT 表的链分布

支持的 NAT 操作说明
PREROUTINGDNAT、REDIRECT入站数据包的目的地址转换
OUTPUTDNAT、REDIRECT本机发出的数据包的目的地址转换
POSTROUTINGSNAT、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 的区别

特性SNATMASQUERADE
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 NATNAT 标准文档
man iptables-extensionsNAT 相关扩展的手册
conntrack-tools 文档连接跟踪管理工具

本章小结

NAT 类型参数用途
SNATPOSTROUTING--to-source内网出站源地址替换
DNATPREROUTING--to-destination外网入站目的地址替换
MASQUERADEPOSTROUTING无需参数动态 SNAT
REDIRECTPREROUTING/OUTPUT--to-port重定向到本机端口

下一章第 06 章:mangle 表详解,将学习如何修改数据包的元数据。