不管是文件传输、远程开发、NAS观影,还是和朋友组网畅玩游戏;想让不同NAT下的不同设备进行互联,就需要一个虚拟组网技术。而Tailscale的免费账户支持连接 100 台设备,而且客户端全平台设备支持,简单易操作,作为一名有追求的技术宅,有什么理由不去用它呢。
由于 Tailscale 官方的服务器在海外,众所周知的原因,国内经常出现高延迟或者连接不上的情况。为了提升网络连接的质量和响应速度,好在官方允许用户自建 DERP 服务充当中继来解决这个问题。通过这种方式,在本地网络中创建一个高效的数据传输节点,能显著减少延迟,提高整体的互联体验。
这里我提供了2种方式自建DERP服务,分别是:域名方式部署 和公网IP方式部署 ;你可以根据自己的条件,使用两种方式的任意一种。本文采用的是常规安装go环境,启动系统服务的方式部署。如果有Docker部署需求的同学,在研究本文的安装原理之后,也可以自己写一个Dockerfile进行容器部署。
废话不多说,直接开始吧。
另外特别声明一下,以下大部分操作都是基于ssh链接云服务器进行操作
准备工作
- 一台云服务器,系统选择
ubuntu
- 安装
Golang
环境(最好最新版本的 go,旧版本会极大概率导致 derp 安装或编译失败) - 一个域名并申请绑定了ssl 证书(可选,域名方式部署需要这个)
下载安装 derper
首先,检查一下go的环境,这里不展开细说,可自取底部拓展教程,或参考其他博文和文章。
使用go执行以下命令安装 derper
:
shell
go install tailscale.com/cmd/derper@main
没有报错,就表示安装成功
部署方式一:使用域名
首先,新建存放证书的文件夹(也可以自定义,自定义时,后面启动脚本端口也要同步修改):
shell
sudo mkdir /usr/local/cert
将下载的ssl 证书上传到存放证书的文件夹,只需要上传.key
和.crt
文件
注意:
- 上述创建的证书文件夹,只有 root 账号才有权限操作上传证书
- 如果没有
.crt
文件,可将.pem 后缀改为.crt- 证书的名称要和你的域名保持一致
接着,使用 vim 创建脚本文件
启动脚本:
shell
sudo vim /usr/local/gopath/bin/runderper
进入编辑模式,粘贴入以下代码:
text
#!/bin/sh
cd /usr/local/gopath/bin
nohup ./derper -hostname test.example.com -c=derper.conf -a :33445 -http-port -1 -certdir /usr/local/cert -certmode manual -verify-clients -stun > console.log 2>&1 &
echo $! > app.pid
说明:
- 你需要将代码中的
test.example.com
替换成自己的域名- 33445端口是我这边定义的端口,你可以根据自己的需要改成自己想要的端口号
- 参数
-verify-clients
用来防止中继服务被滥用的(被白嫖);如果你有这方面需求,可去掉这个参数
停止脚本:
shell
sudo vim /usr/local/gopath/bin/stopderper.sh
进入编辑模式,粘贴入以下代码,保存:
text
#!/bin/sh
kill `cat app.pid`
rm -rf app.pid
输入命令,为上面创建的2个脚本赋权
shell
chmod +x /usr/local/gopath/bin/runderper
chmod +x /usr/local/gopath/bin/stopderper.sh
创建 derper
服务
shell
sudo vim /etc/systemd/system/derper.service
进入编辑模式,粘贴入以下代码并保存:
text
Description=derper服务
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/gopath/bin/runderper
ExecStop=/usr/local/gopath/bin/stopderper.sh
[Install]
WantedBy=multi-user.target
部署方式二:使用公网IP
使用公网IP的方式最重要的步骤是:对derper
文件夹重新编译和自签证书
如果对具体原理感兴趣可以参考: Tailscale官方的文档
首先,我们需要进入到,下载安装的derper安装包的/cmd/derper
目录里面。如果不知道安装命令把derper下载安装到哪里了,你可以使用find
命令查找到路径,再进行cd
操作
shell
find / -type d -name derper
接着,需要打开cert.go
文件,找到下面三行代码,将与域名验证相关的内容删除或注释:
然后,在/...中间省略.../cmd/derper/ 目录下输入命令,将derper重新编译,并输出到指定目录:/etc/derp/derper
shell
go build -o /etc/derp/derper
我们回到根目录,检查是否编译并输出成功:
bash
cd /
ls /etc/derp
如果控制台输出有文件内容,则表示操作成功
紧接着,自签一个假的域名,用来启动derper
服务:
shell
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout /etc/derp/derp.myself.com.key -out /etc/derp/derp.myself.com.crt -subj "/CN=derp.myself.com" -addext "subjectAltName=DNS:derp.myself.com"
注意哦,derp.myself.com
是瞎编的哦(。◕‿◕。) ,只是用来启动derper
,并不会出现在网络上。你也可以自己自定义,不过需要注意下自签的证书名字哦。
最后创建 derper
服务
shell
cat > /etc/systemd/system/derp.service <<EOF
[Unit]
Description=TS Derper
After=network.target
Wants=network.target
[Service]
User=root
Restart=always
ExecStart=/etc/derp/derper -hostname derp.myself.com -a :33445 -http-port 33446 -certmode manual -certdir /etc/derp --verify-clients
RestartPreventExitStatus=1
[Install]
WantedBy=multi-user.target
EOF
说明:
33445
是https协议用的端口,你可以根据自己的需求自定义33446
是https协议用的端口,为了防止可能的端口冲突,没有实际用途manual
参数表示证书采取手动指定的方式/etc/derp
也是自签证书的输出目录- 参数
-verify-clients
用来防止中继服务被滥用的(被白嫖);如果你有这方面需求,可去掉这个参数
启动derper
服务
输入命令启动服务:
shell
systemctl start derper
systemctl enable derper
云服务器开放端口
这里我们需要开放云服务器或自有服务器的33445
和3478
端口
需要注意的是:
3478
端口号是固定的,且类型必须为 UDP33445
为你自己定义的端口,类型为TCP
各个服务商的云服务器配置略有差异,以下是腾讯云的配置供参考:
验证derper
服务
在浏览器地址栏输入:域名 derp.example.com:33445 或者IP 47.xxx.xx.xx:33445 ,并打开
注意:IP方式
下浏览器会显示不安全提示,直接点击下方高级
按钮,继续访问即可:
最后出现如下图即代表derp
中继服务在运行:
在Tailscale 控制台添加中继节点
打开Tailscale网页控制台,切换到 Access Controls,在配置项目顶部添加如下配置并Save
保存:
javascript
{
"derpMap": {
// OmitDefaultRegions: false, // 忽略官方中继节点配置,自建后就不用官方的小水管了
"OmitDefaultRegions": true,
"Regions": {
// 这里的从900开始随便取数字
"901": {
"RegionID": 901, // 和上面的相等
"RegionCode": "Tencent-cloud", // 自己取个易于记名字
"RegionName": "Tencent-cloud1-derper",
"Nodes": [
{
"Name": "901a", // 节点名称
"RegionID":901, // 这个也和 RegionID 一样
"DERPPort":33445,// 端口号
"HostName": "<你的域名>", // 域名
},
],
},
// 这里可以接着写其它的DERP中继服务配置
//"902": {
// ...
//}
},
},
// .....
// 其他配置项
}
客户端验证
在Tailscale组网的任意一客户端,输入命令:
shell
tailscale netcheck
总结
至此,两种自建DERP中继服务的教程已经搞定了,限于水平有限,tailscale的使用和服务器的基础的相关知识不能一一列举。如果你有更好的关于自建DERP中继的方法,欢迎评论区讨论。
拓展:安装Golang依赖
- 卸载旧版本
注意:如果服务器上有其他软件依赖旧版本的 go,将其升级为新版本可能会发生不可预料的后果,请务必仔细评估与衡量
shell
rm -rf /usr/local/go
# 最好重新启动服务器
reboot
- 下载 go 安装包
以下的命令不能保证是最新版本,可以自行到 Go 官网,根据需要替换go1.22.2.linux-amd64.tar.gz
为最新版本的 Go 语言包。
bash
sudo apt update && apt upgrade # 更新软件源,已更新可省略
sudo apt install -y wget git openssl curl # 安装下载工具,若有可省略
wget https://go.dev/dl/go1.22.2.linux-amd64.tar.gz
- 将安装包解压到指定目录
shell
sudo tar -C /usr/local -xzf $HOME/go1.22.2.linux-amd64.tar.gz
- 配置 go的环境变量 创建go的软件安装目录,再使用 vim 编辑器打开 profile 文件
bash
sudo mkdir -p /usr/local/gopath/bin
sudo vim /etc/profile
在最后一行换行,插入如下代码来设置环境变量:
text
export GOROOT=/usr/local/go
export GOPATH=/usr/local/gopath
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOROOT/bin
export PATH=$PATH:$GOPATH/bin
保存后,输入如下命令,验证 Go 是否安装成功
shell
source /etc/profile
go version
- 配置 Go 的国内代理
shell
go env -w GOPROXY=https://goproxy.cn,direct