主机没有公网 IP 时,进行内网穿透的方法主要有两种:
NAT 及穿透原理
本节部分图片文字转自文章:NAT基本原理及穿透详解(打洞),P2P Communication Across NAT
NAT(Network Address Translation) 用来将内网地址和端口号转换成合法的公网地址和端口号,建立一个会话,与公网主机进行通信。NAT的使用是为了解决公网IP有限及局域网安全性的问题。
NAT工作原理:
-
网络被分为内网和公网两个部分,NAT网关设置在私网到公网的路由出口位置,双向流量必须都要经过NAT网关;
-
网络访问只能先由私网侧发起,公网无法主动访问私网主机;
-
NAT网关在两个访问方向上完成两次地址的转换,出方向做源信息替换,入方向做目的信息替换;
-
NAT网关为了实现双向翻译的功能,需要维护一张关联表,把会话的信息保存下来。
NAT将内部网络的信息隐藏和转换,如果要实现隐藏在NAT下的设备之间通信(对等网络传输)则必须穿透NAT。
常规不同 NAT 设备下的穿透原理示意图如下,更详细的说明可以看这篇文章。
本地部署 Zerotier
内网穿透的常用工具有 frp、zerotier、花生壳等,下面记录本地部署 zerotier 组网完成内网穿透的过程。
刚开始参考教程完成了部署,但鉴于此教程较老,仓库 zerotier-planet和docker-zerotier-moon 已不在维护,更换新的仓库实现可快速部署。
Planet
私有部署 Planet 服务(实际是 Planet + Network Controller UI),实现节点由自己的 Planet 控制,不经过官方的海外节点,更稳定。
docker-zerotier-planet 用 docker 打包了 ZeroTierOne 和后台控制界面 ztncui,一键执行脚本即可。
在服务器防火墙(安全组)放行 planet 端口,下载 /tmp/planet
到本地,并为控制台端口添加域名方便访问(可部署完成后再做)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
# /etc/nginx/sites-available/zerotier.conf
server {
listen 443 ssl http2; # 监听443端口
server_name domain;
# SSL证书和私钥,通过域名服务商获得,然后上传到 /etc/nginx 目录
ssl_certificate domain_bundle.crt;
ssl_certificate_key domain.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://localhost:port;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# HTTP 请求自动跳转 HTTPS
server {
listen 80;
listen [::]:80;
server_name domain;
return 301 https://$server_name$request_uri;
}
|
输入对应网址进入控制台界面,完成用户登录、密码修改、网络创建。
下面进行客户端设置,参考文档替换ZeroTier工作目录下自带的 planet
后启动服务即可。
放行 Moon 端口,把客户端加入到网络后进行测试,可看到 PLANET
节点和本地 LEAF
节点。
1
2
3
4
5
|
$ zerotier-cli peers
200 peers
<ztaddr> <ver> <role> <lat> <link> <lastTX> <lastRX> <path>
824ab2729c 1.10.2 PLANET 39 DIRECT 10120 10120 47.98.50.118/9994
c86faa197d 1.12.2 LEAF 8 DIRECT 10292 10285 114.212.83.66/64107
|
Moon
当结点之间无法“打洞”成功实现 P2P 直接连接时,会退而求其次使用中继服务器(Moon)以转发的方式进行数据传输,我们可以设置自己的私有 Moon 服务器(Private Root Servers)。下面使用 docker-zerotier-moon 快速部署。
seedgou/zerotier-moon 目前仍在维护可以使用
1
2
3
4
5
|
# 创建容器
docker run --name zerotier-moon -d --restart always -p 9993:9993/udp -v /etc/ztconf:/var/lib/zerotier-one seedgou/zerotier-moon -4 [公网ip:x.x.x.x]
# 查看 moon ID
docker logs zerotier-moon
|
在客户端加入 Moon 服务器后,查看当前网络节点,可见 MOON
已经连接。
1
2
3
4
5
6
7
8
9
|
# 加入 moon 服务器
$ zerotier-cli orbit [moon_id] [moon_id]
$ zerotier-cli peers
200 peers
<ztaddr> <ver> <role> <lat> <link> <lastTX> <lastRX> <path>
824ab2729c 1.10.2 PLANET 39 DIRECT 10120 10120 47.98.50.118/9994
b4791c9669 1.8.4 MOON 27 DIRECT 153 133 47.98.50.118/9993
c86faa197d 1.12.2 LEAF 8 DIRECT 10292 10285 114.212.83.66/64107
|
连接测试
跳数
1
2
3
4
5
|
# win
pathping [内网ip:x.x.x.x]
# mac
sudo mtr [内网ip:x.x.x.x]
|
延迟
1
2
3
4
5
6
7
8
|
# win
$ ping [内网ip:x.x.x.x] -n 10
Minimum = 7ms, Maximum = 45ms, Average = 15ms
# mac
$ ping [内网ip:x.x.x.x] -c 10
10 packets transmitted, 10 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 5.075/13.052/27.223/6.514 ms
|
速度
结论:直接采用的 P2P 直连方式,平均时延低(<20ms),上下行速度快,不受公网服务器带宽限制。
参考