前言
如果你想访问家里的摄像头、HA、NAS,并且不想将服务暴露在公网。那么你可以尝试 tailscale、ZeroTier等服务来完成你的需求。
只需要安装好客户端、注册登录之后即可随时访问到家里。
但是,这会有些小问题,例如:
- 直连握手困难 —— 为什么连接速度特别慢,要等很久才能连上
- 带宽不足 —— 为什么特别卡
这个问题的核心原因往往是因为家里的服务器没有公网IP,tailscale 为了保证连接就会一直走官方的DERP服务器。而官方DERP服务都在海外且万人骑,使用体验差也就不奇怪了。所以解决方案就是自建 DERP 服务。
注意:因为对我自己来说官方免费套餐的3个用户 100 个设备已经够我用了,自建 Headscale 不在本文范围内,有兴趣可以自行尝试。
准备工作
- tailscale 账号,并在你的设备上安装客户端并登录(windows,MacOS,Linux,openwrt,Android,iOS等均支持)
- 一台有公网IP的云服务器,最好是境内的。如果没有,可以去买一个服务器,推荐买个云厂商的99元轻量服务器即可。(阿里云,腾讯云等
- 将公网服务器的防火墙打开如下端口及对应协议: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
![](https://cdnfile.sspai.com/2024/05/29/article/8574a5da54d849168d73e6c322746c34.png?imageView2/2/w/1120/q/40/interlace/1/ignore-error/1)
修改完成后,继续执行命令
# 编译文件到之前创建的文件夹
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管理端的访问控制页面,进行修改
注意:
- 修改`IPv4`和`端口`内容,配置内容参考如下。
- 我这里使用的区域是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,
},
],
},
},
},
实际截图如下
![](https://cdnfile.sspai.com/2024/05/29/article/c52c5c0582712359acdf1cf7db4bdded.png?imageView2/2/w/1120/q/40/interlace/1/ignore-error/1)
如此,便完成了 DERP 的配置
本地验证
# 检查状态 ,返回的数据中显示了配置就算成功了。
tailscale netcheck
![](https://cdnfile.sspai.com/2024/05/29/article/fd156c813bc37e1b7674523113454c8c.png?imageView2/2/w/1120/q/40/interlace/1/ignore-error/1)
如果你发现有显示名称但是没有延迟多少毫秒,例如 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|云原生