内网穿透
在任何地方,通过网络可以访问家里笔记本上的应用服务?
内网穿透,也即NAT穿透,为了使某一特定源IP地址和源端口号的数据不被NAT设备屏蔽而正确路由到内网主机。
参考链接:[译] NAT 穿透是如何工作的:技术原理及企业级实践(Tailscale, 2020) (arthurchiao.art)
在两台经过 NAT 的机器之间建立 点对点连接
- IP有两种,IPV4、IPV6;只有IPV4会有内网穿透的情况;
- NAT:一个区域内的所有设备连在一起并统一和主干道上其他区域设备联系,对外只共用一个公网IP来标识自己,对内则分配一些够用的私有地址;
- NAT做的事情:私有IP+端口《--》公网IP+端口
- 识别一个连接只需5元组即可:
协议、源地址、源端口、目的地址、目的端口
- 内网穿透,本质就是对公网IP或者端口做文章,从而实现自定义访问
购买公网ip
- 一台自己拥有的能够操作的、具有公网IP的机子A(物理机、虚拟机都可以);
- 需要进行端口映射/转发,让本地局域网的机子和机子A建立联系,从而实现内网穿透;
- nat123、花生壳、frp、只要是类似的,都是这种模式:使用其他能操作的公网ip进行转发;
直连公网主机端口
- 一般情况下,NAT转换出去的端口是随机的,但你我们手机或电脑上玩的各种软件是可以和他们自己的服务器进行双向通信的;
- 在他们通信的时候,相互获取了对方的公网IP+端口(有些app是固定的域名);
- p2p连接,还是VPN,只要是类似的,就是这种模式;
- 在两端都安装使用辅助的客户端才行(可以理解为获取对方地址相互连接,甚至还可以加密提高安全性);
P2P(直连)
- 协议应该基于 UDP:TCP 的实现过于复杂,可使用 QUIC 获取面向流的连接;
- 对收发包的 socket 有直接控制权:必须在使用的“主要”协议之外,发送和接收额外的数据包。
UDP打洞(UDP hole punching)
只有当两个NAT都是Cone NAT(或者非NAT的防火墙)时才能工作。
- 因为内网的同一个 IP:Port 会被映射到NAT上的同一个 IP:Port
P2P通信技术,被广泛采用的,名为“P2P打洞“。
P2P打洞技术依赖于通常防火墙和cone NAT
允许正当的P2P应用程序在中间件中打洞且与对方建立直接链接的特性。
- 客户端A无法和客户端B直接建立一个UDP通信会话。如果A直接给B的公网地址
138.76.29.7:31000
发送UDP数据,NAT B将很可能会无视进入的数据(除非是Full Cone NAT),因为源地址和端口与S不匹配,而最初只与S建立过会话。B往A直接发信息也类似; - 假设A开始给B的公网地址发送UDP数据的同时,给服务器S发送一个中继请求,要求B开始给A的公网地址发送UDP信息。A往B的输出信息会导致NAT A打开一个A的内网地址与与B的外网地址之间的新通讯会话,B往A亦然。一旦新的UDP会话在两个方向都打开之后,客户端A和客户端B就能直接通讯,而无须再通过引导服务器S了。
如何获取NAT的外网地址和端口号?
Server通过登陆消息的IP头和UDP头得到该客户端的外网相关信息。
STUN 基于一个简单的观察:从一个会被 NAT 的客户端访问公网服务器时, 服务器看到的是 NAT 设备的公网 ip:port 地址,而非该 客户端的局域网 ip:port 地址。
Frp 代理(中继)
在某些场景中,直接访问 socket 这一条件可能很难满足。
退而求其次的一个方式是设置一个 local proxy(本地代理),主协议与这个 proxy 通信 ,后者来完成 NAT 穿透,将包中继(relay)给对端。这种方式增加了一个额外的间接层 ,但好处是:
- 仍然能获得 NAT 穿透,
- 不需要对已有的应用程序做任何改动。
原理
- frps 监听端口17000端口(对内端口),等待fprc的连接
- frpc会请求frps:17000端口,并建立TCP连接,此后会一直维持这个链接, 因为后面所有客户端请求frpc后面的服务时,数据都会通过这个TCP连接进行,而不再建立新的连接。
- frpc连接到服务端的对内端口17000,同时告诉frps要监听的对外端口17001和转发类型http;
- frps服务端fork新的进程监听客户端对外端口17001;
- 外网客户1请求frps:17001时,frps会把数据转发17000(对内端口)给frpc,frpc会把数据发给22端口服务ssh