Appearance
第 2 讲|服务器上公网
本机执行 curl http://127.0.0.1:8080 能正常返回,但换一台机器或换一个网络环境,同一个服务就连不上——这是第一次部署服务时几乎所有人都会遇到的场景。
根本原因是:服务在机器内部跑起来,与外部用户能访问到它,中间还隔着公网 IP、入口转发、端口监听、防火墙、安全组这一组关卡。任何一层断了,外部都无法访问。本讲依次讲清楚这些关卡,以及云上和机房环境的差异。

一、IP 地址类型:内网与公网
服务器通常有两种 IP 地址:内网地址和公网地址。两者在网络可达范围、用途、计费方式上完全不同。
内网 IP 的固定网段
由 RFC 1918 规定,以下三个网段是私有 IP,只能在局域网/机房/云 VPC 内部使用,无法在公网路由:
| 网段 | 范围 | 可用地址数 |
|---|---|---|
10.0.0.0/8 | 10.0.0.0 ~ 10.255.255.255 | 约 1677 万 |
172.16.0.0/12 | 172.16.0.0 ~ 172.31.255.255 | 约 105 万 |
192.168.0.0/16 | 192.168.0.0 ~ 192.168.255.255 | 约 6.5 万 |
看到 IP 是这三个网段开头的,基本可以判定是内网地址——同一 VPC/机房内的机器互通,但外部公网无法直接访问。
公网 IP
不属于上述三个私有网段的地址,统称为公网 IP——全世界唯一,理论上从任何能上网的位置都能访问。云服务器一般同时分配两种 IP:
- 内网 IP — 用于同 VPC 内机器之间互通(应用连数据库、应用调用内部 API),无流量费、低延迟
- 公网 IP — 用于接受外部用户的请求
生产环境的高频规范:应用服务器与数据库之间的通信必须走内网 IP,绝对不要走公网 IP。原因:
- 延迟:内网通常 < 1ms,公网几十到几百毫秒
- 流量费:云厂商对公网流量收费,内网免费
- 安全:数据库走公网就意味着暴露公网接口,极大增加被攻击的可能

云上公网 IP 的实现:EIP 与 NAT 映射
云上的公网 IP 不一定真正绑定在虚拟机的网卡上。两种常见实现:
| 实现方式 | 特征 | 典型云厂商 |
|---|---|---|
| EIP(Elastic IP) | 公网 IP 是独立资源,可以挂载/卸载到 ECS 上 | AWS EIP、阿里云 EIP |
| 直接绑定 | 公网 IP 由云平台在出口做 NAT 映射,机器内 ip addr 只看到内网地址 | 部分国内云厂商的"公网带宽"模式 |
第二种情况会让初学者困惑——ip addr 看不到公网 IP,但外部确实能通过公网 IP 访问。这是云平台在网关层做的 SNAT/DNAT 映射,对虚拟机内部透明。
验证一台云主机的公网 IP 实际工作方式:
bash
# 从外网角度看
curl -s https://api.ipify.org # 这个公网 IP 是云平台映射后的
# 从机器内部看
ip addr # 可能只看到内网 IP
二、机房环境与云上的概念对照
机房自建与云上部署在物理层面差异很大,但在抽象上是对应的:
| 机房组件 | 云上对应资源 | 职责 |
|---|---|---|
| 物理服务器 | ECS / CVM / 虚拟机实例 | 计算资源 |
| 公网出口线路 | EIP / 弹性公网 IP | 公网入口 |
| 防火墙策略 | 安全组 / 网络 ACL | 包过滤 |
| 内网网段 / VLAN | VPC / 子网 | 网络隔离 |
| 入口负载均衡设备 | SLB / ALB / CLB | 流量分发 |
| F5、A10 等专用硬件 | LB 服务 | 高性能负载均衡 |
理解这种对应关系的好处:机房经验可以直接迁移到云上,云上学到的设计模式也能应用到机房。任何一层的故障定位思路都是通用的。
公网请求的标准路径
外部请求进入服务的标准链路:
公网用户
↓
公网 IP (EIP)
↓
安全组规则 (云防火墙)
↓
VPC / 子网
↓
负载均衡 SLB (可选)
↓
ECS 虚拟机
↓
主机防火墙 (iptables / firewalld)
↓
服务进程 (监听端口)每一层都可能成为访问失败的卡点,排查时基本就是顺着这条链路逐层确认。
三、NAT:SNAT 与 DNAT
NAT(Network Address Translation,网络地址转换)是支撑"内网与公网互通"的核心机制。两种典型用法:
SNAT:让内网机器主动访问公网
许多内网服务器虽然没有公网 IP,但 yum install、docker pull、curl https://api.github.com 这些访问外网的操作都能成功——背后是 SNAT(Source NAT,源地址转换)在工作。
机制:内网机器的请求出去时,被网关(或专门的 NAT 服务器)把源地址从内网 IP 替换成网关的公网 IP,这样目标服务器才能正确回包。回包到达网关后,网关查询转换表,反向把目标地址改回内网 IP,转交给真正发起请求的机器。整个过程对内网机器透明。
DNAT:让公网用户访问内网服务
外部用户访问没有公网 IP 的内网服务,用的是 DNAT(Destination NAT,目的地址转换)。
机制:公网 IP 的某个端口被映射到内网某台机器的端口上。例如负载均衡器拿到访问公网 80 端口的请求,转给内网 10.0.1.10:8080。这是端口转发(port forwarding)、负载均衡、Kubernetes Service 等机制的基础。
SNAT 与 DNAT 的记忆方法
| 缩写 | 全称 | 替换什么 | 适用场景 |
|---|---|---|---|
| SNAT | Source NAT | 源地址 | "内网主动访问外网" |
| DNAT | Destination NAT | 目的地址 | "外网访问内网服务" |
记忆方法:S = Source,主动方向(我出去);D = Destination,被动方向(别人进来)。

四、端口与监听
公网 IP 能 ping 通不代表服务能访问——还需要端口这一层正确配置。从外部请求到达应用进程,需要四个位置都对得上:
1. 应用进程:必须监听在正确的地址和端口上
最常见的坑:服务监听了 127.0.0.1:8080 而非 0.0.0.0:8080。
127.0.0.1 与 0.0.0.0 的区别:
| 监听地址 | 含义 | 谁能访问 |
|---|---|---|
127.0.0.1:8080 | 仅本机回环 | 仅本机 |
0.0.0.0:8080 | 所有网卡 | 所有能访问该机器的 IP |
192.168.1.10:8080 | 特定网卡 IP | 仅能访问该 IP 的客户端 |
排查方式:
bash
ss -lntp | grep 8080
# 或
netstat -tlnp | grep 8080如果输出显示 127.0.0.1:8080,即使防火墙完全打开,外部仍然无法访问——必须修改服务配置,把监听地址改为 0.0.0.0:8080 或具体的网卡 IP。
2. 主机防火墙
Linux 上的防火墙工具:
iptables(传统,主流)firewalld(RHEL 系)ufw(Ubuntu 简化前端)nftables(新一代,替代 iptables)
任意一个工具阻拦了对应端口,外部都进不来。
3. 云安全组
云环境特有的一层——在云平台控制台配置的网络规则,作用于云内网络出入口,优先于主机内部的防火墙。
云安全组没放行的端口,流量在云平台层面就被丢弃,根本到不了虚拟机。这种情况下:
- 机器内的服务监听正常
- 主机防火墙开放
- 但外部访问仍然超时
诊断方法是用云控制台 VNC 登录机器从机器内部反向访问——如果机器内能访问、外部不能,基本就是安全组问题。
4. 入口转发
如果架构里有 Nginx、负载均衡器,要确认它们的转发配置指向正确的后端地址和端口。例如:
- Nginx
proxy_pass http://10.0.1.10:8080;— 后端地址写错会 502 - 负载均衡的 backend 配置 — 健康检查端口和路径必须可访问

五、按用户侧现象快速定位
把所有层串起来,根据用户看到的具体错误,可以快速定位故障层:
| 用户侧现象 | 大概率卡在哪 | 排查重点 |
|---|---|---|
域名报 NXDOMAIN | DNS | 域名解析记录、本地 DNS 缓存 |
| 浏览器一直转,最后超时 | 公网入口或网络层 | 公网 IP 可达性、安全组、防火墙、路由 |
立即返回 ERR_CONNECTION_REFUSED | 端口或服务 | 服务进程是否启动、是否监听对外地址 |
| 能连上但返回 404 | 路由 | Nginx 路由配置、后端路由表 |
| 返回 502 | 入口到后端 | Nginx error log、后端实例健康状态 |
| 接口慢或返回 504 | 后端处理 | 后端应用日志、数据库慢查询 |
实际排查的标准命令组合
新部署服务无法外部访问,从外到内依次诊断:
bash
# 1. 从外部访问点(本地电脑或另一台云主机)
curl -v http://公网IP:80 # 看连接是否建立、是哪种错
nc -zv 公网IP 80 # 单独测端口连通性
# 2. 从云内部访问(如同 VPC 的另一台机器)
curl -v http://内网IP:80 # 排除外网链路问题
# 3. 在目标机器本机访问
curl -v http://127.0.0.1:80 # 排除服务本身问题
# 4. 看服务监听情况
ss -lntp | grep ':80' # 是 0.0.0.0 还是 127.0.0.1?
# 5. 看主机防火墙
iptables -L INPUT -n -v # 计数器看包是否被丢
firewall-cmd --list-all # firewalld 规则
# 6. 看云控制台
# 安全组规则、网络 ACL、EIP 绑定状态按这个顺序排查,前一步通了再继续向内:外部不通就先查安全组、内网通就排除外网链路、本机通就查防火墙、本机也不通就查服务本身。一步一步收敛范围,比"凭直觉判断在哪一层"高效得多。
六、生产环境的端口暴露原则
新机器投入使用前,对监听的端口做一次审查——所有不需要暴露的端口都收紧。
bash
# 看本机所有监听
ss -lntup
# 应该只暴露业务需要的端口,例如:
# - 22 (SSH,且只允许跳板机 IP)
# - 80/443 (业务)
# - 服务自身的端口(必要时仅监听内网)常见错误示例:
| 服务 | 错误做法 | 正确做法 |
|---|---|---|
| Redis | 监听 0.0.0.0:6379 无密码暴露公网 | 监听内网 IP、设密码、安全组只放行应用 IP |
| MySQL | 监听 0.0.0.0:3306 直接对公网开放 | 仅内网监听,运维通过堡垒机访问 |
| 应用调试端口 | 测试用的 /debug 接口公网可访问 | 生产环境禁用或限制访问来源 |
| Docker daemon | 2375/tcp 暴露 | 仅本地 socket、TLS 加密 + 客户端证书 |
公网无认证的 Redis、Elasticsearch、MongoDB、Docker daemon 是最常见的被入侵入口——这类服务被扫描器持续扫描,默认配置就能直接连进去。任何"无认证的服务"都必须严格限制访问来源,绝不能裸暴露到公网。
