Tailscale 是一个基于 WireGuard 的,易于使用的组网工具,Tailscale DERP 服务器是帮助组网设备之间进行 NAT 打洞,或者进行流量转发的,Tailscale 官方在全球提供了很多的 DERP 服务器,但在部分地区,使用这些 DERP 服务器可能会导致较差的组网体验,或者如果存在合规需求,就不得不放弃使用 Tailscale 官方的 DERP 服务器,就得自己部署 DERP 服务器。
由于 Tailscale 的官方教程讲的不是很明白,因此在这里把搭建 DERP 服务器的经验分享给大伙。
需要的东西
首先,你需要有一台能联网的服务器,Windows 或 Linux 系统都可以,不过本文会以 Linux 服务器为例。
其次,你需要有一个域名,这个域名要能指向你的服务器(也就是说,即使是 Azure 提供的 DNS 名称也是可以的),如果你的服务器位于中国大陆内,按照有关要求,你需要先将域名备案,备案成功后才能搭建 DERP 服务器。
最后,你需要动起你的脑子,本教程专注于讲接如何部署 DERP 服务器,但对于一些基本操作则不会讲太细,请好好利用搜索引擎!
开始部署
这里将默认你已经做好了以下准备:
- 已将域名解析至服务器;
- 已按地区政策要求取得有关资质(如果有);
- 你可以使用 Root 账户进行操作(如果你对 Linux 很了解,也可以不使用 Root 账户进行操作,能 sudo 也是可以的,但教程将以 Root 账户身份进行);
配置防火墙
首先,如果服务器启用了防火墙,那么请放行以下端口:
- 入站放行
- HTTP 端口(80/tcp);
- HTTPS 端口(443/tcp);
- STUN 端口(3478/udp);
- Tailscale 通讯端口(41641/udp);(如果启用客户端验证,见下文)
- 出站放行(一般服务器出站默认全放行)
- HTTPS 端口(443/tcp);(用于与协调服务器进行通讯)
注意,部分云服务商提供了平台防火墙功能(可能被称为“安全列表”),如果有,请同时放行以上端口。
如果无法使用上述端口,可以根据情况进行调整,但必须提供两个 TCP 入站端口和一个 UDP 入站端口(如果启用客户端验证,则需要两个 UDP 端口)
安装 Golang 环境
首先安装 Golang 开发环境,按照 Golang 官方文档的安装指引,将最新版的 Golang 环境安装到系统中,安装完毕后执行 go version
检查 Golang 的版本号。
如果显示了 Golang 的版本号,就算安装成功,如果提示未找到命令,请检查一下是否未配置 PATH 环境变量,如果你是按照 Golang 官方教程进行的,请重新执行这个命令来配置 PATH 环境变量:
export PATH=$PATH:/usr/local/go/bin
如果你所在地区的网络不好连接 GoProxy,那么你可以通过 go env -w
来修改 Golang 要使用的 GoProxy 地址,这里以中国地区为例:
go env -w GOPROXY=https://goproxy.cn,direct
Golang 环境就绪后就可以开始安装 DERP 服务端了。
安装 DERP 服务端
使用命令将 DERP 服务端安装到服务器:
go install tailscale.com/cmd/derper@main
执行命令后,Golang 会将 DERP 服务端安装在 ~/go/bin
目录中,因此为了方便后面的操作,我们需要再为 PATH 环境变量添加一个路径:
export PATH=$PATH:~/go/bin
完成后,执行 derper -h
命令,看看 DERP 服务端是否安装成功:
如果成功显示帮助信息,那么 DERP 服务端就安装完成了。
准备 HTTPS 证书
如果你的域名需要使用 Web 服务器(占用了 80、443 端口),或者无法使用标准 HTTP 端口(80 端口),则无法直接通过 DERP 服务端内置的 ACME 功能自动向 Let’s encrypt 申请证书(经过测试,我也用不了 DERP 内置的 ACME 功能来申请证书,所以还是自己手动申请吧)。
所以我们需要使用第三方 ACME 证书申请工具来签发 HTTPS 证书,这里以 acme.sh 工具为例。
首先安装 acme.sh 工具:
# 邮箱请换成自己的联络邮箱,用于接收证书到期提醒。
# 如果不使用联络邮箱,将导致无法申请证书。
curl https://get.acme.sh | sh -s [email protected]
安装完成后是无法直接使用 acme.sh
来执行的,因为 acme.sh 只在 .bashrc 设置了环境变量,但没有给当前 Shell 会话设置环境变量,因此需要重新连接 SSH 来让环境变量生效。
acme.sh 默认使用 ZeroSSL 作为 CA,如果想使用 Let’s encrypt 的证书,需要执行这个命令:
acme.sh --set-default-ca --server letsencrypt
使用 DNS 验证方法
如果持有域名的 DNS 控制权,那么强烈推荐使用 DNS 验证方法,该方法不仅支持在无法使用标准 HTTP 端口的情况下申请证书,也支持在已有 Web 服务器,无法使用 80 端口的时候申请证书。
按照 acme.sh 官方 Wiki,根据自己的 DNS 提供商选择对应的方法,这里以 Cloudflare 为例。
首先,前往 Cloudflare API 密钥(点击前往),点击“创建令牌”,选择“编辑区域 DNS”模板,权限选择“区域”、“DNS”和“编辑”,区域资源选择“包括”、“特定区域”和要使用的域名,TTL 可以设置,也可以不设置,编辑完成后点击“继续以显示摘要”,如下图:
保存后记住 API 令牌,在 Cloudflare 总览中点击域名,查看页面右侧的 API 信息,获得账户 ID 和区域 ID 。
然后把得到的三个东西替换进去,替换后执行:
export CF_Token="<API令牌>"
export CF_Account_ID="<账户ID>"
export CF_Zone_ID="<域名的区域ID>"
执行后使用 acme.sh 以 DNS 方式申请证书:
./acme.sh --issue --dns dns_cf -d xxxxxxx.com
使用 Standalone 模式
Standalone 是 acme.sh 提供的,无需 Web 服务器的验证方式,如果服务器不部署任何 Web 服务器,可以使用标准 HTTP 端口,那么就可以用这个方法快速申请 HTTPS 证书。
首先安装一个依赖工具 socat
:
# Debian 分支的系统(Debian、Ubuntu)
apt update && apt install socat
# RHEL 分支的系统(RHEL、Fedora、CentOS)
dnf install socat
# 如果没有 dnf,系统是比较旧的 RHEL 分支系统,就用下面这个
yum install socat
安装成功后,执行命令申请证书:
acme.sh --issue -d <域名> --standalone
安装证书
申请证书成功后,创建一个新的目录用于存储 DERP 服务端的 HTTPS 证书,并通过 acme.sh 将证书安装到目录(这里以 ~/derper/ssl/
目录为例):
mkdir -p ~/derper/ssl
acme.sh --install-cert -d <域名> \
--fullchain-file ~/derper/ssl/<域名>.crt \
--key-file ~/derper/ssl/<域名>.key
安装成功后即可。
配置并启动 DERP 服务端
由于 Tailscale 的 DERP 服务端没有配置文件这种东西,所以我们就得根据情况使用合适的参数来启动它。
(可能这里会有人问题,为什么说 DERP 服务端没有配置文件?帮助信息不是说了用 -c <path>
来指定配置文件了吗?问得好,因为这个配置文件只是用来存储 DERP 密钥的,并不存储运行配置)
使用标准 HTTPS 端口和 STUN 端口
如果服务器不运行 Web 服务器,并且可以直接使用标准 HTTPS 端口,那么可以使用这个命令来启动 DERP 服务端:
derper -hostname <域名> -certmode manual -certdir ~/derper/ssl/ -http-port -1
由于可以使用标准端口,且我们选择手动申请证书,因此只需要指定 -certmode
为 manual
,且指定 -http-port
为 -1
关闭 HTTP 即可。
使用非标准 HTTPS 端口或非标准 STUN 端口
如果无法使用标准 HTTPS 端口,或无法使用 3478 作为 STUN 端口的话,可以使用 -a :<HTTPS端口>
和 -stun-port <STUN端口>
参数:
derper -hostname <域名> -certmode manual -certdir ~/derper/ssl -http-port -1 -a :<HTTPS端口> -stun-port <STUN端口>
如果希望指定 DERP 服务端监听指定的网卡,只需要在 -a
参数值的冒号前指定网卡地址即可:
derper -hostname <域名> -certmode manual -certdir ~/derper/ssl -http-port -1 -a <网卡地址>:<HTTPS端口>
如果是 IPv6 地址的话,需要加上方括号,比如像这样:-a [f800::01]:8443
设置好参数后就可以启动服务端了,执行命令后,DERP 服务端将输出 HTTPS 端口和 STUN 端口,代表 DERP 服务端启动成功。
使用工具让 DERP 在后台运行
由于我们目前使用 SSH 会话运行 DERP 服务端,当 SSH 断开后将无法继续运行 DERP 服务端,因此我们需要使用一些工具来帮我们维持 DERP 服务端的运行,这里以 screen 为例子。
首先,安装 screen 工具:
# Debian 分支的系统(Debian、Ubuntu)
apt update && apt install screen
# RHEL 分支的系统(RHEL、Fedora、CentOS)
yum install epel-release
# 先执行完上面的命令,再执行下面的命令
yum install socat
安装完成后,使用这个命令启动 DERP 服务端:
screen -S derp -s <启动 DERP 服务端的命令>
比如说这样:
screen -S derp -s derper -hostname <域名> -certmode manual -certdir ~/derper/ssl/ -http-port -1
执行后,screen 将创建一个虚拟终端,并在虚拟终端中运行 DERP 服务端,依次按下 Ctrl + A
和 D
后即可退出 DERP 服务端的运行终端,使用 screen -r derp
就能重连运行 DERP 服务端的终端。
启动 DERP 服务端后,还不能开始使用它,因为组网仍不知道 DERP 服务器的存在,因此我们要去 Tailscale 管理面板注册 DERP 服务器。
注册 DERP 服务器
首先登录 Tailscale 管理面板,切换到“Access Controls”(ACL)配置页面,可以看到 JSON 格式的 ACL 配置在编辑器中,我们需要给 ACL 添加一个 derpMap
字段(有关字段的定义可以在这里查看):
{
...,
"derpMap": {
// Regions 记录了有哪些 DERP 区域, Tailscale 是按区域划分 DERP 服务器组的
"Regions": {
// 900 是这个区域的区域 ID, 只能填数字, 且范围只能在 900-999 以内(包括头尾)。
"900": {
// 与区域 ID 相同.
"RegionID": 900,
// 区域的代号名, 纯英文.
"RegionCode": "myself-derp",
// 区域的名字, 不建议太长.
"RegionName": "Myself Derp",
// 区域的节点列表.
"Nodes": [
{
// 节点名称, 会显示在日志里, 但不会显示在 netcheck 中.
"Name": "my-derper",
// 与所在区域 ID 相同.
"RegionID": 900,
// DERP 服务器域名.
"HostName": "<域名>",
// 如果使用了非标准 HTTPS 端口, 那么可以将 HTTPS 端口设置在此.
"DERPPort": 443,
// 如果 STUN 指定了非 3478 端口, 那么可以将 STUN 端口设置在此.
"STUNPort": 3578,
// 下面的字段一般不用设置, 属于高级操作.
// 如果域名没有解析到服务器, 那么可以在这里指定.
// "IPv4": "xxx.xxx.xxx.xxx",
// 如果服务器有 IPv6, 但没有设置域名 DNS 记录的话, 可以在这里指定.
// "IPv6": "xxx::xxx",
// 如果服务器使用的证书与域名不符, 可以在这里指定
// 用于 HTTPS 握手的域名地址.(SNI 域名地址)
// "CertName": "xxx.com"
},
// ...
],
},
},
},
...
}
如果 DERP 服务器只有一两个的话,可以只修改 Nodes
里的对象,修改完成后将整个 derpMap
字段对追加到 ACL 配置对象的末尾,保存即可,追加后效果如下:
{
// Declare static groups of users beyond those in the identity service.
"groups": {},
// Declare convenient hostname aliases to use in place of IP addresses.
"hosts": {
// "example-host-1": "100.100.100.100",
},
"tagOwners": {},
// Access control lists.
"acls": [
// Match absolutely everything.
// Comment this section out if you want to define specific restrictions.
{"action": "accept", "users": ["*"], "ports": ["*:*"]},
],
"derpMap": {
"Regions": {
"900": {
"RegionID": 900,
"RegionCode": "myself-derp",
"RegionName": "Myself Derp",
"Nodes": [
{
"Name": "my-derper",
"RegionID": 900,
"HostName": "<域名>",
"DERPPort": 8443,
"STUNPort": 3578,
}
],
},
},
}
}
保存 ACL 后,尝试在任意一个组网设备上执行 tailscale netcheck
,如果成功显示区域和延迟,则代表配置成功。
如果没有找到添加的 DERP 区域,则有可能是 ACL 配置尚未分发到节点设备,请稍等片刻后重新执行命令;如果出现了 DERP 区域,但未显示延迟,请检查 DERP 服务器是否正常运行,防火墙是否开放。
启用客户端验证
DERP 服务器默认是公开的,也就是说,只要有人知道你 DERP 服务器的域名、IP 地址和端口,那个人就能用你的 DERP 服务器帮他中转流量!
要想阻止这个情况,我们就得配置 DERP 服务端,启用客户端认证。
安装 Tailscale 客户端
DERP 服务端需要通过 Tailscale 得知有哪些节点可以连接,因此我们需要先在服务器上安装 Tailscale 客户端。执行这个命令:
curl -fsSL https://tailscale.com/install.sh | sh
等待安装完成后,使用 tailscale up
命令登录 Tailscale 客户端,将第一个链接复制到浏览器,打开并登录。
登录成功后,如果启用了管理员授权,则需要到 Tailscale 管理面板 批准登录。
添加 DERP 服务端参数
登录成功后,停止 DERP 服务端,在 DERP 服务端的参数中添加 -verify-clients
参数,比如我原本的启动命令是:
derper -hostname <域名> -certmode manual -certdir ~/derper/ssl/ -http-port -1
那么添加参数后就是这样的:
derper -hostname <域名> -certmode manual -certdir ~/derper/ssl/ -http-port -1 -verify-clients
添加参数后启动 DERP 服务端,然后在其他节点执行 tailscale netcheck
看看是否能正常连接 DERP 服务器,如果能显示延迟,则代表设置成功。
如果需要查看有哪些节点可以连接 DERP 服务器,只需要在 DERP 服务器上执行 tailscale status 即可,执行命令后显示的所有节点都可以通过 DERP 服务器中转流量。
使用 Systemd 管理 DERP 服务端进程
目前我们使用 screen 来将 DERP 服务端放在后台运行,但如果系统需要重启的话,我们还得要重新连接 SSH,然后重新使用 screen 来运行,这样比较麻烦。
我们可以利用 Systemd,帮助我们让 DERP 服务端能够开机自启!
首先我们需要准备一个 Service 文件,内容是这样的:
[Unit]
Description=Tailscale Relay Server (Derper)
Wants=network-online.target
# 如果不启用客户端验证,可以不要这两行
Requires=tailscaled.service
After=tailscaled.service
[Service]
# Restart=on-failure
Type=simple
# 这行留空, 用于规避某个神奇的问题.
ExecStart=
# 将上面准备好的启动命令, 把相对路径换成绝对路径后替换到下面
ExecStart=<启动 DERP 的命令>
Environment=
注意,命令不能直接填进去,因为其中的路径是相对路径,因此你需要将启动 DERP 服务端的命令里的每个相对路径转换成绝对路径,然后替换进 service 文件内容中即可。
准备好 service 文件内容后,执行以下命令:
systemctl edit -f tailscale-derper
执行命令后打开文本编辑框,将 service 内容粘贴进去后保存并退出,将原来的 DERP 服务端进程关闭后,使用以下命令设置开机自启并启动 DERP 服务端,检查 DERP 服务端的运行状况:
systemctl enable --now tailscale-derper
systemctl status tailscale-derper
如果显示 Active: active (running)
则代表 DERP 服务端启动成功,至此 Service 配置完成!
参考资料
- What firewall ports should I open to use Tailscale? · Tailscale
- Custom DERP Servers · Tailscale
- How to install TLS certificate for derp server? – Tailscale Forum
文章写的比较晚,如果有错误的位置可以通过评论或邮件提醒我,感谢你的阅读~
——LamGC
2023 年的第一篇文章!ヾ(≧∇≦*)ゝ