【记录】本地部署 ZeroTier 组网实现内网穿透

主机没有公网 IP 时,进行内网穿透的方法主要有两种:

  • 转发(反向代理):有公网 IP 的服务器作为中转节点,成功率高,数据传输需要经过服务器,带宽受服务器带宽限制。

  • “打洞”(P2P):节点直连,数据传输不经过公网服务器,延迟更低,带宽不受服务器限制,往往可以跑满本地带宽。但“打洞” 的成功率不高(如多层 NAT 的情况),同运营商相近地理区域更容易成功,

NAT 及穿透原理

本节部分图片文字转自文章:NAT基本原理及穿透详解(打洞)P2P Communication Across NAT

NAT(Network Address Translation) 用来将内网地址和端口号转换成合法的公网地址和端口号,建立一个会话,与公网主机进行通信。NAT的使用是为了解决公网IP有限及局域网安全性的问题。

https://imgs.alfly.cn/NAT-router.png

NAT工作原理:

  • 网络被分为内网和公网两个部分,NAT网关设置在私网到公网的路由出口位置,双向流量必须都要经过NAT网关;

  • 网络访问只能先由私网侧发起,公网无法主动访问私网主机;

  • NAT网关在两个访问方向上完成两次地址的转换,出方向做源信息替换,入方向做目的信息替换;

  • NAT网关为了实现双向翻译的功能,需要维护一张关联表,把会话的信息保存下来。

Public and private IP address domains

NAT将内部网络的信息隐藏和转换,如果要实现隐藏在NAT下的设备之间通信(对等网络传输)则必须穿透NAT。

常规不同 NAT 设备下的穿透原理示意图如下,更详细的说明可以看这篇文章

UDP Hole Punching, Peers Behind Different NATs

本地部署 Zerotier

内网穿透的常用工具有 frp、zerotier、花生壳等,下面记录本地部署 zerotier 组网完成内网穿透的过程。

刚开始参考教程完成了部署,但鉴于此教程较老,仓库 zerotier-planetdocker-zerotier-moon 已不在维护,更换新的仓库实现可快速部署。

Planet

私有部署 Planet 服务(实际是 Planet + Network Controller UI),实现节点由自己的 Planet 控制,不经过官方的海外节点,更稳定。

docker-zerotier-planet 用 docker 打包了 ZeroTierOne 和后台控制界面 ztncui,一键执行脚本即可。

1
./deploy.sh

在服务器防火墙(安全组)放行 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;
}

输入对应网址进入控制台界面,完成用户登录、密码修改、网络创建。

https://imgs.alfly.cn/controller.png

下面进行客户端设置,参考文档替换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

速度

https://imgs.alfly.cn/librespeed.png

结论:直接采用的 P2P 直连方式,平均时延低(<20ms),上下行速度快,不受公网服务器带宽限制。

参考

0%