1. 先把概念理清楚:公网、私网、内网、外网到底在说什么
很多人第一次接触这几个词,是在配路由器、连 NAS、搭开发环境或者调试服务器的时候。明明感觉自己懂一点网络,结果一看到“公网 IP”“内网穿透”“NAT 模式”就懵了。更麻烦的是,这几个词在日常交流里经常被混着用,不同人说“内网”的时候,指的可能完全不是一回事。
我自己就踩过这个坑。早些年帮朋友调一台家里的存储设备,他说“你从外网连一下试试”,我理解成从公网访问,结果他其实只是想让我从另一个房间的电脑连过去。两个人鸡同鸭讲了半天,最后发现是概念没对齐。所以这篇文章我打算把公网、私网、内网、外网这四个词彻底拆开讲清楚,顺便把 NAT、内网穿透、DDNS 这些绕不开的配套概念也一并说透。
先给一个最粗的框架,方便你建立第一印象:
- 公网:全球唯一的地址空间,任何人都能路由到达。
- 私网:专门保留出来、不在公网路由的地址段,只能在局部网络里用。
- 内网:一个组织或家庭内部的网络,通常用私网地址。
- 外网:相对“内网”而言的外部网络,可能是公网,也可能是上级网络。
你看,公网和私网是地址属性的区分,内网和外网是相对位置的区分。这两组概念经常被绑在一起说,但本质上不是一回事。搞混这一点,后面所有的困惑都从这里来。
这篇文章适合谁看?如果你是刚入行的运维、后端开发、嵌入式工程师,或者只是想把家里的 NAS、开发板、小服务器连起来玩的爱好者,那这篇内容基本能覆盖你 90% 的疑问。我会从原理讲到实操,从地址规划讲到内网穿透方案选型,尽量让你看完就能动手。
2. 公网与私网:地址层面的本质区别
2.1 公网 IP 到底是什么,为什么它这么稀缺
公网 IP 的本质是“全球唯一且可被路由”。你可以把它想象成现实世界里的门牌号:快递员只要知道这个号码,就能把包裹送到。互联网上的数据包也一样,只要目标地址是公网 IP,理论上世界上任何一台联网设备都能把数据发过去。
IPv4 的公网地址总量是 2 的 32 次方,大约 43 亿个。这个数字在互联网早期看起来很多,但架不住设备爆炸式增长。手机、电脑、平板、摄像头、智能音箱、车机,全都要地址。于是公网 IPv4 早就分配殆尽了,这也是为什么现在家庭宽带拿到的几乎都是私网地址,而不是公网地址。
这里有个关键点很多人不知道:你从运营商那里拿到的“宽带 IP”,大概率不是公网 IP。运营商在骨干网和你的光猫之间又做了一层 NAT,把你放在了一个更大的私网里。这就是所谓的“大内网”或“运营商级 NAT”。所以你在路由器后台看到的 WAN 口 IP,可能是一个 100.64.x.x 开头的地址,那是运营商内部使用的保留段,不是真正的公网。
判断自己是不是公网 IP,有个很简单的办法:登录路由器,看 WAN 口 IP,然后去任意一个查 IP 的网站看显示的地址。如果两个一致,大概率是公网;如果不一致,那就是被 NAT 了。这个方法不是 100% 准确,但足够日常判断。
2.2 私网地址段:三个保留区间和它们的设计逻辑
私网地址是专门从 IPv4 空间里划出来、不在公网路由的段。RFC 1918 定义了三个区间:
| 地址段 | 范围 | 常见用途 |
|---|---|---|
| A 类 | 10.0.0.0/8 | 大型企业、云内网、容器网络 |
| B 类 | 172.16.0.0/12 | 中型网络、Docker 默认网段 |
| C 类 | 192.168.0.0/16 | 家庭、小型办公室 |
为什么是这三段?因为当年划分地址时,预留了一部分给“私有使用”,避免和公网地址冲突。任何路由器在公网出口都不会转发目标地址是这些段的包,所以你在家里用 192.168.1.1,隔壁老王也用 192.168.1.1,完全不会打架。
这里有个实操细节:Docker 默认会占用 172.17.0.0/16,如果你公司内网恰好也用了 172.17 段,就会冲突。我遇到过好几次,容器起不来,排查半天发现是网段撞了。解决办法是改 Docker 的默认网段,在/etc/docker/daemon.json里加:
{ "bip": "172.31.0.1/24", "default-address-pools": [ {"base": "172.30.0.0/16", "size": 24} ] }改完重启 Docker 服务,冲突就解决了。这个坑在云服务器上尤其常见,因为很多云厂商的 VPC 默认就用 172.16 段。
2.3 公网和私网之间怎么通信:NAT 的核心作用
公网和私网不能直接互通,中间必须有个“翻译官”,这就是 NAT(网络地址转换)。NAT 的工作方式,你可以理解成公司前台:外面的人打电话进来,前台根据分机号转接;里面的人打出去,前台把主叫号码换成公司总机。
最常见的 NAT 是SNAT(源地址转换),也就是你家里的路由器干的事。你的电脑用 192.168.1.100 访问百度,路由器把源地址换成自己的公网 IP,再加一个端口号做标记,百度回包时路由器根据端口号把包转回给你的电脑。整个过程你的私网地址对外是不可见的。
还有DNAT(目的地址转换),用于把外部请求转发到内部某台机器。比如你把路由器的 8080 端口映射到内网 NAS 的 80 端口,外部访问公网 IP:8080 就能打开 NAS 页面。这就是常说的“端口映射”或“端口转发”。
NAT 带来的一个副作用是:外部无法主动发起连接到内部。因为 NAT 表里没有对应的映射记录,包不知道该转给谁。这就是为什么家里没有公网 IP 时,外面连不进来,必须靠内网穿透或者反向连接来解决。
3. 内网与外网:相对位置带来的理解差异
3.1 内网不是“私网”的同义词
很多人把内网和私网画等号,其实不准确。内网强调的是“位置”,私网强调的是“地址属性”。一个内网可以用公网地址,一个私网也可以跨多个内网。
举个真实场景:某公司申请了一段公网 IP,内部服务器直接用公网地址互联。从地址看是公网,但从网络位置看,它们仍然是“内网”,因为不对外提供服务,外面也访问不到。反过来,你家里用 192.168.1.0/24,这是私网,同时也是你家的内网。
所以当你听到“内网”这个词,先问一句:是相对于谁的内网?是相对于公网的内网,还是相对于某个上级网络的内网?这个上下文决定了它到底指什么。
3.2 外网的多重含义:从公网到上级网络
“外网”这个词更模糊。在家庭场景里,外网通常指公网;在企业场景里,外网可能指公司总部网络、云上 VPC,或者任何当前网络之外的地方。
我见过最典型的混淆是:开发说“这个服务要能访问外网”,运维理解成“要能访问公网”,结果开发其实只是想访问公司另一个机房的服务。两边都没错,但理解不一致,最后配置出来的东西就不是想要的。
一个实用的判断方法是:看路由表。你的设备能到达哪些网段,哪些就是“可达的外网”。如果默认路由指向公网网关,那外网就是公网;如果默认路由指向公司核心交换机,那外网就是公司其他网段。
3.3 一张表把四个概念彻底分开
| 概念 | 本质 | 判断依据 | 典型例子 |
|---|---|---|---|
| 公网 | 地址属性 | 全球唯一、可路由 | 8.8.8.8、云服务器公网 IP |
| 私网 | 地址属性 | 保留段、不可公网路由 | 192.168.1.1、10.0.0.1 |
| 内网 | 相对位置 | 当前网络内部 | 家庭局域网、公司办公网 |
| 外网 | 相对位置 | 当前网络外部 | 公网、上级网络、其他机房 |
这张表建议你存下来。以后遇到任何网络问题,先按这两组维度定位,基本不会跑偏。
4. 内网穿透与 NAT 打洞:没有公网 IP 时怎么办
4.1 为什么需要内网穿透
没有公网 IP,外部就主动连不进来。但现实需求很多:在外面访问家里 NAS、给客户演示本地开发的服务、远程调试嵌入式设备。这些都需要把内网服务暴露出去,于是就有了内网穿透。
内网穿透的核心思路是:由内网主动向外建立连接,保持通道,外部请求通过这个通道转发进来。因为是由内向外发起的,NAT 表里有记录,所以能通。这就像你给前台打了个电话说“我一直在线上,有找我的人直接转给我”,而不是等别人打进来。
4.2 常见方案对比:frp、ngrok、cpolar、EasyTier
| 方案 | 部署方式 | 是否需要公网服务器 | 适用场景 |
|---|---|---|---|
| frp | 自建 | 需要 | 长期稳定、可控性强 |
| ngrok | 托管 | 不需要 | 临时演示、快速验证 |
| cpolar | 托管 | 不需要 | 个人用户、轻量使用 |
| EasyTier | 自建/托管 | 视模式而定 | 组网、多节点互联 |
frp 是我用得最多的。它的原理很简单:你在公网服务器上跑 frps,在内网机器上跑 frpc,frpc 主动连 frps,建立隧道。外部访问 frps 的某个端口,流量就通过隧道转到内网。配置也不复杂,frps 端一个frps.toml,frpc 端一个frpc.toml,填好地址、端口、token 就能跑。
ngrok 和 cpolar 属于托管服务,省去了自己买服务器的麻烦,但免费版通常有带宽和连接数限制,适合临时用。EasyTier 更偏向组网,适合多台设备互联,不是单纯的端口暴露。
4.3 实操:用 frp 把内网 Web 服务暴露出去
假设你有一台公网服务器1.2.3.4,内网有一台机器跑着 Web 服务在 8080 端口。步骤如下:
第一步,在公网服务器下载 frp 并解压,编辑frps.toml:
bindPort = 7000 auth.token = "your_token_here"启动 frps:
./frps -c frps.toml第二步,在内网机器编辑frpc.toml:
serverAddr = "1.2.3.4" serverPort = 7000 auth.token = "your_token_here" [[proxies]] name = "web" type = "tcp" localIP = "127.0.0.1" localPort = 8080 remotePort = 8080启动 frpc:
./frpc -c frpc.toml第三步,外部访问1.2.3.4:8080,就能看到内网的 Web 服务了。
注意:公网服务器的防火墙和安全组要放行 7000 和 8080 端口,否则连不上。这个坑我踩过,排查了半天以为是 frp 配置问题,结果是云厂商安全组没开。
4.4 NAT 打洞和 UPnP:另一条路
除了内网穿透,还有 NAT 打洞。原理是双方通过一个公网服务器交换各自的 NAT 映射信息,然后尝试直接建立连接。如果 NAT 类型允许,就能点对点直连,不经过中转,速度更快。
UPnP 则是让内网设备自动向路由器申请端口映射。很多下载工具、游戏主机都用这个。但 UPnP 有安全风险,因为它允许内网程序随意开端口,企业环境通常禁用。家庭环境可以用,但要清楚开了什么。
5. 动态公网 IP 与 DDNS:让地址变化不再是问题
5.1 动态公网 IP 的现实
即使你拿到了公网 IP,大概率也是动态的。运营商会定期更换,或者重拨后变化。这对需要固定地址的服务很不友好。解决办法就是 DDNS(动态域名解析)。
DDNS 的思路是:域名固定,IP 变化时自动更新解析记录。你在路由器或内网机器上跑一个 DDNS 客户端,定期检测公网 IP,发现变化就调用域名服务商的 API 更新 A 记录。这样你始终用域名访问,不用关心 IP 变成什么。
5.2 实操:用脚本实现 DDNS
以某域名服务商为例,写一个简单的 shell 脚本:
#!/bin/bash DOMAIN="nas.example.com" RECORD_ID="your_record_id" API_TOKEN="your_token" LAST_IP_FILE="/tmp/last_ip.txt" CURRENT_IP=$(curl -s https://api.ipify.org) LAST_IP=$(cat $LAST_IP_FILE 2>/dev/null) if [ "$CURRENT_IP" != "$LAST_IP" ]; then curl -s -X PUT "https://api.example.com/records/$RECORD_ID" \ -H "Authorization: Bearer $API_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"value\":\"$CURRENT_IP\"}" echo $CURRENT_IP > $LAST_IP_FILE fi加到 crontab 里每 5 分钟跑一次:
*/5 * * * * /path/to/ddns.sh这个方案简单可靠,适合家庭 NAS 场景。注意 API Token 要保管好,别提交到公开仓库。
5.3 申请公网 IP 的经验
不同地区、不同运营商政策不一样。有的直接给,有的要打电话申请,有的要升级套餐。我的经验是:先打客服电话,说明需要公网 IP 用于远程访问,态度好一点,多数情况能办。如果客服说没有,可以试试换时间段再打,或者去营业厅问。
拿到公网 IP 后,记得确认是 IPv4 还是 IPv6。现在很多地区 IPv6 已经普及,而且 IPv6 地址充足,基本人人都有公网 IPv6。如果你的设备和服务支持 IPv6,直接用 IPv6 可能比折腾 IPv4 公网更省事。
6. 常见问题与排查技巧实录
6.1 排查思路:从下往上,逐层验证
网络问题排查最忌讳瞎猜。我的习惯是从物理层往上查:网线、网卡、IP 配置、网关、DNS、路由、防火墙。每一层确认通了再往上走。
具体到“外网访问不了内网服务”这个问题,按这个顺序查:
- 内网机器本身服务是否正常?
curl localhost:8080试试。 - 内网其他机器能否访问?
curl 192.168.1.100:8080。 - 路由器端口映射是否配置正确?
- 公网 IP 是否真的可达?从外部 ping 一下。
- 防火墙、安全组是否放行?
- 运营商是否封了对应端口?80、443、8080 常被封。
6.2 常见问题速查表
| 问题 | 可能原因 | 解决办法 |
|---|---|---|
| 外部 ping 不通公网 IP | 运营商封 ICMP、防火墙拦截 | 换 TCP 测试,检查防火墙 |
| 端口映射无效 | NAT 回流未开、映射配置错 | 开 NAT 回流,核对内外端口 |
| DDNS 不更新 | 脚本权限、API 变更 | 手动跑脚本看报错,检查 Token |
| frp 连不上 | 安全组、token 不匹配 | 检查端口放行和配置文件 |
| Docker 网段冲突 | 与内网网段重叠 | 改 daemon.json 的 bip |
| WSL 代理不生效 | NAT 模式限制 | 改用镜像网络模式或手动配代理 |
6.3 几个容易忽略的坑
NAT 回流:很多路由器默认不开 NAT 回流,导致内网用公网 IP 访问自己的服务失败。开了之后,内网访问公网 IP 也能正确转发。这个在企业环境很常见,绿盟等设备上都有相关配置。
光猫路由 NAT 模式下的 DNS 延迟:光猫同时做路由和 NAT 时,DNS 转发可能变慢。解决办法是把光猫改桥接,用自己路由器拨号,DNS 也由自己控制。
WSL 的 localhost 代理问题:WSL2 默认 NAT 模式,Windows 上的代理不会自动镜像到 WSL。要么改镜像网络模式,要么在 WSL 里手动配代理环境变量。
内网机器下载依赖慢:纯内网环境装 nginx、uv 这些工具,要么配内网源,要么用离线包。我一般提前在有网的机器上下好,再拷进去。
7. 内网环境下的开发与部署实践
7.1 纯内网安装软件的通用套路
纯内网环境没有外网,装软件是个麻烦事。通用套路是:在有网的机器上下载好所有依赖,打包拷进去,再本地安装。
以 RHEL 6.10 配外网 yum 为例,如果完全没外网,可以搭一个本地 yum 源。把 ISO 挂载,配 repo 文件指向本地路径,就能用 yum 装了。aarch64 架构装 nginx 也是类似,找对应架构的 rpm 包,rpm -ivh安装,缺依赖就补依赖。
pnpm 项目迁移到内网,关键是node_modules和 pnpm store。把 store 一起拷过去,配好.npmrc指向内网 registry,基本能跑。GitLab 内网安装也是,提前下好 omnibus 包,装完再配。
7.2 内网文件共享与协作
内网文件共享有很多方案。简单点用 Samba,Windows 和 Linux 都能访问。复杂点用 Nextcloud,功能全但部署重。还有 Raidrive 这类工具,可以把内网存储挂载成盘符,用起来像本地磁盘。
如果只是临时传文件,起个 Python HTTP 服务最快:
python3 -m http.server 8000内网其他人访问http://你的IP:8000就能下载。简单粗暴,但很有效。
7.3 内网安全的基本意识
内网不等于安全。内网渗透、横向移动这些攻击手法很常见。基本措施要有:内网分段、最小权限、日志审计、定期扫描。
内网横向渗透的告警信息通常表现为:异常端口扫描、异常登录、异常进程。发现这些要及时排查。别觉得内网就高枕无忧,很多大事故都是从内网一台机器被拿下开始的。
8. 我个人的一些经验体会
折腾网络这些年,最大的体会是:概念清晰比技术细节更重要。公网、私网、内网、外网这四个词,只要你能准确区分“地址属性”和“相对位置”这两个维度,后面所有的问题都能自己推导出来。
第二个体会是:先确认需求,再选方案。是要长期稳定还是临时用?是有公网服务器还是纯内网?是单服务还是多设备组网?这些问题的答案直接决定你该用 frp 还是 ngrok,该自建还是托管。
第三个体会是:排查问题要有层次。从物理层到应用层,一层层确认,别跳步。我见过太多人一上来就怀疑配置,结果发现是网线没插好。
最后分享一个小技巧:家里如果 IPv6 可用,优先用 IPv6。现在大部分运营商都给了公网 IPv6,地址充足,不用 NAT,直接就能访问。很多路由器也支持 IPv6 防火墙放行,配置比 IPv4 端口映射简单得多。这个方向值得花点时间研究,能省掉不少内网穿透的麻烦。