安装服务端

创建headscale配置目录

1
2
$ mkdir -p /etc/headscale/{data,certs}
$ cd /etc/headscale

生成headscale配置文件

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
$ cat >config.yaml<<EOF
---
# 这个地址是告诉客户端需要访问的地址, 即使你需要在跑在
# 负载均衡器之后这个地址也必须写成负载均衡器的访问地址
server_url: http://35.241.79.221:8080

# Headscale 实际监听ip和端口
listen_addr: 0.0.0.0:8080

# 监控数据地址
metrics_listen_addr: 127.0.0.1:9090

# grpc 监听地址
grpc_listen_addr: 0.0.0.0:50443

# 是否允许不安全的 grpc 连接(非 TLS)
grpc_allow_insecure: false

private_key_path: /var/lib/headscale/private.key
noise:
private_key_path: /var/lib/headscale/noise_private.key

# 给vpn客户端分配的vpn网段
ip_prefixes:
- 192.168.66.0/24

# 中继服务器相关配置
derp:
server:
enabled: false
region_id: 999
region_code: "headscale"
region_name: "Headscale Embedded DERP"
stun_listen_addr: "0.0.0.0:3478"
urls:
paths:
# 自定义的中继服务器配置文件,后面需要创建这个配置文件
- /etc/headscale/derp.yaml
auto_update_enabled: true
update_frequency: 24h
disable_check_updates: false
ephemeral_node_inactivity_timeout: 30m
node_update_check_interval: 10s

# SQLite config
db_type: sqlite3
db_path: /var/lib/headscale/db.sqlite

# acme自动生成ssl证书配置
acme_url: https://acme-v02.api.letsencrypt.org/directory
acme_email: ""
# 这里不使用自动前面证书,我自己网上生成。
tls_letsencrypt_hostname: ""
tls_client_auth_mode: relaxed
tls_letsencrypt_cache_dir: /var/lib/headscale/cache
tls_letsencrypt_challenge_type: HTTP-01
tls_letsencrypt_listen: ":http"
tls_cert_path: ""
tls_key_path: ""
log:
format: text
level: info
acl_policy_path: ""
dns_config:
nameservers:
# 给客户端分配dns服务器
- 114.114.114.114
domains: []
magic_dns: true
base_domain: example.com
unix_socket: /var/run/headscale.sock
unix_socket_permission: "0770"
logtail:
enabled: false
randomize_client_port: false
EOF

创建中继服务器使用的证书目录及证书

1
2
3
4
5
6
# 在headscale的配置目录新建一个中继服务器用的证书目录
$ cd /etc/headscale

# 将生成的证书文件一定要以 你解析的域名.key 你解析的域名.crt 这种格式
$ vim certs/derper.xxx.cn.key
$ vim certs/derper.xxx.cn.crt

创建中继服务器配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ cd /etc/headscale
$ cat >derp.yaml<<EOF
regions:
900:
regionid: 900
regioncode: thk
regionname: aliyun SH
nodes:
- name: 900a
regionid: 900
hostname: derper.xxx.cn
ipv4: 35.241.xx.221
stunport: 3478
stunonly: false
derpport: 8082
EOF

配置说明:

  • regions 是 YAML 中的对象,下面的每一个对象表示一个可用区,每个可用区里面可设置多个 DERP 节点,即 nodes
  • 每个可用区的 regionid 不能重复。
  • 每个 nodename 不能重复。
  • regionname 一般用来描述可用区,regioncode 一般设置成可用区的缩写。
  • ipv4 字段不是必须的,如果你的域名可以通过公网解析到你的 DERP 服务器地址,这里可以不填。如果你使用了一个二级域名,而这个域名你并没有在公共 DNS server 中添加相关的解析记录,那么这里就需要指定 IP(前提是你的证书包含了这个二级域名,这个很好支持,搞个泛域名证书就行了)。
  • stunonly: false 表示除了使用 STUN 服务,还可以使用 DERP 服务。
  • 上面的配置中域名和 IP 部分我都打码了,你需要根据你的实际情况填写。

安装docker并生成docker-compose文件

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
42
43
44
45
46
$ curl https://www.putianhui.cn/package/script/install_docker.sh | bash

# 如果docker-compose版本过低,请在这下载最新版本的
$ wget https://github.com/docker/compose/releases
$ cat > docker-compose.yaml<<EOF
version: '3.9'

services:
headscale:
container_name: headscale
image: headscale/headscale:0.16.4
ports:
- '8080:8080'
cap_add:
- NET_ADMIN
- NET_RAW
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv6.conf.all.forwarding=1
restart: always
volumes:
# 这里挂载当前目录到容器中
- ./:/etc/headscale
- ./data:/var/lib/headscale
command: ['headscale', 'serve']
derper:
container_name: derper
image: fredliang/derper
ports:
- '8082:8082'
- '3478:3478/udp'
environment:
# 这里域名改成你的
- DERP_DOMAIN=derper.xxx.cn
- DERP_CERT_MODE=manual
- DERP_ADDR=:8082
- DERP_HTTP_PORT=-1
restart: always
volumes:
# 这里把本地证书目录挂载到容器中,注意证书的名称一定要遵循格式
- ./certs:/app/certs
volumes:
config:
data:
EOF

启动

1
docker-compose up -d

启动成功后注意防火墙放行如下端口

1
2
# tcp协议:8080、8082
# udp协议:3478

服务端常用命令

1
2
3
4
5
6
7
8
9
10
# 如果是docker运行的服务端就用 [docker exec headscale headscale ns list] 这样
# 查看namespace列表
$ headscale ns list
# 创建namespace
$ headscale ns create test-net

# 查看服务端注册进来的节点列表
$ headscale nodes list
# 查看对应节点的routes,-i 1 这里是指节点列表前的id
$ headscale nodes routes list -i 1

安装客户端

Linux 用户目前只需要使用以下命令安装即可:

1
curl -fsSL https://tailscale.com/install.sh | sh

节点加入到服务端

1
tailscale up --login-server http://35.241.79.221:8080 --advertise-routes=192.168.0.0/24 --accept-routes=true --accept-dns=false

关于选项设置:

  • --login-server: 指定使用的中央服务器地址(必填)
  • --advertise-routes: 向中央服务器报告当前客户端处于哪个内网网段下, 便于中央服务器让同内网设备直接内网直连(可选的)或者将其他设备指定流量路由到当前内网(可选)
  • --accept-routes: 是否接受中央服务器下发的用于路由到其他客户端内网的路由规则(可选)
  • --accept-dns: 是否使用中央服务器下发的 DNS 相关配置(可选, 推荐关闭)
  1. 执行加入命令完成后, tailscale 将会卡住, 并打印一个你的服务器访问地址; 浏览器访问该地址后将会得到一条命令

  2. 复制到浏览器访问显示的链接,然后浏览器会显示一条服务端执行的命令。

  3. 复制浏览器显示的命令,去服务端执行一下。

    1
    2
    3
    4
    5
    6
    # NAMESPACE换成你自己的namespace名称,如果没有用下面的命令创建一个。
    # 创建namespace
    $ headscale ns create test-net

    # 执行浏览器显示的命令,注意替换NAMESPACE为你自己的。
    $ docker exec headscale headscale -n NAMESPACE nodes register --key 584b3fc394e9c8a310ac1c23122dfc03a16422674f38dfe2cac780cdb6cd1503
  4. 当服务端执行命令后,几秒钟客户端就自动退出一直卡住的界面了。

  5. 此时客户端就可以ping通对端集群内的客户端vpn-ip了。

上面步骤完成后只能客户端之间ping通客户端的vpn-ip,如果想ping对端客户端所在的内网其他主机,需要用下面命令开启路由功能.

1
2
3
4
5
# 以下命令在服务端执行
# 查看服务端注册进来的节点列表
$ headscale nodes list
# 查看对应节点的routes,-i 1 这里是指节点列表前的id,把所有节点都开启路由
$ headscale nodes routes list -i 1

此时就可以在一个客户端去ping对端内网的其他主机了。

客户端常用命令

1
2
3
4
5
6
7
8
# 查看当前节点vpn网段ip
$ tailscale ip
# 查看当前节点到其他对等网的信息,显示字段依次是 主机名,namespace,操作系统,客户端状态,direct|relay
$ tailscale status
# 网络到其他地域的延迟检查
$ tailscale netcheck
# ping其他对端的vpn-ip,如果是直连ping一下就停止,如果走了中继服务器就一直ping
$ tailscale ping 192.168.66.1

自建私有中继服务器

中继服务器部署

1
2
3
4
5
6
7
8
9
10
11
12
13
# 在headscale的配置目录新建一个中继服务器用的证书目录
$ pwd
/etc/headscale

# 创建中继服务器使用的证书目录
$ mkdir certs

# 将生成的证书文件一定要以 你解析的域名.key 你解析的域名.crt 这种格式
$ vim certs/derper.xxx.cn.key
$ vim certs/derper.xxx.cn.crt

# 启动服务
docker run -d --name derper -v /etc/headscale/certs:/app/certs -e DERP_DOMAIN=derper.xxx.cn -e DERP_CERT_MODE=manual -e DERP_ADDR=:8082 -e DERP_HTTP_PORT=-1 -p 8082:8082 -p 3478:3478/udp fredliang/derper

启动参数介绍

  • -d:容器后台运行
  • --name:指定容器名称
  • -v:将宿主机/etc/headscale/certs这个ssl证书目录挂载到容器中的/app/certs证书目录。
  • -e DERP_DOMAIN:指定你解析过来的二级域名
  • -e DERP_CERT_MODE:ssl证书的模式使用自定义
  • -e DERP_ADDR:自定义端口

配置headscale使用自定义中继服务器

1、在headscale的配置目录下创建一个中继服务器列表文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ cat >derp.yaml<<EOF
regions:
900:
regionid: 900
regioncode: thk
regionname: aliyun SH
nodes:
- name: 900a
regionid: 900
hostname: derper.xxx.cn
ipv4: 35.241.xx.221
stunport: 3478
stunonly: false
derpport: 8082
EOF

配置说明:

  • regions 是 YAML 中的对象,下面的每一个对象表示一个可用区,每个可用区里面可设置多个 DERP 节点,即 nodes
  • 每个可用区的 regionid 不能重复。
  • 每个 nodename 不能重复。
  • regionname 一般用来描述可用区,regioncode 一般设置成可用区的缩写。
  • ipv4 字段不是必须的,如果你的域名可以通过公网解析到你的 DERP 服务器地址,这里可以不填。如果你使用了一个二级域名,而这个域名你并没有在公共 DNS server 中添加相关的解析记录,那么这里就需要指定 IP(前提是你的证书包含了这个二级域名,这个很好支持,搞个泛域名证书就行了)。
  • stunonly: false 表示除了使用 STUN 服务,还可以使用 DERP 服务。
  • 上面的配置中域名和 IP 部分我都打码了,你需要根据你的实际情况填写。

2、修改 Headscale 的配置文件,引用上面的自定义 DERP 配置文件。需要修改的配置项如下:

1
2
3
4
5
6
7
8
9
10
11
12

# /etc/headscale/config.yaml
derp:
# List of externally available DERP maps encoded in JSON
# 把默认使用官方的中继服务器配置禁用掉,方便测试。
urls:
# - https://controlplane.tailscale.com/derpmap/default

#
# 这里的中继服务器配置列表用我们新创建的。
paths:
- /etc/headscale/derp.yaml

修改完配置后,重启 headscale 服务

3、在 Tailscale 客户端上使用以下命令查看目前可以使用的 DERP 服务器

1
2
3
4
5
6
7
8
9
10
11
$ tailscale netcheck
Report:
* UDP: true
* IPv4: yes, 120.26.48.71:39855
* IPv6: no, but OS has support
* MappingVariesByDestIP:
* HairPinning: false
* PortMapping:
* Nearest DERP: aliyun SH # 这里显示我们使用的中继服务器
* DERP latency:
- thk: 33.9ms (aliyun SH)