tailscale自建headscale和derp中继
Tailscale 官方的 DERP 中继服务器全部在境外,在国内的网络环境中不一定能稳定连接,所以有必要建立自己的 DERP 服务器的。
准备工作:
- 需要有自己的云服务器,本示例为阿里云轻量服务器
- 需要有自己的域名,本示例为阿里云域名
- 云服务器已经安装 docker 运行环境
准备两个子域名:
- derper.example.com
- headscale.example.com
创建docker网络
创建名为headscale的docker网络,用于不同容器直接通过名称互访。
docker network create headscale
部署tailscale客户端
在需要搭建 DERP Server 的服务器上, 首先安装一个 Tailscale 客户端,这样做的目的是让搭建的 DERP Server 开启客户端认证, 否则你的 DERP Server 可以被任何人白嫖.
为derper容器提供tailscale.sock套接字,用于后续部署derp时指定-v tailscale:/var/run/tailscale参数.
docker run -d --name tailscaled
--restart always \
-v tailscale:/var/run/tailscale \
-v /var/lib:/var/lib \
-v /dev/net/tun:/dev/net/tun \
--network=host --privileged \
tailscale/tailscale tailscaled
部署derp中继服务器
docker run -d --name derper \
--restart always \
-p 8443:8443 -p 3478:3478 \
-e DERP_ADDR=:8443 \
-e DERP_DOMAIN=derper.example.com \
-e DERP_CERT_MODE=letsencrypt \
-e DERP_VERIFY_CLIENTS=true \
--net headscale \
-v tailscale:/var/run/tailscale \
docker.io/fredliang/derper:latest
参数说明:
- 3478 端口不要修改
- 8443 端口可以按照自己的喜好来改,DERP_ADDR 变量后面的端口需要与该端口保持一致,冒号不能丢
- DERP_VERIFY_CLIENTS=true,DERP 会验证连接的客户端是否与本机的客户端为同一个账号下,从而避免其他客户端白嫖服务器
-v tailscale:/var/run/tailscale
将tailscale.sock套接字接口挂载进容器中
浏览器访问derper域名:https://derper.example.com/
,显示以下内容,说明derp服务端运行正常:
部署headscale
创建headscale目录
mkdir -p /data/headscale/config
touch /data/headscale/config/db.sqlite
下载headscale配置文件
wget -O /data/headscale/config/config.yaml \
https://raw.githubusercontent.com/juanfont/headscale/main/config-example.yaml
修改headscale配置文件,以下仅显示修改部分,其他保持默认
$ vim /data/headscale/config/config.yaml
server_url: https://headscale.example.com
listen_addr: 0.0.0.0:8080
metrics_listen_addr: 0.0.0.0:9090
private_key_path: /etc/headscale/private.key
noise:
private_key_path: /etc/headscale/noise_private.key
derp:
urls:
# - https://controlplane.tailscale.com/derpmap/default
paths:
- /etc/headscale/derp.yaml
dns_config:
override_local_dns: true
nameservers:
- 223.5.5.5
- 223.6.6.6
创建derp配置文件
$ vim /data/headscale/config/derp.yaml
regions:
900:
regionid: 900
regioncode: aliyun
regionname: aliyund-derp
nodes:
- name: 900a
regionid: 900
hostname: derper.example.com
stunport: 3478
stunonly: false
derpport: 8443
配置说明:
- regions 是 YAML 中的对象,下面的每一个对象表示一个可用区,每个可用区里面可设置多个 DERP 节点,即 nodes。
- 每个可用区的 regionid 不能重复。
- 每个 node 的 name 不能重复。
- regionname 一般用来描述可用区,regioncode 一般设置成可用区的缩写。
- ipv4 字段不是必须的,如果你的域名可以通过公网解析到你的 DERP 服务器地址,这里可以不填。如果你使用了一个二级域名,而这个域名你并没有在公共 DNS server 中添加相关的解析记录,那么这里就需要指定 IP(前提是你的证书包含了这个二级域名,这个很好支持,搞个泛域名证书就行了)。
- stunonly: false 表示除了使用 STUN 服务,还可以使用 DERP 服务。
部署headscale
docker run -d --name headscale \
--restart always \
-p 8080:8080 -p 9090:9090 \
--net headscale \
-v /data/headscale/config:/etc/headscale \
headscale/headscale:latest-alpine headscale serve
部署caddy-server
创建caddy配置文件目录
mkdir -p /data/caddy
创建caddy配置文件
cat >/data/caddy/Caddyfile<<EOF
https://headscale.cloudcele.com {
reverse_proxy * http://headscale:8080
}
https://derper.cloudcele.com {
reverse_proxy * http://derper:8443
}
EOF
部署caddy-server
docker run -d --name caddy \
--restart always \
-p 80:80 -p 443:443 \
--net headscale \
-v /data/caddy/Caddyfile:/etc/caddy/Caddyfile \
docker.io/caddy/caddy:latest
headscale服务端配置
创建一个命名空间:
docker exec headscale \
headscale namespaces create defaultns
生成用于客户端注册的认证key
docker exec headscale \
headscale --namespace defaultns preauthkeys create --reusable --expiration 24h
tailscale 注册
docker exec -it tailscaled \
tailscale up --accept-dns=false --accept-routes=true \
--auth-key=90e20f91f2497c518144254b0fe66cc0619ae5571e8a2e5c \
--force-reauth --login-server=https://headscale.example.com --reset
windows客户端注册
1、安装tailscale windows客户端
2、浏览器访问以下链接,下载页面中的reg注册表文件并执行
https://headscale.example.com/windows
点击下载页面中的reg注册表文件并执行
3、注册客户端到headscale控制端
打开CMD执行以下命令
tailscale up --accept-dns=false --accept-routes ^
--login-server=http://headscale.example.com ^
--auth-key=90e20f91f2497c518144254b0fe66cc0619ae5571e8a2e5c ^
--force-reauth --unattended --reset ^
--advertise-routes=192.168.12.0/24,192.168.13.0/24
关于选项设置:
- –login-server: 指定使用的中央服务器地址(必填)
- –advertise-routes: 向中央服务器报告当前客户端处于哪个内网网段下, 便于中央服务器让同内网设备直接内网直连(可选的)或者将其他设备指定流量路由到当前内网(可选)
- –accept-routes: 是否接受中央服务器下发的用于路由到其他客户端内网的路由规则(可选)
- –accept-dns: 是否使用中央服务器下发的 DNS 相关配置(可选, 推荐关闭)
客户端开启IP转发,在注册表编辑器中,打开 ,将参数IPEnableRouter的值从0修改为1,然后关闭注册表编辑器并重新启动系统。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
4、headscale控制端查看注册的节点列表
docker exec -it headscale headscale nodes list
如果需要删除节点执行以下命令
headscale nodes delete -i 2
5、server端查看客户端发布的subnet
/ # headscale nodes routes list -i 2
Route | Enabled
192.168.12.0/24 | false
192.168.13.0/24 | false
server端启用客户端发布的subnet
/ # headscale nodes routes enable -i 2 -r 192.168.13.0/24,192.168.12.0/24
Route | Enabled
192.168.12.0/24 | true
192.168.13.0/24 | true
tailscale ping 命令
tailscale ping 命令可以用于测试 IP 连通性, 同时可以看到是如何连接目标节点的. 默认情况下 Ping 命令首先会使用 Derper 中继节点通信, 然后尝试 P2P 连接; 一旦 P2P 连接成功则自动停止Ping.
由于其先走 Derper 的特性也可以用来测试 Derper 连通性.
C:\Users\willme>tailscale ping 192.168.12.16
pong from winpc (fd7a:115c:a1e0::2) via DERP(aliyun) in 49ms
pong from winpc (fd7a:115c:a1e0::2) via DERP(aliyun) in 117ms
pong from winpc (fd7a:115c:a1e0::2) via DERP(aliyun) in 46ms
pong from winpc (fd7a:115c:a1e0::2) via DERP(aliyun) in 38ms
pong from winpc (fd7a:115c:a1e0::2) via DERP(aliyun) in 80ms
pong from winpc (fd7a:115c:a1e0::2) via DERP(aliyun) in 42ms
pong from winpc (fd7a:115c:a1e0::2) via DERP(aliyun) in 163ms
pong from winpc (fd7a:115c:a1e0::2) via DERP(aliyun) in 68ms
pong from winpc (fd7a:115c:a1e0::2) via DERP(aliyun) in 41ms
pong from winpc (fd7a:115c:a1e0::2) via DERP(aliyun) in 255ms
direct connection not established
tailscale status 命令
通过 tailscale status 命令可以查看当前节点与其他对等节点的连接方式, 通过此命令可以查看到当前节点可连接的节点以及是否走了 Derper 中继:
C:\Users\winpc>tailscale status
fd7a:115c:a1e0::1 win-laptop defaultns windows -
fd7a:115c:a1e0::2 winpc defaultns windows active; relay "aliyun", tx 45680 rx 49464
tailscale netcheck 命令
有些情况下我们可以确认是当前主机的网络问题导致没法走 P2P 连接, 但是我们又想了解一下当前的网络环境; 此时可以使用 tailscale netcheck 命令来检测当前的网络环境, 此命令将会打印出详细的网络环境报告:
C:\Users\winpc>tailscale netcheck
Report:
* UDP: false
* IPv4: (no addr found)
* IPv6: no, but OS has support
* MappingVariesByDestIP:
* HairPinning:
* PortMapping:
* CaptivePortal: true
* Nearest DERP: aliyund-derp
* DERP latency:
- aliyun: 126.3ms (aliyund-derp)