自建 Headscale + DERP 全流程实战记录

2003 字
10 分钟
自建 Headscale + DERP 全流程实战记录

记录一次完整、可上线、可长期运行的 Headscale + 自建 DERP 搭建过程。
本文不是“能跑就行”的教程,而是生产可用、已多客户端验证的配置方案。

简介#

  • Tailscale(Headscale)就是组建一个大的局域网,可以将你手里头的所有设备都拉到这个局域网内,进而使用局域网IP进行互联。
  • 此外,Tailscale(Headscale)还有一个作用就是内网穿透,局域网内的设备之间的访问会通过穿透进行打洞(成功概率挺高),进而实现公网的点对点互联。而且就算打洞失败,也可以利用中转服务器进行互联。
  • 应用场景举例:家里没有公网IP,但是可以通过Tailscale组网和穿透的方式实现在任意网络下对家里设备的访问。

整体架构说明#

  • 使用 Headscale 作为 Tailscale 控制平面
  • 自建 DERP Server,不依赖官方 DERP
  • 使用 宝塔 / Nginx 统一终止 TLS
  • 开启 DERP 防白嫖(verify-clients)
  • 多客户端 tailscale netcheck 验证通过

最终架构如下:#

Tailscale Client
Headscale(控制平面)
↓ 下发 DERP Map
https://derp.muxui.com/derp.json
DERP Server(derper,HTTP 本地端口)
宝塔 / Nginx(HTTPS 443)

DERP Server 搭建#

安装最新版GO#

  • 更新软件包,安装依赖
apt update && apt upgrade
apt install -y wget git openssl curl
  • 下载最新版GO
wget https://go.dev/dl/go1.25.5.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.25.5.linux-amd64.tar.gz

目前最新版为1.25.5,后续若有更新则可以去 https://go.dev/dl/ 查看最新版并替换下载即可,记得后面的版本号都要改

  • 配置环境变量
export PATH=$PATH:/usr/local/go/bin
go version
echo "export PATH=$PATH:/usr/local/go/bin" >> /etc/profile
source /etc/profile
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

安装最新版Derper#

  • 安装
go install tailscale.com/cmd/derper@latest
  • 拷贝二进制文件
mkdir /etc/derp/
cp ~/go/bin/derper /etc/derp/
  • 查看是否拷贝成功
ls /etc/derp

derper 域名部署(宝塔反代模式,国内服务器域名需要备案)#

⚠️ 关键原则:DERP 不自己处理 TLS

  • TLS 由宝塔 / Nginx 负责
  • derper 只监听本地 HTTP

正确启动参数(手动验证用):#

/etc/derp/derper \
-a :13445 \
--hostname derp.muxui.com \
--certmode=off \
--stun \
--stun-port 3478 \
--verify-clients

看到以下日志即为成功:

STUN server listening on [::]:3478
derper: serving on :13445

systemd 服务(最终版)#

[Unit]
Description=Tailscale DERP Server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
ExecStart=/etc/derp/derper \
-a :13445 \
--hostname derp.muxui.com \
--certmode=off \
--stun \
--stun-port 3478 \
--verify-clients
Restart=always
RestartSec=5
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target

启用并启动:

systemctl daemon-reload
systemctl enable derp --now
systemctl status derp

Derper IP部署(123.123.123.123改成自己服务器的IP)#

DERP_IP="123.123.123.123"
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout ${DERP_IP}.key -out ${DERP_IP}.crt -subj "/CN=${DERP_IP}" -addext "subjectAltName=IP:${DERP_IP}"

这时候/root文件夹下会有两个证书文件:/root/123.123.123.123.crt/root/123.123.123.123.key,拷贝到/etc/derp/:

mv /root/123.123.123.123.crt /etc/derp
mv /root/123.123.123.123.key /etc/derp

启动Derper服务器#

  • 写入后台

新建文件derp.service

touch /etc/systemd/system/derp.service

写入以下内容

[Unit]
Description=TS Derper
After=network.target
Wants=network.target
[Service]
User=root
Restart=always
ExecStart=/etc/derp/derper -hostname 123.123.123.123 -a :13445 -http-port 13446 -certmode manual -certdir /etc/derp
RestartPreventExitStatus=1
[Install]
WantedBy=multi-user.target

  • 启动
systemctl enable derp
systemctl restart derp
systemctl status derp

验证Derper是否搭建成功#

浏览器打开https://123.123.123.123:13445,忽略不安全,看看是不是显示下面的内容:

DERP
This is a Tailscale DERP server.

It provides STUN, interactive connectivity establishment, and relaying of end-to-end encrypted traffic for Tailscale clients.

Documentation:

About DERP
Protocol & Go docs
How to run a DERP server

DERP 防白嫖(verify-clients)#

为什么必须开启?#

不开启 --verify-clients

  • 任何人只要知道你的 DERP 地址
  • 都可以把你当 TCP 中继刷流量

verify-clients 的工作方式#

  • DERP 通过 本机的 tailscaled
  • Headscale 校验客户端身份
  • 只允许本 Tailnet 成员使用

搭建Headscale和Headscale-ui#

 安装最新版Headscale#

  • 下载
wget --output-document=headscale.deb \
https://github.com/juanfont/headscale/releases/download/v0.27.1/headscale_0.27.1_linux_amd64.deb

目前最新版为0.27.1,后续若有更新则可以去 https://github.com/juanfont/headscale/releases 查看最新版并替换下载即可,记得后面的版本号都要改


  • 安装
mv headscale_0.27.1_linux_amd64.deb headscale.deb
dpkg --install headscale.deb

  • 修改配置文件(/etc/headscale/config.yaml

仅列出需要修改的地方

server_url: https://headscale.muxui.com
listen_addr: 0.0.0.0:8080
metrics_listen_addr: ""
prefixes:
v4: 100.64.0.0/10
# v6: fd7a:115c:a1e0::/48
# List of externally available DERP maps encoded in JSON
urls:
- https://derp.muxui.com/derp.json
base_domain: tailnet.muxui.com
# List of DNS servers to expose to clients.(建议改成国内适合自己的DNS)
nameservers:
global:
- 114.114.114.114

  • 启动
systemctl enable headscale
systemctl restart headscale
systemctl status headscale

3.3 安装最新版Headscale-ui#

  • 下载
wget https://github.com/gurucomputing/headscale-ui/releases/download/2025.08.23/headscale-ui.zip

目前最新版为2025.08.23,后续若有更新则可以去 https://github.com/gurucomputing/headscale-ui 查看最新版并替换下载即可,记得后面的版本号都要改


  • 安装
apt-get install unzip
unzip -d /var/www headscale-ui.zip

配置Derper服务器#

  • 配置/etc/headscale/derp.json文件

新建

touch /etc/headscale/derp.json

写入以下内容

ip部署

{
"Regions": {
"901": {
"RegionID": 901,
"RegionCode": "Myself",
"RegionName": "Myself Derper",
"Nodes": [
{
"Name": "901a",
"RegionID": 901,
"DERPPort": 13445,
"IPv4": "123.123.123.123",
"InsecureForTests": true
}
]
}
}
}

使用域名(推荐做法)#

{
"Regions": {
"901": {
"RegionID": 901,
"RegionCode": "MUXUI",
"RegionName": "Muxui DERP",
"Nodes": [
{
"Name": "901a",
"RegionID": 901,
"HostName": "derp.muxui.com",
"DERPPort": 443,
"InsecureForTests": true
}
]
}
}
}

Nginx / 宝塔暴露 derp.json#

location /d/derp.json {
alias /etc/headscale/derp.json;
default_type application/json;
}

验证:

https://derp.muxui.com/derp.json

能直接返回 JSON。

如果不是宝塔,就下载安装并配置Nginx

  • 下载
apt install -y nginx

  • 打开/etc/nginx/sites-available/default并添加以下内容:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name headscale.example.com;
ssl_certificate /root/cert.crt;
ssl_certificate_key /root/private.key;
ssl_protocols TLSv1.2 TLSv1.3;
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 $scheme;
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
}
location /web {
index index.html;
alias /var/www/web;
}
}
server {
listen 80;
listen [::]:80;
server_name 127.0.0.1;
root /var/www;
index index.html index.htm index.nginx-debian.html;
location /d {
alias /var/www;
autoindex on;
}
location / {
try_files $uri $uri/ =404;
}
}

  • 启动
systemctl enable nginx
systemctl restart nginx
systemctl status nginx

验证安装#

  • 重启Derper,Headscale和Nginx服务
systemctl restart derp
systemctl status derp
systemctl restart headscale
systemctl status headscale
systemctl restart nginx
systemctl status nginx

  • 打开网站

https://headscale.example.com/web

如无意外应该是三个服务的状态应该是全绿的,网页也能正常打开,有报错的话建议按教程自查或在帖子底下留言

配置Headscale-ui#

  • 生成API Key
headscale apikeys create --expiration 9999d

并将其写入到https://headscale.muxui.com/web/settings.htmlHeadscale API Key里面,点击Save API Key提交,见到右侧有小对勾即可


  • 新建用户Default

打开https://headscale.`muxui`.com/web/users.html,点击New User,输入Default并提交

最终验证(最关键)#

Windows 客户端 netcheck#

tailscale netcheck

结果示例:

Nearest DERP: Muxui DERP
DERP latency:
- MUXUI: 6.9ms

下载最新客户端#

https://tailscale.com/download


启动指令解析#

—login-server: 指定使用的Headscale服务器地址,即https://headscale.example.com
—advertise-routes: 向Headscale服务器报告当前客户端处于哪个内网网段下, 便于Headscale服务器让同内网设备直接内网直连(可选的)或者将其他设备指定流量路由到当前内网(可选),多条路由英文逗号隔开
—accept-routes: 是否接受Headscale服务器下发的用于路由到其他客户端内网的路由规则(可选)
—accept-dns: 是否使用Headscale服务器下发的 DNS 相关配置(可选, 推荐关闭)
—force-reauth:强制重新认证
—advertise-exit-node:作为出口节点


不同客户端的启动方法#

  • Windows

以管理员身份启动PowerShell,输入以下代码:

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

  • iOS

用非国区Apple ID下载,配置V P N文件

点击右上角头像,点击Log In...,点击右上角三个点,点击Use a custom coordination server,输入https://headscale.example.com,点击Login in


  • Linux

安装

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

运行

tailscale up --reset --advertise-routes=192.168.x.0/24 --accept-routes=true --login-server=https://headscale.example.com

到Headscale-ui中允许设备加入局域网#

上面在客户端执行了tailscale up之后,在客户都会显示一个带Device Key的代码,格式类似于:

headscale nodes register --user USERNAME --key mkey:ed8f19e22f51c9c231c8bc8ccbxxxxxxxxxxxxxxf86c8211e4ad32b6c6e

拷贝mkey:ed8f19e22f51c9c231c8bc8ccbxxxxxxxxxxxxxxf86c8211e4ad32b6c6e,去 https://headscale.example.com/web/devices.html中导入Device Key

 参考教程#

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

自建 Headscale + DERP 全流程实战记录
https://muxui.com/posts/自建-headscale-derp-全流程实战记录/
作者
Muxui
发布于
2025-12-25
许可协议
CC BY-NC-SA 4.0
相关文章智能推荐
1
YOLO训练麻将(Mahjong)识别,导出ONNX
文章本文基于 Roboflow Universe 数据集(例如 $1 )与仓库内脚本,在 Windows 上完成训练,并导出 ONNX 供后端推理。下文配图均为本机实测截图,便于对照。快速体验 小程序 1\. 环境要求 \ Windows 10
2
[开源]AI Summary - WordPress智能摘要生成插件
PHPAI Summary是一款专为WordPress设计的智能摘要生成插件,它集成了五大主流AI服务:百度文心一言、OpenAI ChatGPT、Google Gemini、字节豆包和阿里通义千问。无论您是个人博客作者还是企业网站运营者,这款插
3
Java线程池
Java总体设计 ThreadPoolExecutor实现的顶层接口是Executor,顶层接口Executor提供了一种思想:将任务提交和任务执行进行解耦。用户无需关注如何创建线程,如何调度线程来执行任务,用户只需提供Runnable对象,将任务
4
Java线程知识
Java线程基础 Java线程是什么? 线程 (Thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。 进程 (Process):程序运行的实例,每个进程有独立的内存空间。 线程 :进程内部的执行单元,可以
5
从 WordPress 到 Astro迁移实战全记录
文章记录将 Muxui 从 WordPress(B2 Pro)完整迁移到 Astro 静态博客主题 Firefly 的全过程:导出 WXR、HTML 转 Markdown、图床改写、友链与导航定制,以及迁移中踩过的坑。
随机文章随机推荐

评论区

Profile Image of the Author
Muxui
Hello, I'm Muxui.
公告
欢迎来到我的博客!这是一则示例公告。
分类
标签
站点统计
文章
24
分类
8
标签
19
总字数
53,213
运行时长
0
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.14.5
文章许可
CC BY-NC-SA 4.0