一提到 NAT 的配置很多人的第一反应是“家用路由器后台的某个开关”再往深一点就是“端口映射”。但这些年做服务器网络和办公网络维护我的体会是NAT 是底层网络概念不是路由器界面某行菜单。早些时候我帮一个办公环境搭网络出口整层楼几十台设备只有一个公网 IP所有内网机器要稳定互访又要出外网最后靠的就是一套 Linux 网关 NAT 配置。这篇文章我干脆从原理讲起把 NAT 是什么、分哪几种、Linux 上怎么配、容器和路由器环境下怎么理解、配置完不通怎么查这几件事一次说清楚。正在学网络基础的同学以及配过 NAT 但问题处理起来没把握的运维同事都可以直接照着思路走一遍。1. NAT 解决的远不只是“公网地址不够用”这一个问题1.1 IPv4 地址短缺是 NAT 存在的第一前提先说地址问题。IPv4 地址是 32 位理论总数大约 42.9 亿个听着不少但如今每一台手机、电脑、云主机、物联网设备都要占用至少一个可路由的公网地址全球互联网早就“入不敷出”了。尤其是一些中型机房和办公场景上联往往只能拿到一个 IPv4 地址想再多申请几个要么走额外收费流程要么根本没有富余配额。地址不够用就不能让每台设备都直接暴露公网。NAT 的思路比较“讨巧”内网设备先用私网地址互相通信需要访问外网时统一把数据包交给出口网关网关在数据包出境时把源 IP 替换成自己的公网地址。这样所有设备对外呈现为一个公网地址内网却能同时容纳几十台、上百台机器。整个过程对客户端是透明的普通终端根本感知不到自己被转换过。1.2 私有地址段和 NAT 是配套设计与 NAT 绑定出现的是私网地址段。按照通用的地址保留规则10.0.0.0/8、172.16.0.0/12、192.168.0.0/16 这三段被明确划为私有地址公网路由设备不会主动转发目标地址落在这些段内的数据包。换句话说私网地址天然只能在局域网内部使用内网设备之间可以畅通无阻但想和外网通信必须经过一层边界转换。配置 NAT 的时候内网侧几乎总是从上面这几段里挑一个子网来规划上联侧则使用运营商分配的公网地址。拿办公场景打个比方公网地址是大楼的对外总机号码私网地址是每个工位的内部分机号。外部拨打总机由前台转接到对应分机分机要外呼也必须走总机统一出口。NAT 就是这套“总机逻辑”在网络层的实现。1.3 NAT 的隐藏收益内网拓扑被边界藏起来了地址转换除了解决短缺之外还带来一个容易被人忽略的副产品——内网拓扑不可见。因为内网设备在出境时统一换成网关地址外部网络看到的所有连接都来自同一个出口 IP内部的服务器数量、主机 IP 分布、拓扑结构都不容易被外界摸清。对安全体系比较薄弱的小型办公网络来说这个特性等于天然加上了一层基础遮蔽。不过需要提醒一句NAT 不是防火墙它只做地址转换不做精细化访问控制。很多初学者会误以为“配了 NAT 就安全了”这是典型的理解偏差。NAT 让外部主动连入内网的通道被收敛但真正要防恶意访问还需要依靠防火墙策略、系统加固和访问控制一起来做。配置阶段把安全职责分清楚后面排错才不容易被误导。2. 配置前先对齐需求静态 NAT、动态 NAT、NAPT 哪种才是你要的2.1 三种模式横向对比NAT 不是单一功能而是几种转换机制的统称。很多配置教程只给命令不给选择逻辑结果就是读者抄了命令换个场景就懵。实际上日常配置基本绕不开三种模式。模式转换维度公网地址消耗典型场景静态 NAT一对一固定映射一个内网 IP 占一个公网 IP对外提供固定服务公网访问内网服务器动态 NAT一对一按需分配内网设备从公网地址池中临时获取较少用适合公网地址相对充足的接入场景NAPT/PAT多对一IP 端口双重转换多个内网 IP 共享一个公网地址办公网络共享上网宽带路由器主流方案很多人嘴里说的“NAT 配置”实际指的是 NAPT也就是最常见的“多对一端口复用”。这种模式不仅替换源 IP还会为每个会话分配不同的源端口从而区分同一公网 IP 下的不同内网主机。这也是家用路由器和办公网关默认采用的方式。2.2 一句话分清 SNAT 和 DNAT进入 Linux 配置之前还必须分清两个方向SNAT源地址转换和 DNAT目的地址转换。SNAT 发生在数据包离开网关时把内网点换成自己地址上解决的是“内网怎么访问外网”的问题。DNAT 发生在数据包刚进入网关时把目的 IP 从公网地址改写为内网某台主机的地址解决的是“外网怎么访问内网吧”的问题。这两个方向在 netfilter 里对应的执行点完全不同SNAT 在 POSTROUTING 链做DNAT 在 PREROUTING 链做。配置时拿反了最常见的现象就是内网能出去但回不来或者外网映射不生效。我见过不少把 DNAT 写进 POSTROUTING 的配置规则看着合法逻辑上完全是拧的。2.3 端口映射不是什么“新功能”它本质就是 DNAT配置家用路由器时经常看到“端口映射”“虚拟服务器”“端口转发”这类菜单。表面看是路由器自带功能实际内核里做的就是目的地址转换。外部用户访问路由器公网 IP 的某个端口路由器根据映射表把目的地址改成某个内网主机再顺着局域网路由把包送进去。理解这个本质很重要因为 Linux 网关、企业防火墙、家用路由器里的“端口映射”底层逻辑是同一个。只会点网页界面、不懂数据流方向一旦遇到要手写规则或跨设备排错就会卡住。后面讲到 Linux DNAT 配置时思路和家用路由器是互通的。3. 内核转发和 netfilter 链路Linux 上配置 NAT 的准备工作3.1 第一步确认内核 IP 转发已开启Linux 主机默认不转发跨网卡的数据包。也就是说就算你把两个网络接到同一台 Linux 上eth0 收到的数据包如果目标地址不是本机内核会直接丢弃根本不会往 eth1 送。要让 Linux 变成网关第一件事是打开 IP 转发。临时开启用一条命令即可sysctl -w net.ipv4.ip_forward1永久生效要把参数写入配置目录echo net.ipv4.ip_forward 1 /etc/sysctl.conf sysctl -p /etc/sysctl.conf需要支持 IPv6 转发时再把net.ipv6.conf.all.forwarding一并设置。这里有个容易忽略的点开启转发本身不会让内网自动共享外网它只是放行“路由路径上的数据包”真正的地址转换还要靠下面的 NAT 规则。3.2 第二步分清 netfilter 里要动哪些表和链Linux 的 NAT 功能由内核 netfilter 框架提供经典操作工具是 iptables新一代工具是 nftables。无论哪个核心概念都是“表”和“链”。配置 NAT 时主要操作 nat 表其中最重要的三个链是PREROUTING数据包到达本机、还没做路由判断之前适合做 DNAT。POSTROUTING数据包即将离开本机时适合做 SNAT 或 MASQUERADE。OUTPUT本机自身产生的数据包出口一般少用但网关本机要访问 DNAT 映射的服务时会用到。另外还有一个 filter 表里的 FORWARD 链虽然和 NAT 不在同一张表但网关转发流量默认都会经过它。如果 FORWARD 链策略是 DROP 或没有对应放行规则NAT 做得再对流量照样被拦在网关这一层。这是新手配置 NAT 最常踩的隐形坑。3.3 第三步确认防火墙方案避免两条规则打架动手之前先确认当前系统用的是 iptables 还是 nftables 体系有没有 firewalld、ufw 这类上层管理工具。不同发行版默认方案不一样有的用 iptables-nft 兼容层有的直接用 nft 原生规则。配置前执行iptables -L -n或nft list ruleset先看一眼现状再决定是直接加规则还是先清理冲突规则。实际经验里最常见的冲突发生在“手工加了 iptables NAT 规则同时系统又开着 firewalld结果 firewalld 的默认 FORWARD 策略把转发全拦了”。这种故障不查防火墙状态很难定位。所以第三步不是细节是前置条件先确认你装的是哪套防火墙、当前 FORWARD 策略是什么再动手。4. 一个可复现的配置实例Linux 网关让内网自动访问外网4.1 场景和 IP 规划先定好哪个口上联、哪个口接内网用一个最典型的办公共享上网场景来演示。假设机器有两块网卡eth0 是上联口接外部网络使用文档测试网段地址 203.0.113.10/24eth1 是内网口地址 192.168.50.1/24。内网有一台客户端IP 是 192.168.50.100默认网关指向 192.168.50.1。开始之前先确认两块网卡都已经配置好 IP并且ip addr能看到接口处于 up 状态。很多配置失败并不是 NAT 规则写错而是内网口本身没起来或者网关地址和客户端不在同一网段。4.2 配置命令逐条拆解第一步先打开 IP 转发sysctl -w net.ipv4.ip_forward1第二步为了让演示环境干净先清理 nat 表中可能存在的旧规则。生产环境不要随便iptables -F一定要先评估现有规则再操作iptables -t nat -F iptables -t nat -X第三步打出核心 NAT 规则iptables -t nat -A POSTROUTING -s 192.168.50.0/24 -o eth0 -j MASQUERADE这条规则的意思是来自 192.168.50.0/24 网段、从 eth0 口出去的数据包把源地址动态替换为 eth0 上联口的地址。到这里地址转换本身已经完成。但还没结束。第四步要放通 filter 表的 FORWARD 链否则内网数据包在转发路径上会被丢弃iptables -A FORWARD -i eth1 -o eth0 -s 192.168.50.0/24 -j ACCEPT iptables -A FORWARD -i eth0 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCEPT第一句允许内网主动发往外网的新连接第二句允许已经建立连接的回程包进入内网。这两条规则合起来才构成“内网发起访问外网外网响应包能回到内网”的完整通道。很多教程只给第一条回程流量反而被默认策略拦死排查起来非常诡异。第五步验证。客户端配上 192.168.50.100/24、网关 192.168.50.1然后先 ping 网关再通过网关访问外部地址。如果外网 IP 能通说明 SNAT 和链路放行都正常。接着测试域名解析和实际业务端口别只拿 ping 下结论。4.3 固定出口 IP 用 SNAT动态出口用 MASQUERADE遇到固定公网 IP 的场景用 SNAT 写死源地址更精确iptables -t nat -A POSTROUTING -s 192.168.50.0/24 -o eth0 -j SNAT --to-source 203.0.113.10MASQUERADE 和 SNAT 在效果上相似但执行机制不同。MASQUERADE 在每条新连接建立时都会动态检查出口地址适合出口 IP 可能变化的场景比如拨号获取动态地址SNAT 则固定写死翻译地址性能稍高一点也方便外部日志和访问控制对接固定公网 IP。配置静态拨号等固定 IP 时优先用 SNAT。4.4 反向场景用 DNAT 把内网服务发布到公网内网机器访问外网只用了 SNAT 方向但外部访问内网还需要配合 DNAT。例如内网有一台 Web 服务监听在 192.168.50.100:80想通过网关公网地址的 8080 端口对外发布执行规则如下iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination 192.168.50.100:80 iptables -t nat -A POSTROUTING -d 192.168.50.100 -p tcp --dport 80 -j MASQUERADE第一条负责把外部访问改写为内网服务器第二条负责回程包转换确保内网服务器返回数据时能正确回到外部访问方。这两条方向相反缺了任何一条表现出的现象通常是“外部连不上”或“连接崩了但响应报文返回时丢包”。如果网关自身也需要访问这个 DNAT 服务必须同时把规则加到 OUTPUT 链否则网关访问自己的公网 IP 不会命中 PREROUTING。4.5 规则持久化不能让配置随着重启消失手工敲的 iptables 规则不会自动保存重启后清空是常态。常见持久化做法有三种按发行版选择即可。Debian/Ubuntu 系常用 iptables-persistent保存后再开机自动恢复。RHEL 系如果默认走 firewalld需要在firewall-cmd中定义富规则或者关闭 firewalld 后改用 iptables-services。nftables 环境则直接配置/etc/nftables.conf用nft add语法把规则固化。无论用哪种方式务必在规则生效后再执行一次保存动作。很多同事配完当时一切正常第二天发现网络又断了就是漏了这一步。5. 容器、虚拟机、路由器NAT 在不同环境里的配置逻辑5.1 Docker 的 bridge 网络默认就在做 NATDocker 默认的 bridge 网络对普通用户是“透明”的容器启动后自动拿到一个内网 IP外部网络访问不到但容器能主动访问外网。这里有很重要的网桥规则浏览器通过宿主机 iptables 的 MASQUERADE 规则实现容器出网。用iptables -t nat -L -n | grep -i masq就能看到 Docker 自动写入的相关规则。理解了这一点就不会产生“我明明没配置 NAT为什么容器能上网”的疑惑。容器、宿主机、外部网络按照 NAT 逻辑串起来容器内网 IP 被隐藏所有外部连接看起来都来自宿主机地址。如果宿主机本身禁用了 iptables NATbridge 模式下容器外网访问可能直接失败。5.2 发布容器端口实际等于宿主机做了 DNAT用docker run -p 8080:80发布容器端口时底层行为就是把宿主机 8080 端口的目的地址转换成容器 IP 的 80 端口。这个过程和前面 Linux DNAT 的原理一模一样只不过 Docker 自动化完成。但自动不代表没有坑。很多服务器为了安全filter 表 FORWARD 链默认 DROP。Docker 启动时虽然会加入自己的规则但如果你手工调整过链的默认策略顺序错乱就会导致容器端口发布后外部始终访问不了。碰到这种情况先查宿主机 FORWARD 链里 Docker 规则是否被其他规则拦截再查 nat 表里的 DOCKER 链是否存在对应映射。5.3 虚拟机的 NAT 模式与桥接模式差别很大VMware、VirtualBox 这类虚拟化软件创建虚拟机网络时常见的是“NAT 模式”和“桥接模式”两种选择。NAT 模式隐藏虚拟机 IP由宿主机充当转换网关适合只想让虚拟机访问外网、不希望外部访问虚拟机的场景桥接模式则让虚拟机直接暴露在宿主机所在网络使用同一网段的真实 IP外部网络可以直连虚拟机。模式虚拟机地址获取外部访问虚拟机适用场景NAT 模式虚拟网卡从隐藏子网自动获取 IP默认不能直接访问需额外配置端口转发测试环境、向宿主机隐藏虚拟机桥接模式直接获取宿主所在网络的地址可以虚拟机如同普通主机需直接对外提供服务的场景这里有个容易引发混淆的点虚拟机“NAT 模式”里配置的端口转发实现方式同样是 DNAT。不管界面长得怎样底层逻辑是相通的。5.4 家用/办公路由器上的“端口映射”本质是同一件事带 web 后台的路由器通常把 NAT 藏得比较深最常用的是“端口映射”或“虚拟服务器”菜单。一个完整的映射记录无非是外部端口、内网 IP、内部端口、协议类型。翻译成刚才的 Linux 概念就是一条 PREROUTING DNAT 规则加上必要的回程放行。家用路由器里的 DMZ 主机功能可以理解为“把所有外部端口都映射到某台内网主机”配置简单方便代价是目标主机所有端口都暴露在公网。配置优先级上能用端口映射解决就不要开 DMZ。UPnP 虽然能自动建立映射但安全风险比较高非特殊需要建议关闭。6. NAT 配置完成却不通按这条链路一步步定位6.1 先判断数据到底有没有到网关NAT 不通第一步不是看 NAT 规则而是确定数据包有没有正确到达网关。在网关上用 tcpdump 抓一下就知道了tcpdump -i eth0 -n host 外部访问方或者全长地址 tcpdump -i eth1 -n host 192.168.50.100如果内网口抓不到客户端的包问题在交换机、网线、客户端 IP 配置上如果内网口有包、外网口没有说明包在转发路径被丢弃多半出在 FORWARD 链如果内网口和外网口都有包但回程还是不通就要回去检查 NAT 规则和路由。6.2 查看 NAT 规则命中次数判断规则是否匹配用iptables -t nat -L -n -v看每条规则的包计数。SNAT 规则应该有非零的 pkts 计数。如果计数始终是 0说明来源网段、出口接口或匹配条件写错了数据包根本没走到这条规则上。很多所谓“NAT 不生效”本质是规则没被匹配到。回程状态还可以通过 conntrack 查看转换记录cat /proc/net/nf_conntrack | grep 192.168.50.100能看到内网 IP 和外网 IP 之间完整的转换元组排查方向会很清晰。看不到对应记录说明会话根本没建立起来问题大概率在数据包到达阶段。6.3 FORWARD 默认策略和状态放行是重灾区我在实际排障中遇到最多的是 filter 表 FORWARD 链默认 DROP且没有添加对应放行规则。判断很快执行iptables -L FORWARD -n --line-numbers看有没有明文 ACCEPT 规则以及默认策略是 ACCEPT 还是 DROP。如果是 DROP请回到 4.2 节补上回程放行规则。这里也要提醒不要图省事把 FORWARD 策略直接改成 ACCEPT。虽然能立刻通网但等于把网关的转发安全边界完全打开内网和外部网络之间的隔离会崩塌。6.4 高并发场景下nf_conntrack 表被打满也会表现成“NAT 不通”连接数大的办公或服务场景NAT 时间可能间歇性断网新连接建立失败但已有连接还在跑。这不是规则问题而是连接跟踪表溢出了。日志里常看到nf_conntrack: table full的报错。解决办法是两个参数的调整一是适当提高连接跟踪最大容量二是调整超时参数。但调高会增大内存使用需要结合机器实际规格做权衡sysctl -w net.netfilter.nf_conntrack_max200000调参之后要持续观察内存占用和实际并发量不能拍脑袋拉高。6.5 反向路径过滤和策略路由导致“回不来”最后留一个容易被忽略的点某些多网卡、多出口环境会启用反向路径过滤内核会自动丢弃“源地址不在本侧合理路由范围内”的数据包。典型表现是 SNAT 之后回包到网关时被 rp_filter 拦截现象上表现为“外面连进来能通内网发起访问却总失败”。此时需要检查对应接口的 rp_filter 参数并结合实际路由表决定是否要调整。遇到这类场景先把net.ipv4.conf.all.rp_filter和对应接口的 rp_filter 输出对比一下确认是否存在反向路径校验问题再去动规则。做 NAT 配置这些年我踩过最隐蔽的坑是在内网转发回程路径上漏了 FORWARD 放行。当时网关测转发、测 SNAT 全部看起来正常内网机器只能发出请求却收不到响应折腾了大半天才意识到是 FORWARD 默认策略把所有回程包拦了。那次之后我总结了一套固定自查顺序先确认数据包到哪一层再查规则命中计数然后看转发链策略最后看连接跟踪表。按这个链路走大部分 NAT 问题都能在几分钟内定位。希望这篇内容能帮你省下我当初浪费的那半天时间。