前言

如果你想访问家里的摄像头、HA、NAS,并且不想将服务暴露在公网。那么你可以尝试 tailscale、ZeroTier等服务来完成你的需求。

只需要安装好客户端、注册登录之后即可随时访问到家里。

但是,这会有些小问题,例如:

  • 直连握手困难 —— 为什么连接速度特别慢,要等很久才能连上
  • 带宽不足 —— 为什么特别卡

这个问题的核心原因往往是因为家里的服务器没有公网IP,tailscale 为了保证连接就会一直走官方的DERP服务器。而官方DERP服务都在海外且万人骑,使用体验差也就不奇怪了。所以解决方案就是自建 DERP 服务。

注意:因为对我自己来说官方免费套餐的3个用户 100 个设备已经够我用了,自建 Headscale 不在本文范围内,有兴趣可以自行尝试。

准备工作

  1. tailscale 账号,并在你的设备上安装客户端并登录(windows,MacOS,Linux,openwrt,Android,iOS等均支持)
  2. 一台有公网IP的云服务器,最好是境内的。如果没有,可以去买一个服务器,推荐买个云厂商的99元轻量服务器即可。(阿里云腾讯云
  3. 将公网服务器的防火墙打开如下端口及对应协议:33445(TCP),33446(TCP), 3478(UDP)

 

准备好之后就可以开始正式操作了

开始操作

注意,我的主机是系统版本是 Ubuntu22.04,如果不对可以参考思路,但方式都是类似的。

公网服务器

通过SSH连接到你的公网服务器上(或者你可以去云厂商在控制面板提供的一键登录之类的功能)

按照这个shell 的操作命令一行一行运行即可

# 更新软件包列表 & 升级系统
sudo apt update && sudo apt upgrade -y

# 安装基本依赖
sudo apt install -y wget git openssl curl

# 下载Golang,我使用的是x86_64版本,您也可以根据需要选择合适的版本 [All releases - The Go Programming Language](https://go.dev/dl/) 
wget https://go.dev/dl/go1.22.3.linux-amd64.tar.gz

# 删除旧的Golang并解压新的内容
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.22.3.linux-amd64.tar.gz 

# 配置环境变量
export PATH=$PATH:/usr/local/go/bin

# 检查Golang是否安装成功
go version

# 配置Golang环境(国外服务器可跳过)
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

# 安装Tailscale Derper
go install tailscale.com/cmd/derper@main

# 创建 /etc/derp 文件夹并赋予权限,以便后续修改文件重新编译到这里
sudo mkdir -p /etc/derp/
sudo chmod 777 /etc/derp/

# 编译文件到指定文件夹
cd ~/go/pkg/mod/tailscale.com@v1.67.0-pre.0.20240527202236-f1d10c12acf6/cmd/derper

找到红框中的代码,然后将绿框的三行内容注释掉(golang 是双斜线 「//」)

我这里是使用的 sudo vi cert.go 找到对应行之后输入 i 进入 insert 模式,然后双斜线注释后再按 esc 键输入:wq (保存并退出编辑)

注意:我这里是 用的 vi ,也许这个文件你会报错说它是只读文件,所以你可以强制退出来(esc 键之后 :q!)之后 sudo chmod 777 ./cert.go

修改完成后,继续执行命令

# 编译文件到之前创建的文件夹
go build -o /etc/derp/derper

# 生成SSL证书
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.service
sudo sh -c "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
RestartPreventExitStatus=1
[Install]
WantedBy=multi-user.target
EOF
"

# 启动服务
sudo systemctl enable derp
sudo systemctl start derp

值得注意的是 derp.service 文件的内容中的ExecStart,我没有启用参数 -verify-clients ,如果你的 derp 服务器暴露了,就更容易被人搭车。

为了避免这种情况,需要修改 derp.service. 完整内容如下:

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

 

Tailscale ACL修改

前往Tailscale管理端的访问控制页面,进行修改

注意:

  1. 修改`IPv4`和`端口`内容,配置内容参考如下。
  2. 我这里使用的区域是902,您可以选择类似的数字,只要不报错即可。

ACL 内容参考

"derpMap": {
		"OmitDefaultRegions": true,
		"Regions": {
			"901": {
				"RegionID":   901,
				"RegionCode": "Myself",
				"RegionName": "Myself Derper",
				"Nodes": [
					{
						"Name":             "901a",
						"RegionID":         901,
						"DERPPort":         33445,
						"IPv4":   "服务器IP",
						"InsecureForTests": true,
					},
				],
			},
		},
	},
 
 

 

实际截图如下

如此,便完成了 DERP 的配置

本地验证

# 检查状态 ,返回的数据中显示了配置就算成功了。
tailscale netcheck 

如果你发现有显示名称但是没有延迟多少毫秒,例如 99.9ms 则说明你没开公网云服务器的3478端口

 

 

参考资料

[推荐先看]Tailscale玩法之内网穿透、异地组网、全隧道模式、纯IP的双栈DERP搭建、Headscale协调服务器搭建,用一期搞定,看一看不亏吧?_哔哩哔哩_bilibili

[译] NAT 穿透是如何工作的:技术原理及企业级实践(Tailscale, 2020)

Derp服务搭建 让Tailscale/HeadScale飞起来_哔哩哔哩_bilibili

Custom DERP Servers · Tailscale

 Tailscale基础教程:部署私有DERP中继服务器 – 云原生实验室 - Kubernetes|Docker|Istio|Envoy|Hugo|Golang|云原生