headscale

有关项目

有关教程

搭建headscale服务端

1. 创建相关文件

创建 db.sqlite,再下载官网给的配置文件示例,然后按需修改。

1
2
3
4
5
mkdir -p /home/docker/headscale/config && mkdir -p /home/docker/headscale/data && \

touch /home/docker/headscale/data/db.sqlite && \

wget https://github.com/juanfont/headscale/raw/v0.22.3/config-example.yaml -O /home/docker/headscale/config/config.yaml

需要修改下载镜像对应版本号config-example.yaml​,否则可能配置文件无法对应导致启动报错。

2. 修改配置

修改相关配置文件,比如配置文件中配置 127.0.0.1​ 的话,那么就只能本机访问。这里修改为 0.0.0.0​ 那么就所有的 ip 都能访问(建议先使用0.0.0.0​,部署好后可尝试修改127.0.0.1​测试是否正常)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
vim /home/docker/headscale/config/config.yaml

# 这将修改以下几个地方,其中server_url还需要另外修改
# 1. server_url: https://example.com
# 2. listen_addr: 0.0.0.0:8080
# 3. metrics_listen_addr: 0.0.0.0:9090
# 4. grpc_listen_addr: 0.0.0.0:50443
# 5. nameservers:
- 119.29.29.29 (可选,如服务器再国内,最好加一个国内DNS)
- 1.1.1.1
# 开随机端口
# 6. randomize_client_port: true
# 以通过 主机名 + 用户 + 基础域名 访问任意一台终端
# 7. base_domain: wanyunr.com

建议使用域名反代,否则可能出现某些安全验证问题

3. 启用内嵌的 derp

当然你可以使用官方提供的 derp 服务器,但如果你想搭建自己的 derp 服务器,又不想另外搭建一个 derp 服务器,那么这是有必要的。

注意:使用此 derp 服务器,需要有域名并配置 ssl,否则请参考:Docker 搭建中继服务器 derp - 纯 IP 实现

1
2
3
4
5
6
7
8
9
10
11
12
# /home/docker/headscale/config/config.yaml
derp:
server:
# xxx
enabled: true
# xxx
region_id: 999
# xxx
region_code: "headscale"
region_name: "Headscale Embedded DERP"
# xxx
stun_listen_addr: "0.0.0.0:3478"

enabled​ 选项默认为 false,需要设置为 true。

4. 启动

1
2
3
4
5
6
7
8
9
10
11
12
docker run -d \
--name headscale \
--restart always \
-v /root/docker_data/headscale/config:/etc/headscale/ \
-v /root/docker_data/headscale/data:/var/lib/headscale \
-p 8080:8080 \
-p 9090:9090 \
-p 3478:3478/udp \
--restart always \
headscale/headscale:0.22.3 \
headscale serve

5. 常用命令

1
2
3
4
5
6
7
8
# 查看用户
docker exec -it headscale headscale users ls
# 创建用户
docker exec -it headscale headscale users create <user>
# 生成apikey
docker exec -it headscale headscale apikey create
# 查询apikey
docker exec -it headscale headscale apikey ls

二、搭建web-ui

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
docker run -d \
--name headscale-webui \
--restart always \
-v /root/docker_data/headscale/config:/etc/headscale/:ro \
-v /root/docker_data/headscale/web-ui/data:/data \
-u root \
-p 5000:5000 \
-e HS_SERVER=https://wanyunr.com \
-e DOMAIN_NAME=https://wanyunr.com \
-e SCRIPT_NAME=/admin \
-e AUTH_TYPE=Basic \
-e BASIC_AUTH_USER=user \
-e BASIC_AUTH_PASS=passwd \
-e KEY="xxxxxxxxxxxxJdVjaE=" \
--restart always \
ifargle/headscale-webui:latest

其中 /home/docker/headscale/config​ 为上面服务端的映射目录,这两个目录需要一致。HS_SERVER​ 和 DOMAIN_NAME​ 填写自己的域名 1。KEY​ 是用来加密待会需要保存的 apikey 的字符串,使用命令 openssl rand -base64 32​ 生成。

接下来需要创建 headscale 服务器的 api-key,这里设置一个比较久的过期时间。

三、配置 nginx 和 web-ui

配置 nginx

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
30
31
32
33
34
35
36
37
38
39
40
41
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name wanyunr.com;
ssl_certificate /www/sites/wanyunr.com/ssl/fullchain.pem;
ssl_certificate_key /www/sites/wanyunr.com/ssl/privkey.pem;
# ssl_protocols TLSv1.3 TLSv1.2 TLSv1.1 TLSv1;
# ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
# ssl_prefer_server_ciphers on;
# ssl_session_cache shared:SSL:10m;
# ssl_session_timeout 10m;
# add_header Strict-Transport-Security "max-age=31536000";
# error_page 497 https://$host$request_uri;
# proxy_set_header X-Forwarded-Proto https;
# ssl_stapling on;
# ssl_stapling_verify on;

location ^~/ {
proxy_pass http://localhost:8080/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $server_name;
proxy_redirect https:// https://;
proxy_buffering off;
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 $http_x_forwarded_proto;
}

location ^~/admin/ {
proxy_pass http://localhost:5000/admin/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

server {
listen 80;
server_name wanyunr.com;
rewrite ^(.*)$ https://$host:443$1 permanent;
}

保存配置后重启 nginx后,如果配置正确,通过 https://域名/admin​ 应该可以访问到 web-ui 界面,输入容器启动时配置的用户名密码即可进入。

  1. 配置 web-ui

上面提示输入 apikey,这个需要 headscale 服务端生成,这里设置一个比较长的时间,根据自己的需要即可。

1
docker exec -it headscale headscale apikeys create -e 10000d

运行命令后将生成的 key 输入,点击 save 即可

四、创建用户和授权密钥

1
2
3
#  创建用户

docker exec -it headscale headscale users create hz

授权密码的作用是,客户端登陆时不需要再服务端进行确认,阿蛮君总是喜欢使用简单的方式,所以就选择这种方式了。

1
2
3
4
5
6
7
# reusable 参数代表可以重复使用,不加的话密钥只能用来一个客户端加入

docker exec -it headscale headscale preauthkeys create -e 10000d --reusable -u hz

# 查看密钥

docker exec -it headscale headscale preauthkeys list -u hz

这里记得记录好授权密钥,下面将会用到。

客户端安装

headscale 相当于是重新实现了 tailscale 的服务端,客户端基本还是用的 tailscale。

tailscale 客户端下载地址:https://tailscale.com/download/

1. windows

1.1 安装客户端

下载 windows 客户端并进行安装。

1.2 安装注册表

访问 https://wanyunr.com/windows​,可以看见配置的教程。

提示需要修改注册表,这里可以直接 访问https://wanyunr.com/windows/tailscale.reg​ 下载文件后,双击运行文件进行安装即可。

1.3 登录

在 tailscale 的安装目录下使用 cmd 打开,输入命令:

1
tailscale login --login-server https://wanyunr.com --authkey e5bc07f5325dd282563295f03b7894dd686416b47798c998 --accept-dns=false --accept-routes

这里的 authkey 是第四步生成的,然后在服务器使用命令查看。

1
docker exec -it headscale headscale nodes <username>
2. linux

2.1 脚本安装

1
2
3
curl -fsSL https://tailscale.com/install.sh | sh && \

tailscale login --login-server https://head.uve.cc --authkey e5bc07f5325dd282563295f03b7894dd686416b47798c998 --accept-dns=false --accept-routes

这里仅仅安装方式不同,登录的命令完全一样。

2.2 docker 安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
docker run -d \

--name=tailscaled \

-v /home/docker/tailscale/:/var/lib \

-v /dev/net/tun:/dev/net/tun \

-e TS_STATE_DIR=/var/lib/state/ \

--network=host \

--restart always \

--privileged tailscale/tailscale:v1.44.0 \

tailscaled --tun=tailscale0 -no-logs-no-support=true

这里需要将 TS_STATE_DIR​ 指定的文件夹持久化,否则删除容器再新建后,在服务端能看见重复的设备。并且需要指定 --tun=tailscale0​,不然似乎不能在宿主机创建网卡。

然后使用如下命令进行登录。

1
docker exec -it tailscaled tailscale login --login-server https://wanyunr.com --accept-dns=false --accept-routes=false --authkey b6a9b4f4e9c3a7c7e7b9b1a3a6b9e6b7a5e7c2a1e3a0a4a1 --advertise-routes=172.21.9.0/24,172.30.1.0/24,172.26.1.0/24,172.20.2.0/23

根据自己网络情况设置 --advertise-routes​,我这是需要通过这台内网机器访问公司其他网络。

如果出现如下错误:

running [/sbin/ip6tables -t filter -N ts-input –wait]: exit status 3: modprobe: can’t change directory to ‘/lib/modules’: No such file or directory
ip6tables v1.8.8 (legacy): can’t initialize ip6tables table `filter’: Table does not exist (do you need to insmod?)
Perhaps ip6tables or your kernel needs to be upgraded

执行以下命令:

1
2
3
# 防止探测ip6table

sudo modprobe ip6table_filter
3. 安卓

3.1 安装并配置

f-droid 下载

安装后,点击右上角三个设置自定义登录地址,点击 Login in,会出现一串命令,复制key​后面的部分

3.2 手机端注册命令

1
docker exec -it headscale headscale nodes register --user <username> --key nodekey:10xxxxxxxxxxxxxxxxxxxxxxxxx

derper

有ssl证书

没有搭建成功,需要可参考:

Docker 搭建中继服务器 derp - 需要域名并配置 ssl - 阿蛮君博客

Tailscale 基础教程:部署私有 DERP 中继服务器

无证书模式

原理:将域名验证相关的内容删除或注释,并创建自签名证书。除了 derper 之外,Tailscale 客户端还需要跳过域名验证,这个需要在 DERP 的配置中设置。而 Headscale 的本地 YAML 文件目前还不支持这个配置项,需要使用在线 URL。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# host模式,需要443端口
docker run -d \
--restart always \
--net host \
--name derper \
ghcr.io/yangchuansheng/derper:latest


# bridge 模式
docker run -d \
--restart always \
-p 3478:3478/udp \
-p 8443:443 \
--name derper \
ghcr.io/yangchuansheng/ip_derper

使用节点

1
2
3
4
5
6
7
# /etc/headscale/config.yaml
derp:
# List of externally available DERP maps encoded in JSON
urls:
# - https://controlplane.tailscale.com/derpmap/default
- https://xxxxx/derp.json
paths: []

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"Regions": {
"1": {
"RegionID": 1,
"RegionCode": "ali-sh",
"RegionName": "Aliyun GuangZhou",
"Nodes": [
{
"Name": "1",
"RegionID": 901,
"DERPPort": 443,
"HostName": "xxxx",
"IPv4": "xxxx",
"InsecureForTests": true
}
]
}
}
}

配置解析:

  • HostName​ 直接填 derper 的公网 IP,即和 IPv4​ 的值相同。
  • InsecureForTests​ 一定要设置为 true,以跳过域名验证(必须配置

derper 查用命令

1
2
3
4
5
6
7
8
9
10
# docker 运行的客户端
docker exec -it tailscaled tailscale netcheck
# 非 docker 运行的客户端
tailscale netcheck

#使用 tailscale status 命令可以查看到当前网络的状态
# docker 运行的客户端
docker exec -it tailscaled tailscale status
# 非 docker 运行的客户端
tailscale status