两种方式自建Tailscale的 DERP 中继教程

不管是文件传输、远程开发、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文件

注意:

  1. 上述创建的证书文件夹,只有 root 账号才有权限操作上传证书
  2. 如果没有.crt文件,可将.pem 后缀改为.crt
  3. 证书的名称要和你的域名保持一致

接着,使用 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

说明:

  1. 你需要将代码中的test.example.com替换成自己的域名
  2. 33445端口是我这边定义的端口,你可以根据自己的需要改成自己想要的端口号
  3. 参数 -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

说明:

  1. 33445是https协议用的端口,你可以根据自己的需求自定义
  2. 33446是https协议用的端口,为了防止可能的端口冲突,没有实际用途
  3. manual参数表示证书采取手动指定的方式
  4. /etc/derp也是自签证书的输出目录
  5. 参数-verify-clients用来防止中继服务被滥用的(被白嫖);如果你有这方面需求,可去掉这个参数

启动derper服务

输入命令启动服务:

shell 复制代码
systemctl start derper
systemctl enable derper

云服务器开放端口

这里我们需要开放云服务器或自有服务器的334453478端口

需要注意的是:

  1. 3478端口号是固定的,且类型必须为 UDP
  2. 33445为你自己定义的端口,类型为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依赖

  1. 卸载旧版本

注意:如果服务器上有其他软件依赖旧版本的 go,将其升级为新版本可能会发生不可预料的后果,请务必仔细评估与衡量

shell 复制代码
rm -rf /usr/local/go

# 最好重新启动服务器
reboot
  1. 下载 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
  1. 将安装包解压到指定目录
shell 复制代码
sudo tar -C /usr/local -xzf $HOME/go1.22.2.linux-amd64.tar.gz
  1. 配置 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
  1. 配置 Go 的国内代理
shell 复制代码
go env -w GOPROXY=https://goproxy.cn,direct
相关推荐
光影少年8 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
Rattenking13 分钟前
React 源码学习01 ---- React.Children.map 的实现与应用
javascript·学习·react.js
熊的猫1 小时前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
别拿曾经看以后~3 小时前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
川石课堂软件测试3 小时前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
JerryXZR3 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
problc3 小时前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter
Gavin_9154 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼5 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
待磨的钝刨6 小时前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json