前阵子一个朋友问我:家里放了台服务器,人在公司想连回去,但宽带没有固定公网IP,是不是只能租云服务器或者搞内网穿透?我让他登进路由器看了一眼WAN口地址,发现还是100.64开头的运营商CGNAT段,这种情况确实折腾。但聊了会儿我意识到,更多人遇到的其实是另一种“假没公网IP”——明明路由器拿到了公网IPv4,只是不固定,就觉得没法用了。实际上,只要出口设备支持NAT Server,一条命令就能把内网服务器映射到公网侧端口,外网照样能访问。这篇文章就把这条命令从原理、配置到排错、加固完整讲透,适合看过端口映射但没真正上手的人,也适合正准备把内网服务开放给外网试水的运维朋友。
1. “不用公网IP”先把概念说破:NAT Server解决的是哪类痛点
1.1 最常见的外网访问内网困境
先说一个基础场景:你在内网里有台服务器,IP是192.168.1.10,上面跑着一个Web服务,端口80。内网用户访问192.168.1.10一切正常。可一旦人离开办公室,回到家里,电脑拿到的是光猫分配的私网地址,你不可能直接用192.168.1.10去访问那台服务器,因为192.168网段是私有地址,公网路由根本不会把这包转发到你家内网。
于是大多数人想到三条路:买台云服务器把服务迁上去;用带公网IP的服务器做反向代理;或者搭建内网穿透通道。这三条路不是不行,但都要引入额外设备、额外成本,而且延迟和链路稳定性往往不可控。其实很多场景下,你缺的不是方案,而是对“公网IP”三个字的理解。
1.2 NAT Server的工作原理:前台分机转接模式
NAT Server在华为设备上的标准称呼是“NAT Server”,在思科体系里对应着目的地址转换,在大多数家用路由器里则叫“端口映射”或者“虚拟服务器”。名字五花八门,原理却是同一个:在出口路由器或防火墙上,把“公网IP + 某个端口”这个组合,一对一映射到“内网服务器IP + 某个端口”上。
我习惯用一个类比来解释:公司只有一部总机号码,前台就是公网IP,总机号后面的分机就是端口。外部客户打进总机,报一个分机号,前台就把电话接到对应的员工桌上。员工自己并没有独立的直线电话,但通过前台转接,外部一样能找到他。NAT Server干的就是前台转接这件事。
所以标题里的“不用公网IP也能搞定”,准确说法是“不用给每台内网服务器单独申请公网IP”。出口设备上有一个公网侧的地址,哪怕是动态变化的,也能通过一条NAT Server命令把整台内网服务器暴露出去。
1.3 什么情况下适合NAT Server
NAT Server适合的场景其实比很多人想得宽:个人NAS、博客站点、测试环境、远程桌面、SSH登录,这些都属于“外网低频访问内网”的典型需求。只要你的宽带出口设备上有公网IPv4地址,并且能进管理员后台,就具备使用NAT Server的条件。
但也有不适合的情况。如果你所在宽带处于运营商大内网,WAN口拿到的是100.64.x.x这类保留地址,那NAT Server基本没用。还有一种情况是公司网络出口由上级网管统一管控,你自己没有设备管理权限,那也做不了。另外,如果你需要给几十个甚至上百个外部用户提供稳定高频的访问,NAT Server也不是最优解,这时候更该考虑专业的远程接入方案或者上云。
2. 配置前必做的体检:你的宽带到底有没有“真公网IP”
2.1 先在服务器上查出当前出口公网IP(以armbian为例)
很多人一台armbian开发板就搭了各种服务,拿它当小型服务器用。想确认出口IP,最简单的方式就是在服务器终端直接执行查询命令:
curl ifconfig.me curl ip.sb curl cip.cc三个命令任选其一,返回的就是当前出口的公网IP。如果你用的是Windows Server 2016这类内网服务器,没有curl也可以直接用浏览器打开ifconfig.me,效果一样。
这里有个容易搞混的点:服务器上执行ip addr看到的eth0地址,是内网私网地址,那不是出口公网IP。armbian上执行ip addr大概率看到的是192.168.x.x,这是路由器分配的,和查询到的公网IP是两码事。你真正要关心的是出口设备WAN口上的地址,以及它和外部查询到的地址是否一致。
2.2 判断个人公网IP的三种方法
拿到查询结果后,把路由器的WAN口地址和它对比,基本就能判断宽带的IP类型。我用一张表总结一下判断逻辑:
| 检查项 | 结果 | 说明 |
|---|---|---|
| 路由器WAN口地址 | 192.168.x.x、10.x.x.x、172.16-31.x.x | 上面还有一级路由或运营商NAT |
| 路由器WAN口地址 | 100.64.x.x到100.127.x.x | 运营商CGNAT保留段,典型大内网 |
| WAN口地址 = 外部查询地址 | 相等 | 有公网IPv4,NAT Server可用 |
| WAN口地址 = 外部查询地址 | 不相等 | 中间存在NAT,大概率是运营商级 |
tracert到外网地址 | 前面几跳出现100.64.x.x | 已经处于CGNAT环境 |
第4条里说的“WAN口地址和外部查询地址一致”就是最直接也最可靠的判断标准。我见过很多用户把“没有固定公网IP”等同于“没有公网IP”,这是完全两回事。只要WAN口拿到的是公网IPv4,即使它会定期变化,NAT Server也能正常工作,只是你需要配合DDNS才能在IP变化后继续用域名访问,这个放到后面专门讲。
2.3 CGNAT环境为什么NAT Server救不了
如果判断下来你确实处在CGNAT环境,WAN口拿的是100.64.x.x或者和外部查询地址不一致,那就要冷静接受一个事实:NAT Server在这条线路上无论如何都做不通。原因是运营商在城域网内又做了一层NAT,你路由器上的公网地址是假象,你配置的映射只能作用在这层假地址上,外部流量根本到不了你的出口设备。
这种情况下,可选的合法方案是联系宽带运营商申请公网IPv4,部分地区可以免费开通动态公网IP;或者走IPv6直连方案,如果运营商分配了IPv6前缀,内网服务器配合IPv6地址是可以直接被外网访问的。注意,这些方法都不能用来做违规的事情,一切网络操作都需要在遵守法律法规的前提下进行。
3. NAT Server核心配置:一条命令加一个前提
3.1 华为路由器上的最小可用配置
确认宽带具备公网IP后,正式开始配置。以一台华为AR路由器为例,假设公网侧接口是GigabitEthernet0/0/0,地址203.0.113.1,内网服务器192.168.1.10,Web服务端口80,外部访问端口8080:
system-view interface GigabitEthernet0/0/0 ip address 203.0.113.1 255.255.255.0 quit nat server protocol tcp global 203.0.113.1 8080 inside 192.168.1.10 80关键就是最后这一条命令。拆开看:global后面跟的是公网侧地址和外部端口,inside后面跟的是内网服务器地址和实际服务端口。protocol tcp表示只映射TCP流量,如果服务基于UDP,改成protocol udp。这条命令建好之后,外部用户访问http://203.0.113.1:8080,流量就会被设备转发到192.168.1.10的80端口上。
华为防火墙USG系列也类似,只是接口通常有安全区域概念,命令长这样:
interface GigabitEthernet1/0/0 ip address 203.0.113.1 255.255.255.0 service-manage ping permit quit nat server name WebServer protocol tcp global 203.0.113.1 8080 inside 192.168.1.10 80注意防火墙版本不同,nat server后面可能要求带上策略名称,字段顺序也可能有差异,实际敲命令时按设备提示补全即可。
3.2 家用路由器Web界面上的“端口映射”
如果你用的是家用路由器,那更简单,大部分品牌把NAT Server做成了Web界面。常见的入口名称有“转发规则”“虚拟服务器”“端口映射”几种,不同品牌叫法不一样,但填写的字段大同小异:
| 字段 | 示例值 | 说明 |
|---|---|---|
| 外部端口/广域网端口 | 8080 | 外网访问时使用的端口 |
| 内部IP/局域网IP | 192.168.1.10 | 内网服务器地址 |
| 内部端口/局域网端口 | 80 | 服务器实际监听端口 |
| 协议 | TCP | 按服务类型选TCP/UDP/ALL |
有些家用路由器还提供“DMZ主机”功能,填一个内网IP后把所有未映射端口全部转发过去。这个东西我建议慎用,它本质上是把整台服务器裸露在公网,安全风险极高,后面我会单独说。
3.3 防火墙设备的隐藏前提:安全策略也要放行
NAT Server命令本身不复杂,很多人配完发现外网依然不通,问题往往出在“前提”上:企业级防火墙设备上,仅仅配置NAT Server是不够的,还需要安全策略放行对应流量。
以华为USG为例,NAT Server做完后,流量从untrust区域进到trust区域,如果没有对应的security-policy规则,默认会被丢弃。需要补一条允许从外网访问内网服务器80端口的策略:
security-policy rule name NAT_Server_Web source-zone untrust destination-zone trust destination-address 192.168.1.10 24 service tcp 8080 action permit这里有个容易混淆的细节:策略里的目的地址到底写公网地址还是内网地址?在不同版本上有差异。最稳妥的做法是造完NAT Server后,直接抓包或者用display nat server确认地址转换情况,在安全策略里同时放行目标为内网服务器IP的流量。很多新手的坑就是做完NAT、忘了配策略、然后开始怀疑命令敲错了,白折腾半天。
4. 配置完之后的验证与排错:不通别急着怪运营商
4.1 验证三层连通性
配置完成后,第一时间要做验证。我习惯分三层检查:先测出口设备的连通性,再测公网IP对应端口的连通性,最后测整个链路的服务可用性。
首先确认外网能到达你的出口设备。用手机流量(不要连着同一个WiFi)ping一下公网IP,能通说明链路基本正常。不过现在很多运营商封ping,ping不通不代表设备不可达,这时候改用在线端口检测工具,比如在浏览器里搜“端口扫描在线工具”,输入公网IP和8080端口,看端口是否开放。
端口显示开放,说明NAT Server已经生效。接着直接用手机浏览器访问http://公网IP:8080,能打开Web页面就大功告成。如果端口检测显示超时,但内网访问一切正常,那问题大概率出在NAT配置或者安全策略上,进入下一步排查。
4.2 从外网到内网逐段排查链路
外网访问不了,别急着打电话骂运营商,按从外向内的顺序逐段排查:
- 外网客户端是否能到达公网IP(ping/在线工具,排除运营商故障)。
- 公网IP的端口是否开放(排除端口被运营商封禁,注意很多宽带的80、443端口默认被封)。
- 出口设备上NAT Server条目是否生效,用
display nat server查看。 - 是否有安全策略放行(防火墙设备重点查)。
- 内网服务器上服务进程是否正常监听,Windows Server 2016上用
netstat -ano | findstr :80。 - 内网服务器自身防火墙是否放行了对应的入站请求。
这里面最常见的问题是第5条和第6条。很多人在Windows服务器上装好Web服务就用内网IP测试,一切正常就去做NAT,却忘了Windows防火墙默认会阻挡来自公网的入站连接。解决方法是到“高级安全Windows防火墙”里添加入站规则,放行TCP 80端口,或者临时把防火墙关闭测试一下。如果是Linux/armbian服务器,用netstat -tlnp | grep 80检查监听地址,再确认没有iptables规则挡在前面。
4.3 一个最容易忽视的坑:服务绑定在127.0.0.1
这个坑我踩过不止一次。很多服务默认监听地址是127.0.0.1,比如你在家里的armbian上装了某个自用面板,它能正常响应本机访问,但在内网其他机器上访问192.168.1.10就是连不上。原因在于服务只监听了回环地址,根本没有监听内网网卡地址。
NAT Server把流量转给192.168.1.10的80端口,可服务只监听127.0.0.1,等于前台把电话转给了那个分机,但分机没插线。排查时看netstat -tlnp输出,如果监听地址是127.0.0.1而不是0.0.0.0或具体网卡IP,就要去改服务配置文件,把监听地址改成0.0.0.0,然后重启服务。Windows Server 2016上也有对应场景,比如IIS站点绑定地址如果是127.0.0.1,外部一样访问不了,需要在绑定里改成“所有未分配”或具体内网IP。
5. 一台公网入口管多台内网服务器:多策略规划实操
5.1 多条NAT Server策略怎么落
很多人的需求并不是只映射一台服务器。家里有NAS、有开发板、有Windows测试机,都希望能从外网访问。这时只需要在同一条出口设备上添加多条NAT Server策略,让不同公网端口对应不同内网服务器即可。
我举一个实际规划例子:
| 公网端口 | 内网服务器 | 内网端口 | 用途 |
|---|---|---|---|
| 80 | 192.168.1.10 | 80 | Web主站 |
| 53389 | 192.168.1.15 | 3389 | Windows Server 2016远程桌面 |
| 22022 | 192.168.1.20 | 22 | Linux SSH |
对应华为路由器上的命令就是三条:
nat server protocol tcp global 203.0.113.1 80 inside 192.168.1.10 80 nat server protocol tcp global 203.0.113.1 53389 inside 192.168.1.15 3389 nat server protocol tcp global 203.0.113.1 22022 inside 192.168.1.20 22三条命令敲完之后,一台公网入口设备就管起了三台内网服务器。这里的关键是避免端口冲突,公网侧端口必须是唯一的,不能两条策略用同一个端口,否则后配置的规则可能不生效或者覆盖前面的规则。
5.2 端口规划:远程桌面和SSH的隐藏细节
多策略规划时,端口选择很讲究。远程桌面3389和SSH 22是公网扫描器最喜爱的端口,直接暴露出去等于告诉全世界的扫描机器人“这里有Windows服务器”或者“这里有Linux服务器”。我建议一律改成高位端口,比如刚才示例里的53389和22022,这样虽然不能完全避免扫描,但大多数基础扫描器只探测默认端口,能帮你过滤掉大量低水平流量。
另一个细节是,如果内网服务器上开了Windows防火墙,入站规则里放行的端口必须是服务器实际的监听端口3389,而不是公网侧的53389。NAT Server先把公网53389转换成内网3389,再进入Windows防火墙检查,所以防火墙规则放行3389即可。反过来,如果你在路由器上做了多个端口映射,但服务器防火墙只放行了特定来源IP,也要确认NAT转换后流量还能命中规则,必要时把来源IP写宽泛一点。
5.3 多出口场景下的回程路径问题
这是企业网络里才会遇到的高级坑,但值得提一下。如果出口设备有两条链路,比如一条电信一条联通,NAT Server映射的流量从电信口进来,但内网服务器回包时,路由表却说默认出口走联通,那么报文就会从联通口出去。这样做的结果是NAT会话不对称,客户端发出去的请求石沉大海,连接永远建立不起来。
解决办法有两种:一是给映射的内网服务器做策略路由,保证回程流量从同一出口设备转发;二是让NAT设备对映射流量做源地址转换,把回包引流回同一路径。家用路由器通常只有一条出口,不会遇到这个问题,但公司网络里多条出口链路很常见,配置前一定要留意回程路径。判断方法很简单,配好后从外网访问一次,在路由器上用display nat session查看会话表,看入接口和出接口是否一致,不一致就要去调路由。
6. 动态公网IP别怕:DDNS让NAT Server长期稳定可用
6.1 优先用路由器自带的DDNS
家用宽带的公网IP基本是动态的,光猫或者路由器每次重新拨号,IP就可能变化。IP一旦变了,你记录下来的http://203.0.113.1:8080就失效了。这个问题靠DDNS解决。
DDNS全称是动态域名解析,简单说就是每隔一段时间把当前IP上报给DNS服务商,让一个固定域名始终指向你当前的公网IP。大多数家用路由器都有DDNS功能,入口一般在“动态DNS”或者“DDNS设置”里,填上你在服务商注册的域名和账号,启用后路由器就会自动上报IP变化。
用起来之后,外网访问地址就变成http://你的域名:8080,IP怎么变都不用管。
6.2 路由器没有DDNS时的兜底方案
如果路由器太老,没有内置DDNS,也不用慌。只要你的内网环境里有一台Linux服务器,就能写个简单脚本定期检查公网IP,变了就调用DNS服务商的API更新域名记录,然后用cron定时跑:
#!/bin/bash CURRENT_IP=$(curl -s ifconfig.me) OLD_IP=$(cat /tmp/last_ip 2>/dev/null) if [ "$CURRENT_IP" != "$OLD_IP" ]; then # 调用你的DNS服务商API更新A记录,这里以通用思路示意 curl -X PUT "https://你的DNS服务商API/域名/A记录" \ -H "Authorization: Bearer 你的Token" \ -d "{\"value\":\"$CURRENT_IP\"}" echo "$CURRENT_IP" > /tmp/last_ip fi具体API格式看服务商文档,脚本思路是一致的:先查当前出口IP,再用上次记录的IP做对比,变了才更新,避免每次运行都去请求API。cron里设置每5分钟跑一次就够用了。这个脚本我也用在armbian上跑过,稳得很,半年没出过乱子。
6.3 动态IP环境下的定期巡检清单
DDNS解决了IP变化问题,但动态环境还有一些细节需要定期看。我给自己定了一个巡检清单:
- 每次宽带动IP后,域名解析是否在5分钟内更新(用
nslookup 你的域名查看)。 - NAT Server策略是否依然存在,部分路由器重启后会把NAT映射清掉,IP变了策略也可能丢失。
- 内网服务器IP是否因为DHCP租约变化而变了,如果服务器换了IP,NAT策略里的inside地址也要同步改。所以我强烈建议给内网服务器配置静态IP或DHCP保留地址,避免这种低级问题。
- 定期从外网访问一次域名加端口,确认服务正常。
7. 映射出去之后的安全加固:我踩过的坑不想你再踩
7.1 没改默认端口前,我被扫成了筛子
这里说点真实经历。我早期有一台Windows测试机,为了图方便,直接把3389映射到公网侧3389端口,没做任何额外防护。不到一天,Windows事件日志里就刷出了上千条来自世界各地IP的登录失败记录,有的尝试用户名是Administrator,有的是各种乱拼的账号名,全都是自动化扫描的暴力破解流量。
那一刻我才意识到,公网扫描器是无差别攻击的,你开一个默认端口,就等于在门口挂了一块“欢迎光临”的牌子。后来我立刻把公网端口改成高位端口,暴力破解流量立刻少了九成以上。这不是玄学,是因为绝大多数扫描器只做默认端口探测,改掉端口就能过滤掉大部分低水平攻击。
7.2 最小化暴露面:少映射、用高位端口
安全第一原则永远是减少暴露面。能映射一个端口就不要映射第二个,能映射TCP就不要映射ALL。比如你只打算远程桌面,就映射TCP 53389,不要图省事选择ALL协议。家用路由器有些地方会写“协议:ALL”,慎选,它会把TCP和UDP都映射出去,UDP端口一旦被滥用,排查起来更头疼。
同时建议关闭不必要的高风险服务。NAT Server只能做端口映射,它不会帮你过滤应用层漏洞,你暴露在公网上的服务本身必须足够安全。SSH启用密钥认证并关闭密码登录,Windows远程桌面使用强密码或者干脆配置网络级认证,这些基本功一定不能省。
7.3 用ACL做来源限制,只放开自己能用的IP
如果出口设备是防火墙或者企业级路由器,还可以通过ACL限制来源IP,让NAT映射只对特定IP开放。华为路由器上的做法是配置一条高级ACL,只允许你信任的来源地址访问映射端口,然后在NAT Server规则里调用:
acl number 3001 rule 5 permit ip source 203.0.113.0 24 rule 10 deny ip quit家用路由器很多没有这个功能,但如果你的办公出口IP是固定的,可以在路由器防火墙设置里找找有没有类似的“访问控制”选项。即使只能限制个别IP,也能极大降低被乱扫的风险。
7.4 保留日志和会话监控的习惯
最后一条容易被忽略:开启日志。华为USG上有display nat session可以查看当前NAT会话,如果某一天会话数量异常增长,往往意味着有人在尝试扫描你的映射端口。平时多看一眼会话表,多翻一翻安全日志,比等到服务被攻破再补救要省心得多。
家用路由器虽然没有企业级日志功能,但一般都能看到内网设备的连接记录,没事的时候瞄一眼,发现不认识的IP来源频繁访问,就该检查一下是不是有端口暴露过久或者服务被爆破成功了。
我自己现在维护的所有NAT映射,都会在设备上留一条清晰备注说明这个端口是给谁用的、对应哪台服务器、过期时间大概是什么时候,避免三个月后自己都分不清哪个端口通向哪台机器。先想清楚安全策略和端口规划再敲命令,比敲完再后悔靠谱得多。