知乎问答-什么是内网穿透?如何实现无公网ip内网穿透?
要解答这个问题,我们要首先明白为什么要进行内网穿透?
主要是想通过互联网访问内网中的节点或者服务,使原来不可达的内部资源,变得可达。
将原来不可达的资源变为可达,大致有以下几种方式可以实现。
第一种:有公网 IP,直接做端口映射
这是最简单的一种情况。
假设家里有一台 NAS:
192.168.1.100
它运行了一个 Web 服务:
192.168.1.100:8080
这个地址只能在家里的局域网中访问。
如果家里的路由器拥有一个公网 IP,例如:
1.2.3.4
并且你能够配置这台路由器,那么完全可以做一条端口映射:
1.2.3.4:8080
↓
192.168.1.100:8080
这样互联网中的客户端访问:
1.2.3.4:8080
路由器就会把流量转发给内网中的 NAS。
严格来说,这种方式更准确地应该叫:
NAT 端口映射或者端口转发。
因为这里并没有什么神秘的“穿透”。
公网本来就能访问你的路由器,只不过需要告诉路由器:
收到这个端口的数据以后,应该转发给内网中的哪台机器。
真正麻烦的是:
你连这个公网 IP 都没有。
第二种:没有公网 IP,让内网设备主动连接出去
现在很多家庭宽带、移动网络甚至企业网络都会使用 CGNAT。
网络可能变成:
NAS
192.168.1.100
↓
家庭路由器
↓
运营商 CGNAT
↓
Internet
这时候真正的公网 IP 在运营商手里。
你能够管理自己的家庭路由器,却管理不了运营商的 NAT 设备。
所以即使你在家里的路由器上做了:
8080
↓
192.168.1.100:8080
互联网中的客户端依然找不到你。
因为在你的路由器之外,还有一层你无法控制的 NAT。
怎么办?
这里就出现了一个非常重要的思路:
既然互联网无法主动连接进来,那就让内网中的设备主动连接出去。
例如准备一台具有公网 IP 的服务器:
Public Server
1.2.3.4
然后让家里的 NAS 主动连接这台服务器:
NAS
192.168.1.100
│
│ 主动连接
▼
Public Server
1.2.3.4
因为“访问互联网”本来就是 NAT 最擅长处理的事情,所以这条连接通常能够正常建立。
连接建立以后,公网服务器就和内网设备之间有了一条已经存在的通信路径。
外面的电脑再访问公网服务器:
Laptop
↓
Public Server
↓
已经建立的连接
↓
NAS
这样,本来无法从互联网直接访问的 NAS,就变得可以访问了。
这也是 FRP、SSH Remote Forwarding、Cloudflare Tunnel 等很多方案背后的基本思路。
看起来是:
Internet
↓
Internal Host
但真正建立连接的方向其实是:
Internal Host
↓
Internet
这个区别非常重要。
所谓“穿透”,很多时候并不是从外面硬闯进 NAT,而是利用内网允许向外建立连接这个条件,反过来建立访问路径。
第三种:两个 NAT 后的设备直接通信——NAT Traversal
还有一种更有意思的情况。
假设 Alice 和 Bob 都没有公网 IP:
Alice
│
NAT A
│
▼
Internet
▲
│
NAT B
│
Bob
正常情况下:
Alice 不能直接连接 Bob。
Bob 也不能直接连接 Alice。
但是双方都可以主动访问互联网。
这时候可以先找一台公网服务器作为“介绍人”。
Alice 主动连接服务器,服务器就能看到 Alice 经过 NAT 以后表现出来的公网地址和端口。
Bob 也是如此。
例如:
Alice → 1.1.1.1:50001
Bob → 2.2.2.2:40001
公网服务器把双方的信息交换一下:
告诉 Alice:
Bob 在 2.2.2.2:40001
告诉 Bob:
Alice 在 1.1.1.1:50001
接下来 Alice 和 Bob 可以尝试同时向对方发送数据。
双方的 NAT 因为看到了主动发出的流量,就可能建立对应的 NAT 状态。
最终有机会形成:
Alice ←────────→ Bob
这就是 NAT Traversal 中常见的 Hole Punching,也就是“打洞”。
这里公网服务器可能只负责:
让两个人找到彼此。
真正的业务流量并不一定经过服务器。
可以把它理解成一个媒人:
Alice → 媒人 ← Bob
找到彼此以后:
Alice ←────→ Bob
这也是为什么很多 P2P、视频通信、游戏、虚拟组网产品都希望优先建立 Direct Connection。
因为一旦建立直接连接:
延迟通常更低;
速度通常更快;
服务器不需要承担所有业务流量。
如果打洞失败怎么办?
问题是:
NAT Traversal 并不是百分之百成功。
不同运营商、不同路由器、不同 NAT 类型、防火墙策略,都可能导致双方无法建立直接连接。
那么怎么办?
最简单粗暴的办法就是:
中继。
变成:
Alice
│
▼
Relay Server
│
▼
Bob
双方都主动连接公网服务器。
服务器负责把 Alice 的数据转给 Bob,再把 Bob 的数据转给 Alice。
于是:
Alice → Relay → Bob
Bob → Relay → Alice
这种方式的最大优势是:
简单,而且对网络环境要求比较低。
但是缺点也很明显。
所有流量都经过服务器。
所以速度会受到:
中继服务器带宽;
服务器所在地区;
运营商线路;
跨境网络;
服务器负载;
等因素影响。
这也是为什么有些免费的内网穿透服务:
能用,但是速度并不理想。
尤其是你的设备在中国,而中继服务器却在欧洲、美国甚至其他地区的时候,数据可能需要绕很远的路。
所以,无公网 IP 怎么实现内网穿透?
到这里答案其实已经很清楚了。
如果没有公网 IP,大致有三条思路:
无公网 IP
│
├── NAT Traversal 成功
│ ↓
│ P2P
│
├── 内网设备主动连接公网服务器
│ ↓
│ Reverse Tunnel
│
└── 无法直接通信
↓
Relay
对于普通用户来说,最简单的办法当然是直接使用成熟产品。
因为它们已经帮你处理好了:
NAT 探测;
节点发现;
Hole Punching;
加密;
身份认证;
中继;
连接保持;
这些问题。
你只需要安装客户端。
免费服务为什么可能比较慢?
如果打洞成功:
电脑 ←────────→ 家里 NAS
真正的数据基本直接走双方之间的网络。
这时候厂商服务器承担的流量很少。
但如果打洞失败:
电脑
↓
厂商服务器
↓
家里 NAS
所有数据都经过厂商服务器。
服务器带宽就是真金白银。
所以很多免费的内网穿透服务会:
限制带宽;
限制流量;
限制中继速度;
限制节点数量;
或者免费节点本身离你比较远。
这并不是技术上“穿不快”,而是:
只要业务流量需要经过第三方服务器,中继服务器的线路和带宽就会成为整个连接的一部分。
不想依赖第三方,可以自己买 VPS
如果对速度、稳定性和控制权要求比较高,也可以自己购买一台具有公网 IP 的 VPS。
例如:
VPS
1.2.3.4
让家里的机器主动连接 VPS:
Home Server
192.168.1.100
│
▼
VPS
1.2.3.4
然后外部访问:
Laptop
│
▼
VPS
│
▼
Home Server
这个时候:
公网节点是你自己的。
服务器放在哪里、带宽多少、走什么线路,都可以自己选择。
FRP 就非常适合做这种事情。
例如:
家里
frpc
│
▼
Internet
│
▼
VPS
frps
外面的客户端只需要访问 VPS,FRP 再通过已经建立好的连接,把流量转回内网。
这也是比较经典的自建内网穿透方式。
最后再重新理解一下“内网穿透”
很多人第一次接触内网穿透时,会觉得:
NAT 后面的机器明明不能被访问,软件到底是怎么“穿”进去的?
其实理解 NAT 以后就会发现,并没有那么神秘。
核心无非是利用了几种办法:
有公网 IP
→ 端口映射
无公网 IP
→ 内部主动建立连接
两个 NAT 后节点
→ NAT Traversal / Hole Punching
直接连接失败
→ Relay
不想用别人的服务器
→ VPS 自建
所以我更愿意把内网穿透理解成:
当一个内部节点没有直接的公网入站路径时,想办法重新为它建立一条从外部可达的通信路径。
而不是某一个具体软件或者协议。
FRP、Tailscale、ZeroTier、Cloudflare Tunnel,甚至 SSH 的 Remote Port Forwarding,采用的技术路线可能完全不同。
它们真正共同解决的,只有一个问题:
原本从互联网访问不到的东西,怎么让它变得可以访问。
但最后还要补一句。
能够访问,和能够安全地访问,是两回事。
一旦你把一个原来封闭在内网里的服务变得互联网可达,也就相当于改变了原来的网络边界。
认证、授权、加密、暴露范围和访问日志,这些问题也必须一起考虑。
所以内网穿透真正解决的只是:
可达性。
至于安全性,则是另外一个问题。