最近有远程组网的需求。一个月,尝试了 FRP,使用 60 秒断连 2 分钟;尝试了 Wireguard,家里 NAS 和路由器死活连不上。@Holegots 推荐了 Tailscale 和它的开源版本控制器 Headscale,试了一下,真的丝滑。
啥是 Tailscale
你可以理解为 VPN,或者说 Wireguard 外面包了一层壳子。它可以将一些设备连接起来,形成一个虚拟局域网。一个很简单的例子,你可以在星巴克里,读取家里任意电脑上的文件。
为啥要用 Tailscale?Wireguard 它不香么?是啊,Wireguard 很香,配置很简单(么?),但是我尝试了整整一个月都没组网成功,还要各种配置防火墙啥的。还有就是,如果需要访问其他设备,Wireguard 需要你自己在本地将所有设备添加到列表里面。虽然我只有有限个设备(手机,Mac,NAS,路由器),但是添加一个设备就需要全部配置一遍 IP 列表,这个事儿十分不爽。加上我是强迫症,手动分配 ip 简直要了老命。Tailscale 就方便多了:你只需要登录,就完事儿了,它会自动把节点信息下发给所有设备。
啥是 Headscale
饿,看名字就知道是和 Tailscale 对着干的。
Tailscale 的客户端是不收费的,服务端是不开源的,超过 20 个设备就需要付费了(毕竟大家都不是做慈善的)。Headscale 是个第三方开源版本的 Tailscale 的服务端,除了「网站界面」之外该有的功能都有。
所以,行动方案是?
- 找个地方部署 Headscale 服务端
- 自己的 Mac 和 Nas 上,使用 Tailscale 作为客户端
那我们开始吧
服务端:Docker 部署
作为一个洁癖,我选择了来无影去无踪的 Docker。
headscale -n default nodes register --key e9a94eb789c04015bd6dc3e68910909a0885f96df67cff2cdfe22609a548ff4e
version: "3.6"
services:
headscale:
image: headscale/headscale:latest-alpine
container_name: headscale
volumes:
- path/to/config:/etc/headscale/
- path/to/data:/var/lib/headscale
ports:
- 41641:41641
command: headscale serve
restart: unless-stopped
cap_add:
- CAP_NET_BIND_SERVICE
除此之外,我们还需要手动新建一下配置文件:
wget https://github.com/juanfont/headscale/raw/main/config-example.yaml -O config.yaml
把它放到上面提到的 config 文件夹里。然后编辑一下它:
- server_url 这个东西是一个简单的「HTTP 设备认证页面」,后面需要暴露在公网上,其他设备如果想加入到你的网络里面,需要访问这个地址,拿到一个 Token。有域名的话推荐用域名+nginx/caddy 反向代理,没域名的话用 ip+端口凑合凑合也成。
- ip_prefixes 可以根据自己喜好来改,留默认的当然也行
其他就没啥好改的了,然后我们启动 docker。
下一步,创建一个「租户」,你可以理解为一个用户。进到 headscale 的 docker 里面,执行
headscale namespaces create SOME_NAME
最后那个 SOME_NAME 自己随意替换,记得住就好。
如果你需要使用域名,那么用 nginx/caddy 反代一下容器的 8080 口就好了。最后,再去防火墙上放行一下 41641 口。
Mac 端:AppStore 版客户端
由于是使用的「非官方版控制器」,所以我们需要稍微 hack 一下,将软件里面默认的「tailscale 官方控制服务器地址」改为我们自己搭建的 Headscale 地址。
访问 http://server_url/apple
,下载并安装一个描述文件。然后打开 Tailscale,点击登录,会看到一个英文界面,里面有一行命令
headscale -n NAMESPACE nodes register --key SOME_HEX_VALUE
将里面的 NAMESPACE 换成你创建的租户名称,然后去服务端 docker 里面,执行它。你就会发现,你的 mac 已经登录成功了。
Linux 端:Docker 版客户端
稍微有一点点小坑。
version: '3.3'
services:
tailscaled:
container_name: tailscaled
image: tailscale/tailscale
network_mode: host
privileged: true
restart: always
cap_add:
- net_admin
- sys_module
volumes:
- 'path/to/config/folder:/var/lib'
- '/dev/net/tun:/dev/net/tun'
启动容器后,需要进入容器,输入这个东西进行登录:
tailscale up --login-server=http://server_url --accept-routes=true --accept-dns=false
这里的坑是:如果报错,那么需要按照这个 issue,创建一下软链接:
ln -s /tmp/tailscaled.sock /var/run/tailscale/tailscaled.sock
如果没坑,那么会提示你访问一个网址,拿到 Token,回到 Server 端进行登录就好。
我还想访问子网内所有设备!
Mac 我不会搞……
Linux 的话,两个步骤:
- 登录的时候,加上子网的信息,例如改成这样
- 登录过后,去服务端,找到对应的设备,并开启路由
tailscale up --login-server=http://server_url --accept-routes=true --accept-dns=false --advertise-routes=192.168.1.0/24
headscale nodes list
headscale routes enable -i X -r "192.168.1.0/24"
第二条命令里面的 X 是第一条命令里面查询到的设备的 id,后面子网范围和登录时候的子网范围一致。
哦如果你是使用的原生 Linux,那么在客户端的主机上还需要稍微做一下处理:
echo 'net.ipv4.ip_forward = 1' | tee /etc/sysctl.d/ipforwarding.conf
echo 'net.ipv6.conf.all.forwarding = 1' | tee -a /etc/sysctl.d/ipforwarding.conf
sysctl -p /etc/sysctl.d/ipforwarding.conf
OK,等个 30 秒,开始享受异地组网的快乐吧。
会有啥问题么
额,还是有的……
你可以去看看你的路由器,运行个一天半天的,DHCP 列表就跟炸了似的……我也不知道是咋回事儿。反正只要局域网里面有 Wireguard 设备,DHCP 列表就会炸。所以要么调整一下 DHCP 时间,要么定时重启一下路由器。