侧边栏壁纸
博主头像
KoolMax 博主等级

行动起来,活在当下

  • 累计撰写 13 篇文章
  • 累计创建 3 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

【Tailscale】从源码搭建DERPer中继及Headscale导入

Administrator
2025-07-25 / 0 评论 / 0 点赞 / 3 阅读 / 0 字

DERP是Tailscale的中继服务器,负责交换客户端之间的连接信息和在无法直接连接时中继流量。其本身只负责协调和转发,不会解密协议承载的流量,因此使用官方的DERP服务器同样是安全的。但是,由于国内较为特殊的网络环境,官方的节点连接到中国大陆时延迟和稳定性均欠佳,而仅凭Headscale内置的单一节点有时是不满足需求的。

Tailscale Derper同样是一个官方开源软件的一部分,但是网上的教程多使用docker搭建,不是很适合在刁钻的环境下使用🥶,在此把博主的一些探索做一个简单的记录。

注意:这是一篇纯文字的流程记录,未添加详细的配图和说明,需要一定的基础进行实践。


一、编译DERP

DERP中继的docker搭建在互联网上已有大量的教程,并且操作非常简单。但是,docker下的derper镜像中不包含tailscale客户端,如果需要对接入设备进行认证则需要将宿主中的tailscale映射至容器中,反而增加了一些麻烦。实际上,derper程序本身也是一个基于go构建的binary单文件,只是官方未提供预编译包,需要我们自己使用go环境进行编译。

# 从https://go.dev/dl/下载对应架构的go环境
wget https://go.dev/dl/go1.23.3.linux-amd64.tar.gz
# 解压
tar -zxvf go1.23.3.linux-amd64.tar.gz
# 移动到go环境目录
cd ./go
# 从源码构建derper二进制文件
./bin/go install tailscale.com/cmd/derper@main
# 在go环境的bin路径下可以找到编译好的derper二进制文件,并进行测试
./bin/derper -version
# 提取文件(可选至指定目录)
cp ./bin/derper /usr/bin/derper
# 添加可执行权限
chmod +x /usr/bin/derper
# 如不需要再次编译,可直接删除go环境
rm -rf /root/go

在以上的方法中,我们只是临时使用go环境,无需将其添加至环境变量,在使用后也可直接删除。

在此获得derper二进制文件可以直接复制到任意同架构和系统版本的系统中运行,也就是你可以在任意同类的环境编译好后分再发到其他的服务器。


二、安装Tailscale

为了防止derper服务器被其他用户使用,我们需要在服务器上运行tailscale客户端接入自己的tailnet网络,来为开启了-verify-clients的derp提供认证信息。

# 最简单地加入一个Tailnet

tailscale up --login-server=https://my.headscale  --netfilter-mode=off --accept-dns=false

安装过程不再赘述,但需要特别注意在阿里云的ECS上,MagicDNS使用的100.100.100.100地址可能与阿里云内网DNS冲突,会导致服务器联网出现问题。可以考虑切换服务器DNS至PublicDNS或修改Tailscale源码解除对该地址的占用。


三、运行DERPer

准备好derper二进制包后,接下来可以进行一些运行的测试工作。在此假设所有文件都位于/home/derp目录下,可以按照以下的方式选择一个合适你使用场景的命令。


# 独占443端口HTTPS访问,HTTP 80端口跳转HTTPS,并验证连接客户端

# 证书通过Let's Encrypt HTTP获取,必须具有独占的80和443端口

/home/derp/derper -c /home/derp/derper.conf -a :443 -http-port 80 -stun-port 3478 -hostname my.derp -certmode letsencrypt -verify-clients

# 使用非标准端口HTTPS访问,手动更新证书,并验证连接客户端

# 证书手动放置于/home/derp中,文件名必须为主机名,如my.derp.crt和my.derp.key

/home/derp/derper -c /home/derp/derper.conf -a :8443 -http-port 8080 -stun-port 3478 -hostname my.derp -certmode manual -certdir /home/derp -verify-clients

# 监听本地HTTP端口,通过NGINX反代访问

# 证书配置在NGINX上,可与其他网站共存

/home/derp/derper -c /home/derp/derper.conf -a :8080 -stun-port 3478 --verify-clients

搭配NGINX转发可以更好的隐藏服务特征,因此博主均使用第三种配置方式作为演示。对于使用systemd的系统(如debian、ubuntu等),将其修改好写入对应位置后,依次进行以下配置实现授权、启动和开机自启:

文件路径:/etc/systemd/system/derper.service
管理进程:service derper start|stop|status
开机自启:rc-upadte add derper

derper.service

[Unit]

Description=Derper Service

After=network.target



[Service]

Type=simple

User=root

Restart=on-failure

RestartSec=5s

# 替换为上述测试好合适的启动命令

WorkingDirectory=/home/derp

ExecStart=/home/derp/derper -c /home/derp/derper.conf -a :8080 -stun-port 3478 -verify-clients

 

[Install]

WantedBy=multi-user.target

对于像Alpine一样使用init.drc-local的系统,将其修改好写入对应位置后,依次进行以下配置实现授权、启动和开机自启:

文件路径:/etc/init.d/derper
文件提权:chmod +x /etc/init.d/derper
管理进程:/etc/init.d/derper start|stop|status
开机自启:rc-upadte add derper

service

#!/sbin/openrc-run

supervisor=supervise-daemon

name="derper"

# 替换为上述测试好合适的启动命令

command="/home/derp/derper"

command_args="-c /home/derp/derper.conf -a :8080 -stun-port 3478 -verify-clients"

 

pidfile="/run/derper.pid"

respawn_delay=5

respawn_max=0


depend() {

        need net

        after firewall

        use logger

}

NGINX在vhsot和证书配置好后,只需要为/derp路径添加反向代理配置即可,无需对全局进行反向代理(也就是可以做到依附在某个网站上)。如果在headscale的derp.yaml中设定了IP地址则该域名可以不进行DNS解析,具有非常好的隐蔽性。配置好后,直接访问对应的路径会有DERP的提示信息,如果确有需要还可以通过sub_filter去掉。

proxy.conf

location /derp {

    proxy_pass http://127.0.0.1:8080;

    proxy_set_header Host $host;

    proxy_set_header X-Real-IP $remote_addr;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_set_header REMOTE-HOST $remote_addr;

    proxy_set_header Upgrade $http_upgrade;

    proxy_set_header Connection $connection_upgrade;

    proxy_http_version 1.1;

    proxy_buffering off;

}

四、添加DERP

Headscale的搭建可以参考博主之前的文章(点击前往),首先需要在headscale的config.yamlderp字段下取消注释paths:并设置好其下的derp.yaml路径,实现从该文件载入DERP列表。官方有提供derp.yaml的示例(点击前往),按照derper的实际信息进行填写。配置好后,重启headscale服务即可。

derp.yaml



regions:

  # 自建DERPER的RegionID设置区间为900-999,不会与官方节点冲突

  900:

    regionid: 900

    regioncode: Shanghai

    regionname: Shanghai Mobile

    nodes:

      - name: 900a

        regionid: 900

        # 主机名,可搭配NGINX反向代理使用

        hostname: derp1.headscale.web

        # IP地址,注意IPv6需添加半角引号,没有时注释掉

        # 使用DDNS的DERP时,请将ipv4和ipv6都注释掉

        ipv4: 123.123.123.123

        ipv6: "2001:da8::1"

        # STUN端口,设置为-1即不开启STUN服务

        stunport: 3478

        # 设置为true仅作为STUN打洞使用

        stunonly: false

        # 通信端口,必须为通过HTTPS访问的端口

        derpport: 443

  # 第一个地域配置完成后,可添加其他地域,同时一个地域也可有多台不同的节点

YAML

由于境内的云服务器多不具备IPv6支持,如果你不想在Headscale引入官方节点以支持IPv6打洞的话,你可以在自己的节点中引入一些支持IPv6的公开STUN节点(比如Cloudflare和Google等)。这样也有一个小问题就是IPv6延迟偏高,会降低IPv6连接优先级,可以尝试寻找一些低延迟的STUN服务器来解决。



regions:

  910:

    regionid: 910

    regioncode: Hubei

    regionname: Hubei Telecom

    nodes:

      # 自己纯IPv4的DERP节点

      - name: 910a

        regionid: 910

        hostname: hb.lty.fun

        ipv4: 59.153.1.1

        stunport: 3478

        stunonly: false

        derpport: 443

      # 添加公开的STUN用于IPv6打洞

      - name: 910x

        regionid: 910

        hostname: stun.cloudflare.com

        ipv6: "2a06:98c1:3200::"

        stunport: 3478

        stunonly: true

      - name: 910y

        regionid: 910

        hostname: stun.l.google.com

        ipv6: "2001:4860:4864:5:8000::1"

        stunport: 19302

        stunonly: true

五、结语

添加结束后,可在客户端使用tailscale netcheck检查是否添加成功,并获得延迟信息。由于Tailscale客户端以延迟排序选择DERP节点,可能需要暂时移除部分其他DERP节点以对其进行单独测试。当DERP节点不可用时Tailscale客户端会有很明显的报错出现,tailscale status中的relay也会降级至其他节点。

0

评论区