Skip to content

服务器上公网

本机打开 http://127.0.0.1:8080 能跑,换个网络环境或者别人电脑就连不上——这个问题困扰过每一个第一次部署服务的人。原因其实就一句话:程序跑起来不等于外部能访问,中间还隔着公网地址、入口转发、端口监听、防火墙、安全组这一堆关卡,任何一层断了外部都进不来。

一、IP 地址类型

服务器一般有两种 IP:内网的和公网的。内网地址有几个固定网段,10.x.x.x172.16.x.x192.168.x.x——只要看到这三个开头,基本就是内网地址,只能在公司网络、机房或者云的 VPC 内部用,出了这个范围连不上。

公网地址就不一样了,全世界唯一、谁都能访问。云服务器一般两种都给:内网 IP 用于同 VPC 内机器互通(比如应用连数据库走内网,快又省钱),公网 IP 用于接外部用户的请求。

这里有个容易绕的细节:有些云厂商(尤其是国内厂商)的公网 IP 不是真的绑在网卡上,而是在云网络里做了一层映射。所以你 ip addr 看到的是内网地址,但外部访问公网 IP 流量能进来——中间这层映射是云平台在出口做的。在阿里云、华为云这种厂商上挺常见,AWS 那种弹性公网 IP(EIP)则是另一种实现,但用户侧看起来都差不多。

二、公网入口组件

如果是机房自建,公网入口通常是这么一条链路:运营商拉过来的光纤 → 防火墙 → 核心交换机 → 负载均衡设备 → 内网服务器。每一段都要配,任何一段断了服务就废了。

云上把这些物理设备都抽象成了控制台资源,概念对照大概是:

机房里叫什么云上叫什么
物理服务器ECS、CVM、虚拟机
公网出口线路弹性公网 IP、EIP
防火墙策略安全组、网络 ACL
内网网段和 VLANVPC、子网
入口负载均衡设备SLB、ALB、CLB

外部请求进来大概的路径是:先到公网 IP → 过安全组规则 → 进 VPC → 到负载均衡或者直接到机器 → 最终到跑服务的进程或容器。每一步都可能成为访问失败的卡点,排查时基本就是顺着这条链路找。

三、NAT

有个反直觉的现象:很多内网服务器明明没有公网 IP,但 yum installdocker pullcurl https://api.github.com 这些访问外网的操作都能成功。原因是出口做了 SNAT——内部机器的请求出去时,被网关把源地址从内网 IP 替换成了一台带公网 IP 的设备的地址,这样外部就能回包,回来之后再做反向替换转给真正发起请求的机器。整个过程对内网机器透明。

反过来,如果外部要访问一个没公网 IP 的内网服务,用的是 DNAT——公网 IP 的某个端口被映射到内网某台机器的端口上。比如负载均衡器拿到公网 80 端口的请求,转给内网 10.0.1.10:8080,这就是 DNAT 的一种典型应用。

记忆方法也简单:SNAT 是 Source(源地址)被替换,所以是"我主动出访"的场景;DNAT 是 Destination(目标地址)被替换,所以是"别人来访问我"的场景。

四、端口与监听

公网 IP 能 ping 通不代表服务能访问——还得看端口这一层。一个请求能从外部打到应用进程,要在四个位置都对得上:

  • 应用进程:必须监听在正确的地址和端口上。比如 0.0.0.0:8080 表示监听所有网卡的 8080;如果只监听 127.0.0.1:8080,那就只有本机能连,外部永远进不来
  • 主机防火墙:Linux 上的 iptables、firewalld、ufw 这些,要把对应端口放进来
  • 云安全组:云控制台里的安全组规则,必须显式放行来源 IP 段和端口——这条忘了的话,机器里端口监听正常、防火墙也开了,但外部还是连不上,因为流量在云网络那一层就被丢了
  • 入口转发:如果前面挂着 Nginx 或者负载均衡,要确认它的转发配置指向了正确的后端地址和端口

127.0.0.1 vs 0.0.0.0 这个坑非常常见。本地 curl 127.0.0.1:8080 能通,部署上去外部访问就不行——十有八九是服务只监听了 127.0.0.1netstat -tlnp | grep 8080 看一眼,如果显示 127.0.0.1:8080 就是这个问题,改成 0.0.0.0:8080 重启就好。

五、访问链路

把前面的层都串起来,用户从浏览器访问一个域名到最终拿到响应,经过的链路大概是:

排查"用户访问不了"这种问题,根据用户侧看到的现象,基本能定位到链路的哪一段:

用户侧现象大概率卡在哪
域名报 NXDOMAINDNS 记录没配或者过期,问题在域名这一层
浏览器一直转、最后超时公网 IP 不通、路由问题、安全组没放行、防火墙拦了
立即返回连接被拒绝(ERR_CONNECTION_REFUSED)端口没监听、服务没起来
能连上但返回 404路径没匹配上,问题在 Nginx 路由或者后端接口
返回 502入口连不上后端,问题在 Nginx 到应用这一段

记住这张表的好处是:用户给你一个截图或者一句描述,你大致就知道该往哪一层查,不用一上来就 ssh 进机器瞎翻日志。这也是为什么前面要把每一层都拆开讲——不是为了背概念,是为了排查的时候能精准定位。