静看光阴荏苒
不管不顾不问不说也不念

部署Headscale控制服务器和DERP中继服务器

介绍

Tailscale是一款构建在Wireguard之上的现代VPN,Tailscale中的大部分内容都是开源的,但是客户端以及控制服务器不开源,Headscale是Tailscale控制服务器的开源替代方案。

DERP中继服务器是后备方案,当NAT打洞无法成功的时候转而使用DERP服务器进行中继连接。虽然Tailscale提供了很多官方的DERP中继服务器,但往往延迟都非常高体验不好,所以就有了自建的必要。

部署Headscale控制服务器

系统我使用的是Debian12,可在Headscale项目页面直接下载deb包进行安装:

apt -y update
apt -y install wget
wget https://github.com/juanfont/headscale/releases/download/v0.22.3/headscale_0.22.3_linux_amd64.deb
dpkg -i headscale_0.22.3_linux_amd64.deb
systemctl enable headscale

由于我的这台机器还跑着其他的服务,所以我将配置Headscale在反向代理后面运行,这样可以重用443端口不会影响到机器上其他的服务。安装NGINX/CertBot:

apt -y install nginx python3-certbot-nginx

编辑Headscale的配置文件:

nano /etc/headscale/config.yaml

需要修改的配置如下,其他的内容暂时不用管:

server_url: https://headscale.example.com # 修改为你的域名
listen_addr: 0.0.0.0:8080
metrics_listen_addr: 0.0.0.0:9090

启动Headscale并检查运行状态:

systemctl start headscale
systemctl status headscale

新建NGINX站点配置文件:

nano /etc/nginx/sites-available/headscale

写入如下配置:

map $http_upgrade $connection_upgrade {
    default      keep-alive;
    'websocket'  upgrade;
    ''           close;
}

server {
    listen 80;
    server_name headscale.example.com; # 修改为你的域名

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $server_name;
        proxy_redirect http:// 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;
        add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
    }

    error_log /var/log/nginx/headscale-proxy-error.log;
    access_log /var/log/nginx/headscale-proxy-access.log;
}

启用站点:

ln -s /etc/nginx/sites-available/headscale /etc/nginx/sites-enabled/headscale

签发SSL证书:

certbot --nginx

使用Headscale

首先需要在Headscale控制服务器创建一个用户:

headscale users create imlala

然后在要接入Headscale网络的机器上安装Tailscale客户端,这里我用一台Windows10和iPhone演示。

Windows客户端下载:https://pkgs.tailscale.com/stable/tailscale-setup-latest.exe

其他平台的客户端下载:https://tailscale.com/download/

安装好客户端后用管理员权限打开PowerShell,执行如下命令登录到我们自建的Headscale:

tailscale login --login-server https://headscale.example.com

接下来在Headscale控制服务器上注册我这台Windows10的机器:

headscale nodes register --user imlala --key nodekey:xxxxx

这样我就将一台Windows10机器加入到了网络内,使用如下命令可检查:

headscale nodes list

在iPhone上安装好Tailscale客户端后,打开设置-找到Tailscale,在ALTERNATE COORDINATION SERVER URL这里填写上你自建的Headscale控制服务器网址:

之后的步骤就和在Windows上的一致了,打开APP登录会回显给你一个注册命令,在Headscale控制服务器上执行给出的命令即可完成注册。

部署DERP中继服务器

部署DERP中继服务器我使用的系统是Debian12,机器是一台甲骨文ARM。

首先要在这台机器上安装Tailscale客户端,添加Tailscale官方的存储库安装即可,此举是为了后续能启用DERP服务的鉴权功能,防止被其他人滥用:

wget https://pkgs.tailscale.com/stable/debian/bookworm.noarmor.gpg -O /usr/share/keyrings/tailscale-archive-keyring.gpg
wget https://pkgs.tailscale.com/stable/debian/bookworm.tailscale-keyring.list -O /etc/apt/sources.list.d/tailscale.list
apt -y update
apt -y install tailscale

确保tailscaled服务正常运行:

systemctl status tailscaled.service

登录到我们自建的Headscale控制服务器:

tailscale up --login-server https://headscale.example.com

在Headscale控制服务器上注册我这台甲骨文ARM的机器:

headscale nodes register --user imlala --key nodekey:xxxxx

安装Golang:

curl -L https://go.dev/dl/go1.21.1.linux-arm64.tar.gz -o go1.21.1.linux-arm64.tar.gz
tar -C /usr/local -xzf go1.21.1.linux-arm64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin' > /etc/profile.d/golang.sh
source /etc/profile.d/golang.sh

新建一个derp用户登录到这个用户:

useradd -r -m -d /opt/derp -s /bin/bash derp
su - derp

安装DERP,完成之后退出当前用户:

go install tailscale.com/cmd/derper@main
exit

[可选]让DERP服务可以绑定低位端口,例如80、443,由于后续我将使用反向代理所以这个步骤可以省略:

setcap 'cap_net_bind_service=+ep' /opt/derp/go/bin/derper

[可选]做一个软链接方便使用:

ln -s /opt/derp/go/bin/derper /usr/local/bin/derper

新建systemd服务:

nano /etc/systemd/system/derper.service

写入如下配置,你只需要将derp.example.com修改成你自己的域名即可:

[Unit]
Description=DERP Server
After=network.target

[Service]
User=derp
Group=derp
AmbientCapabilities=CAP_NET_BIND_SERVICE
WorkingDirectory=/opt/derp
ExecStart=/opt/derp/go/bin/derper -hostname=derp.example.com -c /opt/derp/derper.conf -a 0.0.0.0:9981 -http-port -1 --verify-clients
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

[重要]–verify-clients参数务必要保留,鉴权需要,否则任何人都能连接上你的DERP服务。

启动DERP服务并设置开机自启:

systemctl enable --now derper.service

检查运行状态确保正常运行:

systemctl status derper.service

安装NGINX/CertBot用于反向代理:

apt -y install nginx python3-certbot-nginx

新建NGINX站点配置文件:

nano /etc/nginx/sites-available/derper

写入如下配置:

server {
    listen       80;
    server_name  derp.example.com;

    location / {
        proxy_pass http://127.0.0.1:9981;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    error_log /var/log/nginx/derp-proxy-error.log;
    access_log /var/log/nginx/derp-proxy-access.log;
}

启用站点:

ln -s /etc/nginx/sites-available/derper /etc/nginx/sites-enabled/derper

签发SSL证书:

certbot --nginx

访问DERP服务的域名,如果能看到下图的内容说明DERP服务正常运行:

回到Headscale控制服务器,新建一个DERP服务配置文件:

nano /etc/headscale/derp.yaml

写入如下内容,注意derp.example.com修改为你自己的域名:

regions:
  900:
    regionid: 900
    regioncode: kr
    regionname: oraclekr
    nodes:
      - name: 900a
        regionid: 900
        hostname: derp.example.com
        stunport: 3478
        stunonly: false
        derpport: 443

编辑Headscale控制服务器的配置文件:

nano /etc/headscale/config.yaml

注释掉如下URL以禁用Tailscale官方的DERP服务器,指定刚才新建的DERP服务配置文件:

derp:
  server:
    enabled: false
...
  urls: []
  #  - https://controlplane.tailscale.com/derpmap/default
...
  paths:
    - /etc/headscale/derp.yaml
...

重启Headscale:

systemctl restart headscale

测试DERP中继服务

在Windows客户端执行如下命令查看当前的网络状态:

tailscale netcheck

可以看到DERP服务器列表里面只有我们自建的服务器:

如果两台设备之间通过DERP服务器中继连接,那么也可以执行下面的命令查看连接状态:

tailscale status

或者直接使用内置的PING命令:

tailscale ping iphone

这样最直观:

配置Headscale Exit Nodes(出口节点)

你可以将接入到Headscale网络内的任意节点(设备)设置为Exit Nodes(出口节点)。

这有什么用呢?打个最简单的比方,假设你的Headscale网络内接入了一台境外的VPS,你把这台境外的VPS设置为Exit Nodes,之后你所有接入到Headscale网络内的节点(设备)都可以直接翻墙。

也就是说如果我把自己的这台甲骨文ARM设置为Exit Nodes,那么我之前接入的Windows10、iPhone等设备就可以通过这台甲骨文ARM来翻墙了。下面简单演示一下。

设置Exit Nodes的机器要开启IP转发:

echo 'net.ipv4.ip_forward = 1' | tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | tee -a /etc/sysctl.d/99-tailscale.conf
sysctl -p /etc/sysctl.d/99-tailscale.conf

宣告自己想成为Exit Nodes:

tailscale set --advertise-exit-node

回到Headscale控制服务器,执行如下命令:

headscale routes list

可以看到有两条路由但还没有启用:

ID | Machine    | Prefix    | Advertised | Enabled  | Primary
1  | moonbridge | ::/0      | true       | false    | -
2  | moonbridge | 0.0.0.0/0 | true       | false    | -

再通过执行如下命令来启用这两条路由:

headscale routes enable -r 1
headscale routes enable -r 2

再次查看路由就是启用的状态了:

ID | Machine    | Prefix    | Advertised | Enabled | Primary
1  | moonbridge | ::/0      | true       | true    | -
2  | moonbridge | 0.0.0.0/0 | true       | true    | -

现在我们就可以配置客户端来使用这个出口节点了,在Windows的Tailscale客户端,找到Exit Node选项:

在这里就可以选择使用出口节点了:

iPhone的客户端更简单:

赞(3)
未经允许不得转载:荒岛 » 部署Headscale控制服务器和DERP中继服务器
分享到: 更多 (0)

评论 6

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #1

    不知道为什么,出口特别喜欢离线……

    Saiki7个月前 (10-02) Microsoft Edge 117.0.2045.47 Microsoft Edge 117.0.2045.47 GNU/Linux x64 GNU/Linux x64回复
  2. #2

    p

    abc6个月前 (10-18) Google Chrome 88.0.4324.141 Google Chrome 88.0.4324.141 Android 12 Android 12回复
  3. #3

    headscale 客户端自带derp 服务端可以设置开启,不需要额外安装derp

    lovetailscale5个月前 (11-22) Google Chrome 116.0.0.0 Google Chrome 116.0.0.0 Android 10 Android 10回复

分享创造快乐

广告合作资源投稿