DERP(Designated Encrypted Relay for Packets)是 Tailscale 的中继与连通性组件。它主要承担两件事:

  1. 协助节点打洞,尽量建立直连
  2. 直连失败时,作为中继节点转发流量

两条部署路线:

  • Docker:上手快,依赖容器生态,换镜像即可升级
  • 非 Docker:系统服务 + 二进制,更接近系统级运维,替换二进制即可升级

快速导航

根据你的操作系统和部署方式,按下表选择对应章节:

操作系统 Docker 部署 非 Docker 部署
Debian / Ubuntu §3.1 §4.1
RHEL / CentOS / Rocky §3.2 §4.2
Alpine §3.3 §4.3

完成部署后,所有路径统一执行:§5 ACL 配置§6 客户端重连§7 测试验收

1. 部署参数

文中使用占位符表示需要替换的参数。后续步骤中出现这些占位符时,请替换为你的实际值。

占位符 说明 示例值
<VPS_IP> VPS 公网 IP xxx.xxx.xxx.xxx
<DERP_TCP_PORT> DERP TCP 端口 13477
<STUN_UDP_PORT> STUN UDP 端口 13478
<REGION_ID> 自定义 DERP 区域 ID 900
<REGION_CODE> 自定义 DERP 区域代码 tyxy
<RELAY_HOSTNAME> DERP 服务器的 Tailscale IP(通过 tailscale status 查看第一列) 100.x.x.x

如果你想先完整跑一遍,可把 <VPS_IP><DERP_TCP_PORT><STUN_UDP_PORT> 先替换为 xxx.xxx.xxx.xxx1347713478

2. 通用准备工作

2.1 检查服务器资源与网络信息

free -m
df -h
ip addr show

2.2 放行安全组与防火墙端口

  • <DERP_TCP_PORT>/tcp:DERP 服务端口
  • <STUN_UDP_PORT>/udp:STUN 服务端口

建议同时检查”云厂商安全组 + 系统防火墙”两层规则,避免本地通、外网不通。

3. Docker 部署

3.1 Debian / Ubuntu

安装 Docker 与 Compose

apt update
apt install -y docker.io docker-compose-plugin
systemctl enable --now docker
docker --version
docker compose version

可选:配置国内镜像加速

国内网络下拉取镜像较慢时可配置加速源,此配置写入后永久生效。

mkdir -p /etc/docker

cat > /etc/docker/daemon.json << 'EOF'
{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://dockerproxy.com",
    "https://docker.m.daocloud.io"
  ]
}
EOF

systemctl restart docker

低配置 VPS 可在 daemon.json 中追加以下参数:

{
  "registry-mirrors": ["..."],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "max-concurrent-downloads": 2
}
  • log-opts:限制单个日志文件最大 10MB、最多保留 3 个,防止磁盘被日志撑满
  • max-concurrent-downloads:限制同时下载层数为 2,降低内存和带宽占用

创建 docker-compose.yml

services:
  derper:
    image: ghcr.io/yangchuansheng/ip_derper
    container_name: derper
    restart: unless-stopped
    ports:
      - <DERP_TCP_PORT>:<DERP_TCP_PORT>  # 替换为 DERP 端口,如 13477
      - <STUN_UDP_PORT>:3478/udp         # 替换为 STUN 端口,如 13478
    environment:
      - DERP_ADDR=:<DERP_TCP_PORT>       # 替换为 DERP 端口,格式为 :<端口号>
      - DERP_VERIFY_CLIENTS=true          # 开启客户端验证,避免被公网滥用
    volumes:
      - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
  • STUN 容器内部端口固定为 3478/udp,左边是主机映射端口

启动并验证

docker compose up -d
docker logs derper
ss -tulnp | grep -E "<DERP_TCP_PORT>|<STUN_UDP_PORT>"  # 替换为实际端口号

安装 Tailscale 客户端

curl -fsSL https://tailscale.com/install.sh | sh
systemctl enable --now tailscaled
tailscale up

复制终端中的 https://login.tailscale.com/a/... 认证链接到浏览器完成登录,然后执行 tailscale status 确认状态。


3.2 RHEL / CentOS / Rocky / AlmaLinux

安装 Docker 与 Compose

dnf install -y docker docker-compose-plugin
systemctl enable --now docker
docker --version
docker compose version

可选:配置国内镜像加速

国内网络下拉取镜像较慢时可配置加速源,此配置写入后永久生效。

mkdir -p /etc/docker

cat > /etc/docker/daemon.json << 'EOF'
{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://dockerproxy.com",
    "https://docker.m.daocloud.io"
  ]
}
EOF

systemctl restart docker

低配置 VPS 可在 daemon.json 中追加以下参数:

{
  "registry-mirrors": ["..."],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "max-concurrent-downloads": 2
}
  • log-opts:限制单个日志文件最大 10MB、最多保留 3 个,防止磁盘被日志撑满
  • max-concurrent-downloads:限制同时下载层数为 2,降低内存和带宽占用

创建 docker-compose.yml

services:
  derper:
    image: ghcr.io/yangchuansheng/ip_derper
    container_name: derper
    restart: unless-stopped
    ports:
      - <DERP_TCP_PORT>:<DERP_TCP_PORT>  # 替换为 DERP 端口,如 13477
      - <STUN_UDP_PORT>:3478/udp         # 替换为 STUN 端口,如 13478
    environment:
      - DERP_ADDR=:<DERP_TCP_PORT>       # 替换为 DERP 端口,格式为 :<端口号>
      - DERP_VERIFY_CLIENTS=true          # 开启客户端验证,避免被公网滥用
    volumes:
      - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
  • STUN 容器内部端口固定为 3478/udp,左边是主机映射端口

启动并验证

docker compose up -d
docker logs derper
ss -tulnp | grep -E "<DERP_TCP_PORT>|<STUN_UDP_PORT>"  # 替换为实际端口号

安装 Tailscale 客户端

curl -fsSL https://tailscale.com/install.sh | sh
systemctl enable --now tailscaled
tailscale up

复制终端中的 https://login.tailscale.com/a/... 认证链接到浏览器完成登录,然后执行 tailscale status 确认状态。


3.3 Alpine

可选:使用国内镜像源

国内网络下 apk 拉取较慢时可切换阿里云镜像,此配置对后续所有 apk 操作生效:

# 备份原配置
cp /etc/apk/repositories /etc/apk/repositories.bak

# 使用阿里云镜像(版本号需与你的 Alpine 一致,通过 cat /etc/alpine-release 查看)
cat > /etc/apk/repositories << 'EOF'
https://mirrors.aliyun.com/alpine/v3.22/main
https://mirrors.aliyun.com/alpine/v3.22/community
EOF

apk update

安装 Docker 与 Compose

apk add docker docker-compose
rc-update add docker boot
service docker start
docker --version
docker-compose --version

提示:Alpine 下 Compose 通常是 V1(docker-compose),如需 V2 可通过二进制安装 docker-compose-plugin

可选:配置国内镜像加速

国内网络下拉取镜像较慢时可配置加速源,此配置写入后永久生效。

mkdir -p /etc/docker

cat > /etc/docker/daemon.json << 'EOF'
{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://dockerproxy.com",
    "https://docker.m.daocloud.io"
  ]
}
EOF

service docker restart

低配置 VPS 可在 daemon.json 中追加以下参数:

{
  "registry-mirrors": ["..."],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "max-concurrent-downloads": 2
}
  • log-opts:限制单个日志文件最大 10MB、最多保留 3 个,防止磁盘被日志撑满
  • max-concurrent-downloads:限制同时下载层数为 2,降低内存和带宽占用

创建 docker-compose.yml

services:
  derper:
    image: ghcr.io/yangchuansheng/ip_derper
    container_name: derper
    restart: unless-stopped
    ports:
      - <DERP_TCP_PORT>:<DERP_TCP_PORT>  # 替换为 DERP 端口,如 13477
      - <STUN_UDP_PORT>:3478/udp         # 替换为 STUN 端口,如 13478
    environment:
      - DERP_ADDR=:<DERP_TCP_PORT>       # 替换为 DERP 端口,格式为 :<端口号>
      - DERP_VERIFY_CLIENTS=true          # 开启客户端验证,避免被公网滥用
    volumes:
      - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
  • STUN 容器内部端口固定为 3478/udp,左边是主机映射端口

启动并验证

docker-compose up -d
docker logs derper
netstat -tulnp | grep -E "<DERP_TCP_PORT>|<STUN_UDP_PORT>"  # 替换为实际端口号

安装 Tailscale 客户端

Alpine 不支持官方一键脚本(curl -fsSL https://tailscale.com/install.sh | sh),必须通过 apk 安装。

确保 /etc/apk/repositories 包含 community 仓库(以 Alpine 3.19 为例):

http://dl-cdn.alpinelinux.org/alpine/v3.19/main
http://dl-cdn.alpinelinux.org/alpine/v3.19/community

若缺失可追加:

echo "http://dl-cdn.alpinelinux.org/alpine/v3.19/community" >> /etc/apk/repositories

安装并启动:

apk update
apk add tailscale
rc-update add tailscale default
rc-service tailscale start
tailscale up

复制终端中的 https://login.tailscale.com/a/... 认证链接到浏览器完成登录,然后执行 tailscale status 确认状态。

4. 非 Docker 部署

官方 Tailscale 包不包含 derper 二进制,需从源码编译。

4.1 Debian / Ubuntu

系统准备

apt update
apt upgrade -y
apt install -y wget openssl curl netcat-openbsd

创建目录结构

mkdir -p /usr/local/derp/{bin,certs}

编译 derper

安装 Go 环境:

apt install -y golang
go version

大陆地区切换下载源(Go 1.13 及以上):

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

编译(内存 >= 2GB):

go install tailscale.com/cmd/derper@latest
cp ~/go/bin/derper /usr/local/derp/bin/

低内存 VPS 编译可能报 OOM,可改用 §4.4 异机交叉编译,完成后回到本节「验证编译结果」继续。

验证编译结果

chmod +x /usr/local/derp/bin/derper

# 验证是否为静态二进制
ldd /usr/local/derp/bin/derper  # 应输出 "not a dynamic executable"

# 验证版本
/usr/local/derp/bin/derper --version

--version 输出类似 1.xx.x-ERR-BuildInfo 是正常的(go install 编译不含完整构建信息)。

如果遇到 Permission denied,可能是 /usr/local 被挂载为 noexec

# 检查挂载选项
mount | grep /usr/local

# 如果存在 noexec,复制到其他位置运行
cp /usr/local/derp/bin/derper /root/derper
chmod +x /root/derper
/root/derper --version

确认可执行后,将二进制放回 /usr/local/derp/bin/ 或调整挂载选项。

生成自签名证书

关键点:证书文件名要与 -hostname 对应,建议直接使用 <VPS_IP>.crt<VPS_IP>.key

cd /usr/local/derp/certs

# 将下方所有 <VPS_IP> 替换为你的服务器公网 IP
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 \
  -nodes -keyout <VPS_IP>.key -out <VPS_IP>.crt \
  -subj "/CN=<VPS_IP>" \
  -addext "subjectAltName=IP:<VPS_IP>"
  • -keyout <VPS_IP>.key:私钥输出文件,文件名需与 -hostname 一致
  • -out <VPS_IP>.crt:证书输出文件,文件名需与 -hostname 一致
  • -subj "/CN=<VPS_IP>":证书通用名称,设为服务器 IP
  • -addext "subjectAltName=IP:<VPS_IP>":SAN 扩展,必须包含 IP
  • -days 3650:有效期 10 年

创建 systemd 服务

cat > /etc/systemd/system/derper.service << 'EOF'
[Unit]
Description=Tailscale DERP Server
After=network.target
Wants=network.target

[Service]
User=root
Group=root
# 下方 <VPS_IP>、<DERP_TCP_PORT>、<STUN_UDP_PORT> 替换为实际值(参考 §1)
ExecStart=/usr/local/derp/bin/derper \
  -certmode=manual \
  -certdir=/usr/local/derp/certs \
  -hostname=<VPS_IP> \
  -a :<DERP_TCP_PORT> \
  -stun-port=<STUN_UDP_PORT> \
  -http-port=-1 \
  --verify-clients
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

参数要点:

  • -certmode=manual:手动证书模式
  • -http-port=-1:关闭 HTTP 端口
  • --verify-clients:开启客户端验证
  • Restart=on-failure + RestartSec=5:崩溃后自动重启

启动并验证

systemctl daemon-reload
systemctl enable derper
systemctl start derper
systemctl status derper

# 检查监听端口(替换为实际端口号)
ss -tulnp | grep -E "<DERP_TCP_PORT>|<STUN_UDP_PORT>"

# 本地 TCP 连通性(替换为 DERP 端口)
nc -zv 127.0.0.1 <DERP_TCP_PORT>

# 查看进程
ps aux | grep derper

# 启动失败可查看日志
journalctl -u derper --no-pager -n 30

预期输出:

tcp        0      0 :::<DERP_TCP_PORT>      :::*        LISTEN      1234/derper
udp        0      0 :::<STUN_UDP_PORT>      :::*                    1234/derper

如果缺少某一行,说明对应端口未监听成功,需检查服务日志。

安装 Tailscale 客户端

curl -fsSL https://tailscale.com/install.sh | sh
systemctl enable --now tailscaled
tailscale up

复制终端中的 https://login.tailscale.com/a/... 认证链接到浏览器完成登录,然后执行 tailscale status 确认状态。


4.2 RHEL / CentOS / Rocky / AlmaLinux

系统准备

dnf update -y
dnf install -y wget openssl curl nmap-ncat

创建目录结构

mkdir -p /usr/local/derp/{bin,certs}

编译 derper

安装 Go 环境:

dnf install -y golang
go version

大陆地区切换下载源(Go 1.13 及以上):

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

编译(内存 >= 2GB):

go install tailscale.com/cmd/derper@latest
cp ~/go/bin/derper /usr/local/derp/bin/

低内存 VPS 编译可能报 OOM,可改用 §4.4 异机交叉编译,完成后回到本节「验证编译结果」继续。

验证编译结果

chmod +x /usr/local/derp/bin/derper

# 验证是否为静态二进制
ldd /usr/local/derp/bin/derper  # 应输出 "not a dynamic executable"

# 验证版本
/usr/local/derp/bin/derper --version

--version 输出类似 1.xx.x-ERR-BuildInfo 是正常的(go install 编译不含完整构建信息)。

如果遇到 Permission denied,可能是 /usr/local 被挂载为 noexec

# 检查挂载选项
mount | grep /usr/local

# 如果存在 noexec,复制到其他位置运行
cp /usr/local/derp/bin/derper /root/derper
chmod +x /root/derper
/root/derper --version

确认可执行后,将二进制放回 /usr/local/derp/bin/ 或调整挂载选项。

生成自签名证书

关键点:证书文件名要与 -hostname 对应,建议直接使用 <VPS_IP>.crt<VPS_IP>.key

cd /usr/local/derp/certs

# 将下方所有 <VPS_IP> 替换为你的服务器公网 IP
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 \
  -nodes -keyout <VPS_IP>.key -out <VPS_IP>.crt \
  -subj "/CN=<VPS_IP>" \
  -addext "subjectAltName=IP:<VPS_IP>"
  • -keyout <VPS_IP>.key:私钥输出文件,文件名需与 -hostname 一致
  • -out <VPS_IP>.crt:证书输出文件,文件名需与 -hostname 一致
  • -subj "/CN=<VPS_IP>":证书通用名称,设为服务器 IP
  • -addext "subjectAltName=IP:<VPS_IP>":SAN 扩展,必须包含 IP
  • -days 3650:有效期 10 年

创建 systemd 服务

cat > /etc/systemd/system/derper.service << 'EOF'
[Unit]
Description=Tailscale DERP Server
After=network.target
Wants=network.target

[Service]
User=root
Group=root
# 下方 <VPS_IP>、<DERP_TCP_PORT>、<STUN_UDP_PORT> 替换为实际值(参考 §1)
ExecStart=/usr/local/derp/bin/derper \
  -certmode=manual \
  -certdir=/usr/local/derp/certs \
  -hostname=<VPS_IP> \
  -a :<DERP_TCP_PORT> \
  -stun-port=<STUN_UDP_PORT> \
  -http-port=-1 \
  --verify-clients
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

参数要点:

  • -certmode=manual:手动证书模式
  • -http-port=-1:关闭 HTTP 端口
  • --verify-clients:开启客户端验证
  • Restart=on-failure + RestartSec=5:崩溃后自动重启

启动并验证

systemctl daemon-reload
systemctl enable derper
systemctl start derper
systemctl status derper

# 检查监听端口(替换为实际端口号)
ss -tulnp | grep -E "<DERP_TCP_PORT>|<STUN_UDP_PORT>"

# 本地 TCP 连通性(替换为 DERP 端口)
nc -zv 127.0.0.1 <DERP_TCP_PORT>

# 查看进程
ps aux | grep derper

# 启动失败可查看日志
journalctl -u derper --no-pager -n 30

预期输出:

tcp        0      0 :::<DERP_TCP_PORT>      :::*        LISTEN      1234/derper
udp        0      0 :::<STUN_UDP_PORT>      :::*                    1234/derper

如果缺少某一行,说明对应端口未监听成功,需检查服务日志。

安装 Tailscale 客户端

curl -fsSL https://tailscale.com/install.sh | sh
systemctl enable --now tailscaled
tailscale up

复制终端中的 https://login.tailscale.com/a/... 认证链接到浏览器完成登录,然后执行 tailscale status 确认状态。


4.3 Alpine

可选:使用国内镜像源

国内网络下 apk 拉取较慢时可切换阿里云镜像,此配置对后续所有 apk 操作生效:

# 备份原配置
cp /etc/apk/repositories /etc/apk/repositories.bak

# 使用阿里云镜像(版本号需与你的 Alpine 一致,通过 cat /etc/alpine-release 查看)
cat > /etc/apk/repositories << 'EOF'
https://mirrors.aliyun.com/alpine/v3.22/main
https://mirrors.aliyun.com/alpine/v3.22/community
EOF

apk update

系统准备

apk update
apk upgrade
apk add wget openssl curl netcat-openbsd

创建目录结构

mkdir -p /usr/local/derp/bin /usr/local/derp/certs

编译 derper

安装 Go 环境:

apk add go
go version

大陆地区切换下载源(Go 1.13 及以上):

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

编译(内存 >= 2GB):

go install tailscale.com/cmd/derper@latest
cp ~/go/bin/derper /usr/local/derp/bin/

低内存 VPS 编译可能报 OOM,可改用 §4.4 异机交叉编译,完成后回到本节「验证编译结果」继续。

验证编译结果

chmod +x /usr/local/derp/bin/derper

# 验证是否为静态二进制
ldd /usr/local/derp/bin/derper  # 应输出 "not a dynamic executable"

# 验证版本
/usr/local/derp/bin/derper --version

--version 输出类似 1.xx.x-ERR-BuildInfo 是正常的(go install 编译不含完整构建信息)。

如果遇到 Permission denied,可能是 /usr/local 被挂载为 noexec

# 检查挂载选项
mount | grep /usr/local

# 如果存在 noexec,复制到其他位置运行
cp /usr/local/derp/bin/derper /root/derper
chmod +x /root/derper
/root/derper --version

确认可执行后,将二进制放回 /usr/local/derp/bin/ 或调整挂载选项。

生成自签名证书

关键点:证书文件名要与 -hostname 对应,建议直接使用 <VPS_IP>.crt<VPS_IP>.key

cd /usr/local/derp/certs

# 将下方所有 <VPS_IP> 替换为你的服务器公网 IP
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 \
  -nodes -keyout <VPS_IP>.key -out <VPS_IP>.crt \
  -subj "/CN=<VPS_IP>" \
  -addext "subjectAltName=IP:<VPS_IP>"
  • -keyout <VPS_IP>.key:私钥输出文件,文件名需与 -hostname 一致
  • -out <VPS_IP>.crt:证书输出文件,文件名需与 -hostname 一致
  • -subj "/CN=<VPS_IP>":证书通用名称,设为服务器 IP
  • -addext "subjectAltName=IP:<VPS_IP>":SAN 扩展,必须包含 IP
  • -days 3650:有效期 10 年

创建 OpenRC 服务

cat > /etc/init.d/derper << 'EOF'
#!/sbin/openrc-run

description="Tailscale DERP Server"

command="/usr/local/derp/bin/derper"
# 下方 <VPS_IP>、<DERP_TCP_PORT>、<STUN_UDP_PORT> 替换为实际值(参考 §1)
command_args="-certmode=manual -certdir=/usr/local/derp/certs -hostname=<VPS_IP> -a :<DERP_TCP_PORT> -stun-port=<STUN_UDP_PORT> -http-port=-1 --verify-clients"
command_user="root:root"
supervisor=supervise-daemon
respawn_delay=5
respawn_max=0

depend() {
    need net
    after firewall
}
EOF

参数要点:

  • -certmode=manual:手动证书模式
  • -http-port=-1:关闭 HTTP 端口
  • --verify-clients:开启客户端验证
  • supervisor=supervise-daemon + respawn_delay=5:崩溃后自动重启(等效 systemd 的 Restart=on-failure

启动并验证

chmod +x /etc/init.d/derper
rc-update add derper default
rc-service derper start
rc-service derper status

# 检查监听端口(替换为实际端口号)
netstat -tulnp | grep -E "<DERP_TCP_PORT>|<STUN_UDP_PORT>"

# 本地 TCP 连通性(替换为 DERP 端口)
nc -zv 127.0.0.1 <DERP_TCP_PORT>

# 查看进程
ps aux | grep derper

# 启动失败可看内核日志
dmesg | tail -20

预期输出:

tcp        0      0 :::<DERP_TCP_PORT>      :::*        LISTEN      1234/derper
udp        0      0 :::<STUN_UDP_PORT>      :::*                    1234/derper

如果缺少某一行,说明对应端口未监听成功,需检查服务日志。

安装 Tailscale 客户端

Alpine 不支持官方一键脚本(curl -fsSL https://tailscale.com/install.sh | sh),必须通过 apk 安装。

确保 /etc/apk/repositories 包含 community 仓库(以 Alpine 3.19 为例):

http://dl-cdn.alpinelinux.org/alpine/v3.19/main
http://dl-cdn.alpinelinux.org/alpine/v3.19/community

若缺失可追加:

echo "http://dl-cdn.alpinelinux.org/alpine/v3.19/community" >> /etc/apk/repositories

安装并启动:

apk update
apk add tailscale
rc-update add tailscale default
rc-service tailscale start
tailscale up

复制终端中的 https://login.tailscale.com/a/... 认证链接到浏览器完成登录,然后执行 tailscale status 确认状态。


4.4 附:异机交叉编译(低内存 VPS)

VPS 内存不足 2GB 编译会 OOM,可在其他机器编译后上传。

# 1) 准备 Go 环境(版本建议 >= 1.21)
go version

# 2) 大陆地区切换下载源
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

# 3) 设定目标平台(示例:Linux AMD64)
export GOOS=linux
export GOARCH=amd64    # ARM64 改为 arm64
export CGO_ENABLED=0

# 4) 构建 derper
go install tailscale.com/cmd/derper@latest
ls ~/go/bin/derper

# 5) 在 VPS 上创建目录(替换 <VPS_IP> 为服务器公网 IP)
ssh root@<VPS_IP> "mkdir -p /usr/local/derp/bin /usr/local/derp/certs"

# 6) 上传到 VPS
scp ~/go/bin/derper root@<VPS_IP>:/usr/local/derp/bin/

# 7) 在 VPS 上验证
ssh root@<VPS_IP>
chmod +x /usr/local/derp/bin/derper
ldd /usr/local/derp/bin/derper    # 应输出 "not a dynamic executable"
/usr/local/derp/bin/derper --version

编译参数说明:

  • CGO_ENABLED=0:生成纯静态二进制,降低运行环境依赖
  • GOOS / GOARCH:目标操作系统和架构

上传并验证通过后,回到对应操作系统章节(§4.1 / §4.2 / §4.3),从「验证编译结果」步骤继续完成证书、服务配置与 Tailscale 安装。

5. 配置 ACL(derpMap)

进入 Tailscale 管理后台 Access controls 的 JSON 编辑器,把下列 derpMap 合并到现有 ACL(不要覆盖其他配置项)。

将以下 JSON 中的 <REGION_ID><REGION_CODE><VPS_IP><DERP_TCP_PORT><STUN_UDP_PORT> 替换为你的实际值(参考 §1)。

{
  "derpMap": {
    "OmitDefaultRegions": false,        // 保留官方 DERP 作为兜底
    "Regions": {
      "<REGION_ID>": {
        "RegionID": <REGION_ID>,         // 自定义区域 ID,建议 900 及以上
        "RegionCode": "<REGION_CODE>",   // 自定义区域代码
        "RegionName": "Custom DERP",
        "Nodes": [
          {
            "Name": "myderper",
            "RegionID": <REGION_ID>,
            "HostName": "<VPS_IP>",      // 必须与证书和 -hostname 一致
            "DERPPort": <DERP_TCP_PORT>, // 必须与服务监听端口一致
            "STUNPort": <STUN_UDP_PORT>, // 必须与 STUN 监听端口一致
            "CanPort80": false,
            "InsecureForTests": true     // IP + 自签证书场景必须开启
          }
        ]
      }
    }
  }
}

Tailscale ACL 编辑器支持 HuJSON 格式,// 注释可直接保留,无需删除。

常见坑:

  • JSON 尾逗号导致保存失败
  • ACL 端口与服务监听端口不一致
  • HostName 与证书 SAN 不一致

6. 客户端重连与配置下发

ACL 保存后,建议客户端重连一次,确保拉取新配置:

# Debian / Ubuntu / RHEL / CentOS(systemd)
systemctl restart tailscaled

# Alpine(OpenRC)
rc-service tailscale restart

# 或通用方式(所有系统)
tailscale down
tailscale up

建议等待 1-2 分钟后再跑连通性测试。

6.1 启用 Peer Relay 与 Exit Node(可选)

如果你希望 DERP 节点同时作为 Peer Relay 和 Exit Node 使用:

启用 Peer Relay

Peer Relay 目前处于 Beta 阶段,需要 Tailscale 1.86+。它允许 tailnet 内的设备充当高吞吐中继,直连失败时优先走 Peer Relay,再回退到 DERP。适用于严格 NAT 环境下的大文件传输、高清流媒体等场景。

第一步:在中继设备上开启 Peer Relay

# 确认版本 >= 1.86
tailscale version

# 启用 Peer Relay,指定 UDP 端口
tailscale set --relay-server-port=40000

确保防火墙和云安全组放行该 UDP 端口(如 40000/udp),否则其他设备无法通过 Peer Relay 连接。

第二步:在 ACL 中添加 grant 策略

仅开启端口不够,还必须在 Tailscale 管理后台的 Access controls 中添加 Peer Relay 的 grants 策略。

先查询 DERP 服务器的 Tailscale IP:

tailscale status

输出中第一列 100.x.x.x 即为 Tailscale IP。

在现有 ACL 的 grants 数组中追加 Peer Relay 条目(grants 支持多条共存)。以下是包含基础网络访问和 Peer Relay 的完整示例,将 <RELAY_HOSTNAME> 替换为 DERP 服务器的 Tailscale IP:

{
  "grants": [
    {
      "src": ["*"],
      "dst": ["*"],
      "ip": ["*"]                        // 基础网络访问,允许所有设备互通
    },
    {
      "src": ["*"],
      "dst": ["<RELAY_HOSTNAME>"],       // 替换为 DERP 服务器的 Tailscale IP
      "app": {
        "tailscale.com/cap/relay": []    // relay 能力,无需额外参数
      }
    }
  ],

  "acls": [
    {
      "action": "accept",
      "src": ["*"],
      "dst": ["*:*"]                     // 允许所有流量通过
    }
  ]
}

注意:Tailscale ACL 默认拒绝所有流量。如果你的 ACL 中没有 acls 规则或网络访问 grant(第一条 "ip": ["*"]),设备之间将无法通信,Peer Relay 也不会生效。上方示例中两者都保留以确保正常工作。

如果你已有自己的 aclsgrants 配置,只需将第二条 Peer Relay grant 追加到现有 grants 数组末尾即可。

  • dst必须替换 <RELAY_HOSTNAME> 为 DERP 服务器的 Tailscale IP
  • tailscale.com/cap/relay:必须的 relay 能力声明

多台 Peer Relay 场景:如果你有多台 Peer Relay 或想精细控制,可改用标签。详见 Tailscale Peer Relays 文档

第三步:验证

# 生成流量后查看状态
tailscale status | grep peer-relay

# 或用 ping 测试
tailscale ping <对端设备>

当连接走 Peer Relay 时,tailscale status 会显示 peer-relay 而非 directrelay

禁用 Peer Relay

tailscale set --relay-server-port=""

启用 Exit Node

Linux 必须先开启 IP 转发才能作为 Exit Node:

# 如果系统存在 /etc/sysctl.d/ 目录(推荐)
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf

# 否则使用 /etc/sysctl.conf
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p /etc/sysctl.conf

如果使用 firewalld,需额外允许 masquerade:

firewall-cmd --permanent --add-masquerade

开启 IP 转发后,请确认防火墙默认拒绝转发流量(ufwfirewalld 默认如此),避免意外路由不相关流量。

广播 Exit Node 并启用路由接受:

sudo tailscale set --advertise-exit-node
sudo tailscale up --accept-routes

最后到 Tailscale 管理后台批准 Exit Node:

  1. 打开 Machines 页面,找到该设备
  2. 点击设备右侧 ... 菜单 → Edit route settings
  3. 启用 Use as exit node

如果该设备的用户已在 ACL autoApprovers 中配置了 Exit Node 权限,则会自动批准,无需手动操作。

6.2 网络性能优化(可选)

启用 UDP GRO forwarding 和关闭 GRO list 可提升 Tailscale 的网络吞吐:

# 启用 UDP GRO forwarding
ethtool -K eth0 rx-udp-gro-forwarding on

# 启用 UDP segmentation offload
ethtool -K eth0 rx-gro-list off

# 检查设置
ethtool -k eth0 | grep gro

如果提示 ethtool: command not found

# Alpine
apk add ethtool

# Debian / Ubuntu
apt install -y ethtool

# RHEL / CentOS / Rocky
dnf install -y ethtool

7. 测试与验收

7.1 快速测试命令

# 网络能力检查(UDP / DERP)
tailscale netcheck

# 设备与对等节点状态
tailscale status

# 结构化状态(便于排障与留档)
tailscale status --json

7.2 tailscale netcheck 关注点

  • UDP: true:UDP 通信正常
  • Nearest DERP:应接近你设置的自定义区域
  • DERP latency:自建节点延迟越低越好

7.3 tailscale status 关注点

  • 本机是否 active
  • 对等节点是否可见
  • 连接路径是否出现 relay "<REGION_CODE>"direct ...

7.4 示例输出解读

不同版本输出可能略有差异,重点看判读思路。

示例 1:tailscale netcheck

Report:
        * UDP: true
        * IPv4: yes, 203.0.113.24:41641
        * IPv6: no, but OS has support
        * MappingVariesByDestIP: false
        * HairPinning: false
        * Nearest DERP: tyxy
        * DERP latency:
                - tyxy: 18.2ms
                - tok: 62.4ms

解读要点:

  • UDP: true:STUN 打洞能力正常
  • Nearest DERP: tyxy:客户端已命中自定义区域
  • MappingVariesByDestIP: false:通常表示 NAT 映射更稳定

示例 2:tailscale status

100.64.0.2   vps-derp   linux    active; direct 198.51.100.10:41641, tx 12 rx 20
100.64.0.8   laptop     windows  active; relay "tyxy", tx 3 rx 6

解读要点:

  • active; direct ...:当前直连
  • active; relay "tyxy":当前走 DERP 中继,区域为 tyxy
  • 如果长期全部 relay,继续排查 NAT/防火墙/端口策略

8. 常见问题与排查

8.1 编译时报 OOM

症状:fatal error: runtime: out of memorysignal: killed。 处理:使用 §4.4 异机交叉编译、或临时加 swap。

8.2 Permission denied 执行 derper

症状:chmod +x 后仍报 Permission denied。 原因:/usr/local 可能被挂载为 noexec

mount | grep /usr/local

处理:复制到其他位置运行,或重新挂载去掉 noexec

cp /usr/local/derp/bin/derper /root/derper
chmod +x /root/derper
/root/derper --version

8.3 端口冲突(address already in use

# systemd 系统(替换为实际端口号)
ss -tulnp | grep -E "<DERP_TCP_PORT>|<STUN_UDP_PORT>"

# Alpine(替换为实际端口号)
netstat -tulnp | grep -E "<DERP_TCP_PORT>|<STUN_UDP_PORT>"

处理:停止冲突进程或更换端口,并同步修改服务参数和 ACL。

8.4 看不到自定义 DERP(证书/hostname 问题)

ls -la /usr/local/derp/certs/
# 替换 <VPS_IP> 为实际 IP
openssl x509 -in /usr/local/derp/certs/<VPS_IP>.crt -text -noout | grep -E "Subject:|IP Address"

# 检查服务配置中的 hostname
grep hostname /etc/systemd/system/derper.service  # systemd 系统
grep hostname /etc/init.d/derper                   # Alpine (OpenRC)

处理:确认证书文件名、SAN IP、-hostname 三者一致。

8.5 本地通、外网不通(防火墙问题)

# 本地测试(替换为 DERP 端口)
nc -zv 127.0.0.1 <DERP_TCP_PORT>

# 从外部机器测试(替换为实际 IP 和端口)
nc -zv <VPS_IP> <DERP_TCP_PORT>

处理:重点检查云安全组与系统防火墙规则。

8.6 ACL 配置未生效

处理顺序:

  1. 检查 JSON 语法(尤其尾逗号)
  2. 等待 1-2 分钟同步
  3. 客户端重连:tailscale down && tailscale up
  4. 再执行 tailscale netcheck

8.7 服务脚本问题

systemd(Debian/Ubuntu/RHEL/CentOS): 症状:Failed to start derper.servicestatus=203/EXEC。 处理:检查 ExecStart 路径是否正确、二进制是否有执行权限,修改后执行 systemctl daemon-reload

OpenRC(Alpine): 症状:syntax error: unterminated quoted string。 处理:删除后用 cat << 'EOF' 方式重建,避免手工改引号。

9. 总结

关键要点:

  • Docker 上手快,非 Docker 更接近系统级运维,按需选择
  • IP 场景下,自签证书 + InsecureForTests: true 通常是成套配置
  • HostName、证书 SAN、监听端口、ACL 端口必须全链路一致
  • 配置完成后务必重连客户端,并用 netcheck/status 做验收

至此,你可以在 Debian/Ubuntu、RHEL/CentOS、Alpine 等主流发行版上,按本文的独立指南完成 DERP 的部署、验证与排障。