headscale 全解析
安装
参考文章:
- How to setup headscale server in 5 minutes using docker-compose - TechOverflow
- 【Headscale】自部署 Tailscale 服务端 | 泠泫凝的异次元空间
- How to create namespace on headscale server - TechOverflow
- Tailscale 基础教程:Headscale 的部署方法和使用教程 – 云原生实验室 - Kubernetes|Docker|Istio|Envoy|Hugo|Golang|云原生
前置动作为安装 docker 和 docker-compose,以前的文章写过,就不重复造轮子了。
新建 docker 用 headscale 文件结构,下文以 root 用户默认目录为例
1
2
3
4mkdir -p /root/docker-compose/headscale/config
cd /root/docker-compose/headscale/config
touch ./config/db.sqlite
curl https://raw.githubusercontent.com/juanfont/headscale/main/config-example.yaml -o ./config/config.yaml修改
/root/docker-compose/headscale/config
下的config.yaml
。将
server_url
改为公网 IP/域名及对外端口。这关乎到后续打开网页和 pc 修改完注册表后链接到服务器登录时弹出的网页 url,如果不设置成正确的公网 url,后续弹出的地址就不能用。listen_addr
不用改,这一步和用非 docker 版不一样,因为这个参数所对应的是 docker 内部端口,后续是通过 docker 的映射映射到真正的对外端口的。将
magic_dns
设为 false,防止连不了网。自定义私有网段(可选),便于记忆:
1
2ip_prefixes:
- 10.1.0.0/16
在
/root/docker-compose/headscale/
目录下新建并编辑docker-compose.yml
,只需要修改下面配置文件的对外端口一项,与前面config.yaml
中server_url
设置的端口一致即可。1
2
3
4
5
6
7
8
9
10
11version: '3.5'
services:
headscale:
image: headscale/headscale:latest
volumes:
- ./config:/etc/headscale/
- ./data:/var/lib/headscale
ports:
- [server_ports]:8080
command: headscale serve
restart: unless-stopped确保 ssh 当前目录为 headscale 的 docker-compose 文件所在目录
1
cd /root/docker-compose/headscale
启动
1
docker-compose up -d
配置
我只有 windows 和 android 端的设备,其实我还有个 ipad,但听说 headscale 暂时不支持 ios,那就算了。
windows(23.10.23 更新)
windows 下载 安装包
打开链接
http://[server_url]:[server_ports]/windows
,里面方括号括起来的两个内容自己就是我们上面config.yaml
填的server_url
配置啦。(23.10.23 更新) 新版本这里会提示使用命令进行注册,原有的注册表配置方式已经废弃。只需要把页面中的这句命令行
1 | tailscale login --login-server [server_url] |
输入到 windows 这边的 cmd 里,就会自动跳到下一步。
3. 接下来弹出的界面就是 windows 端的教程。
这张图片里面其实简述了两种方法:
1. 下载 reg
2. 在 cmd 中输入两行命令
这两种方法其实都可以。我想说的是,如果之前配置过 headscale,但现在换了节点的话,可以打开 regedit,导航到 HKLM\Software\Tailscale IPN
,修改其中 LoginURL
的值即可。
此时重新打开 tailscale,右键任务栏的图标后,会弹出注册页面。注册页面会显示让你到 vps 中粘贴命令:
1 | headscale -n NAMESPACE nodes register --key xxxxxxx |
但实际上我们需要改装一下这条命令。
首先在 vps 中创建一个 node。同样的,确保 ssh 当前目录为 headscale 的 docker-compose 文件所在目录,然后运行命令新建 node。
1 | docker-compose exec headscale headscale namespaces create [节点名字] |
改造上面的命令,将 windows 客户端加到节点中
1 | -n已过期 |
查看效果,如果添加的节点显示 online,则成功
1 | docker-compose exec headscale headscale nodes list |
另外这个命令也会显示当前链接设备的 headscale 内局域网 ip。
android
android 端,需要编译 apk,可以通过 github action 下一个最新的,或者再 fork 一份然后自己跑一遍。安装后右上角三个点打开然后把命令考出来像 windows 一样改造后放入 vps,此处不再赘述。最新版的 apk(1.3 以上),疯狂点击 about 就会出现自定义服务器的选项,填入 http://[server_url]:[server_ports]
,重启即可看到命令。
(230514 更新) asus merlin (仅管理界面)
慎用。似乎会搞坏路由器的 dns。
安装 entware,然后通过 entware 安装 tailscale(安装 entware 的教程请见往期文章)
1
opkg install tailscale
启动 tailscaled。要对 tailscale 进行配置需要先启动 tailscaled,另外当 ssh 登出时,tailscaled 就会自动停止,但 tailscale 配置好后会开启自启并持续运行。
1
/opt/etc/init.d/S06tailscaled start
配置 tailscale。
1
tailscale up --login-server=http://<HEADSCALE_PUB_IP>:8080 --accept-routes=true --accept-dns=false
此时 ssh 中会弹出一个网址,访问后会获得要到 vps 中输入的命令,参考上面 windows 端的操作,不再赘述。
配置防火墙。打开/新建
/jffs/scripts/firewall-start
,在#/bin/sh
下面新增两行:1
2iptables -I INPUT 1 -s 10.1.0.0/24 -j ACCEPT
iptables -t nat -A PREROUTING -d 10.1.0.3 -j DNAT --to-destination 192.168.123.110.1.0.0/24
放 tailscale 网段地址。192.168.123.1
放内网访问到路由器管理界面的地址。
此时就在外网可以通过路由器的 tailscale 地址访问路由器管理界面的地址了。
其他延伸配置(23.10.23 更新)
反代 https
如果没有装有 web 服务器,可以用 headscale 内置的 https 功能。但我已经装有 caddy 了,直接用 caddy 就好。
参考文章:headscale/docs/reverse-proxy.md at main · juanfont/headscale
修改
/root/docker-compose/headscale/config
下的config.yaml
,把server_url
改成 https 地址,端口不留,因为默认 https 就走 443 端口。修改 caddy 配置文件 Caddyfile,一般位于
/etc/caddy/Caddyfile
,增加配置(此处我已经申请过泛域名证书,就不使用 caddy 自己的自动申请域名方法了)1
2
3
4https://xxx.xxx.xyz {
reverse_proxy localhost:[server_ports]
tls /etc/ssl/xxx.crt /etc/ssl/xxx.key
}然后重启 caddy 和 docker-compose headscale 即可。
更换 headscale nodes list 里的节点 id 和 ip
参考文章:自定义/更改 IP 地址 · 问题 #1455 · juanfont/headscale
安装 sqlite。
1 | apt install sqlite -y |
找到 /root/docker-compose/headscale/data/
下的 db.sqlite 文件。使用 sqlite3 打开并编辑。
1 | sqlite3 /var/lib/headscale/db.sqlite |
重启被修改 ip 的客户端即可。
修改 randomize_client_port
如果访问不正常,可以尝试修改。参考文章:Headscale 端到端直连 - Yogile - 博客园
修改 /root/docker-compose/headscale/config
下的 config.yaml
。
randomize_client_port :原为 false ,须改为 true 。否则客户端端点访问互相干扰,无法访问服务。
使用 preauthkeys 无需服务器同意一键添加设备
新建 key
1 | docker-compose exec headscale headscale --user zbttl preauthkeys create --reusable --expiration 24h |
查看新建的 key,记下 key 的值
1 | docker-compose exec headscale headscale -u [节点名字] preauthkeys list |
在客户端处输入命令,以 windows 为例:
1 | tailscale up --auth-key=[key_value] --login-server=[server_url] --accept-dns=false --unattended |
tailscale 会即刻登录,无需进入服务器使用命令二次确认。
然后让 key 过期
1 | docker-compose exec headscale headscale --user [节点名字] preauthkeys expire [key_value] |
使用 headscale ui 并配置 Ephemeral 供临时使用
参考文章:
- 配置 Headscale UI - Gurucomputing 博客
- gurucomputing/headscale-ui: A web frontend for the headscale Tailscale-compatible coordination server — gurucomputing/headscale-ui:headscale Tailscale兼容协调服务器的Web前端
啥是 Ephemeral 呢?参考临时节点 · Tailscale 文档,简而言之,上一步我们用 preauthkeys 添加设备时候用的节点,变成了一次性的,使用者登录后只要登出(比如重启 tailscale,重启电脑等),节点信息就会失效,就连不上 headscale 控制器了,适合短期的给临时设备使用。要方便的使用这个功能,甚至方便的进行设备的添加删除,查看在线的设备而无需进入 ssh,都可以搭建这么一个 headscale-ui 在前端。
(可选,便于验证配置文件是否工作正常)把 config.yaml
中的 metrics_listen_addr
端口映射出来,默认为 9090。因为用的是 docker,还需要把这里的地址修改为 0.0.0.0 以被访问到
1 | metrics_listen_addr: 0.0.0.0:9090 |
然后修改 headscale 映射的端口,还需要添加 headscale-ui 配置到 headscale 的 docker-compose 文件中。
1 | version: '3.5' |
重启 docker-compose 后即可通过 ip:[metric_ports]/metrics
访问到访问到 metrics 页面,然后通过 ip:[metric_ports]/headscale_ports
不出意料也能进入 ui 页面。
此时我们在 ssh 处申请一个 api:
1 | docker-compose exec headscale headscale apikeys create |
记住这里的 api。因为后面无法再获取这个 api,如果忘记了只能重新获取;我们待会就要用这个 api 登录网页端,更换设备,清除 cookies 都需要重新输入这一串长长的随机 api。所以建议保存起来。
在网页端的 settings->headscale api key 中填入刚刚获取的 api。在 user view 中就能看到我们创建的 headscale 节点名字了。device view 处则能管理已授权的设备。
在 user view 处点开节点,点 preauth keys 前面的加号
此时能看到三个选项,分辨是 key 的过期时间、是否可以重复使用、是否为 Ephemeral key(即我上面说的临时 key),选择需要的配置,点击 create preauth key 即可创建成功。将 key 套入命令中在命令行里输入即可成功添加,上一章说过了,不再赘述。
反代 https
当然 headscale-ui 和 metrics 也可以通过 caddy 反代了。另外为了安全我还在 headscale-ui 页面外面套了一层用户和密码。修改 caddyfile:
1 | https://xxx.xxx.xyz { |
重启 caddy,即可用 https://xxx.xxx.xyz/metrics
和 https://xxx.xxx.xyz/web` 访问 metrics 页面和 headscale-ui 页面了。
自定义 derp
参考文章:Tailscale 基础教程:部署私有 DERP 中继服务器 – 云原生实验室 - Kubernetes|Docker|Istio|Envoy|Hugo|Golang|云原生
上面说的只是搭建 headscale 控制器,而连接的流量节点是 tailscale 的那些默认服务器。也可以自建流量节点,我们称为 derp,不过一般用不着,如果特别卡的话,再说。
有两种方法,一种是 derp 和 headscale 控制器节点在同一台机器上,一种是无所谓在不在一台机器上都可以使用。不管那一种,需要开一个和 headscale 控制器不同的三级域名。
简易版自体 derp
参考文章:“嵌入式 DERP(和 STUN)服务器”提供哪些具体服务 · 问题 #1326 · juanfont/headscale
derp 和 tailscale 节点在同一台机器上的情况下,只需要调整 config.yaml
的 derp 相关配置:
1 | derp: |
然后修改 docker-compose.yml
:
1 | version: '3.5' |
最后重启 docker-compose
1 | docker-compose down |
在客户端处使用 tailscale netcheck
检查,出现 derp 节点即为成功。
通用 derp 配置
参考文章:slchris/derp-server:Tailscale/Headscale derp 服务器
需要配置一个 docker 的 derp 容器。网上有挺多教程用的是单独开的 derp 域名然后用这个域名去申请证书,申请到的证书名字前缀命名和域名一致,或者用证书工具来申请。但我还是照例,用我之前申请的泛域 ssl 证书。新建一个 derp 文件夹,里面放上 docker-compose.yml
文件。假设我的 derp 域名为 derp.xxx.xyz:
1 | version: '3.3' |
启动容器 docker-compose up -d
,访问 https://derp.xxx.xyz:12345 查看 12345 端口是否能访问。
然后修改 config.yaml
文件的 derp 部分,其实只用改那个 paths 就行,另外提一嘴,如果只需要用自建的 derp 而不需要 tailscale 提供的公共 derp,只需要注释掉 urls 里面的那行网址就行:
1 | derp: |
在 config.yaml
文件夹内新增一个 derp.yaml
:
1 | regions: |
最后重启 docker-compose
1 | docker-compose down |
在客户端处使用 tailscale netcheck
检查,出现 derp 节点即为成功。
关于两种方法的混用问题
这是一个小发现:如果使用了第一种方法通过 docker 把 3478 端口透出来了,那么第二部如果是在同一台机子上,derp 容器是无法启动的。但反过来,自体 derp 如果没有映射 3478 端口的话,使用 tailscale netcheck
来看节点是没有启动的(没有 ping 值),但!此时我们启动 derp 容器,不用再做后面修改 config.yaml
和 derp.yaml
的步骤,会发现节点也连上了。利用这种方法部署,也未尝不可。
防止 DERP 被滥用
从配置上看,人家只要拿到我们的 derp 网址,探测到端口就可以白嫖了(虽然还是有一定门槛)。有什么办法可以阻拦一下呢?还真有,那就是客户端需要连上和 derp 一样的 headscale 节点才能使用 derp,然后开启一个叫 DERP_VERIFY_CLIENTS 的参数。修改 derp 节点的 docker-compose.yml:
1 | version: '3.3' |
如果 derp 和 headscale 控制器不在一起的话,就需要把 derp 所在的这个节点也用 tailscale 客户端连上自己的 headscale 控制器才可以。可以使用 apt 等工具包安装 tailscale,也可以使用 docker 安装 tailscale 客户端,这里我使用后者,新建一个 docker-compose.yml 文件:
1 | version: '3.1' |
启动 docker-compose up -d
用 ui 配置一个一次性的 key,然后用 key 连接到 headscale:
1 | docker-compose exec Headscaled tailscale up --auth-key=[key_value] --login-server=[server_url] --accept-dns=false |
最终完全版 headscale 控制器参考配置
开启 headscale-ui,https 反代,derp。
docker-compose.yml:
1 | version: '3.5' |
caddyfile:
1 | https://xxx.xxx.xyz { |
config.yaml:
1 | server_url: https://xxx.xxx.xyz |
注意事项
不要在国内云上架设 headscale!试过秒封(良心云,直接封机子,申诉还要上传身份证)。
windows 端,如果发现使用局域网速度缓慢,或者连接不上,可以通过:
- disconnect 再 connect,重新刷新链接
- 使用命令
tailscale netcheck
和tailscale status
查看连接情况。
如果有哪个节点配置错误或需要删除,可以通过下面的命令删除
1
2
3#已过期
#docker-compose exec headscale headscale nodes delete yyyy
docker-compose exec headscale headscale nodes delete -i [节点序号]yyy 的内容就是
docker-compose exec headscale headscale nodes list
第三列显示的设备名(即 Name)。