加速外部访问NAS:无需域名建立tailscale derp中继服务

背景

对于NAS玩家,随时随地,而不仅仅是在家庭局域网内,访问自己的NAS是的普遍需求。

实际使用中,使用Tailscale实现设备间安全连接时,直连并不总是稳定可靠。为了提高Tailscale网络的稳定性和性能, 需要自建DERP中继服务器。

参考过的教程

  1. 大内网战略(6):自建 Tailscale DERP 中继服务器 保姆级教程 - 知乎
  2. 【傻呱呱】Tailscale 搭建derp中继节点(无需域名)_derp教程-CSDN博客

本文与参考教程区别

  • 教程1需要域名,本文无需
  • 教程2需要付费的FinalSHELL工具,本文使用更广泛接受的VS Code。
  • 包含了实践教程1、2过程中遇到的新问题和解决方法
  • 用简化方法达成教程1、2中的部分步骤
  • 非docker方案,无需docker修改和重新打包

前置准备

阿里云ECS Ubuntu 22.04 LTS

开始

使用VS Code连接到阿里云ECS

  1. 在本地计算机上,打开终端或命令提示符。

  2. 进入 SSH 配置文件所在的目录:

    • 在 Windows 上,SSH 配置文件通常位于 C:\Users\<your-username>\.ssh\ 目录下。
    • 在 macOS 和 Linux 上,SSH 配置文件通常位于 ~/.ssh/ 目录下。
  3. 打开或创建一个名为 config 的文件(如果该文件不存在)。可以使用任何文本编辑器打开该文件,如 VS Code、记事本等。

  4. config 文件中,添加以下内容:

    1
    2
    3
    4
    Host myremotehost     
    HostName your-remote-host-ip-or-domain
    User your-username
    IdentityFile path/to/your/private/key
    • myremotehost 替换为你想要给远程主机起的别名,可以是任何易记的名称。
    • your-remote-host-ip-or-domain 替换为远程主机的 IP 地址或域名。
    • your-username 替换为你在远程主机上的用户名。
    • path/to/your/private/key 替换为你的私钥文件的实际路径。

    例如:

    1
    2
    3
    4
    Host myserver     
    HostName 192.168.0.100
    User john
    IdentityFile ~/.ssh/id_rsa

  5. 保存 config 文件并关闭编辑器。

  6. 在 VS Code 中,安装 “Remote - SSH” 插件(如果尚未安装)。

  7. 在 VS Code 中,打开命令面板(可以按 F1Ctrl+Shift+P),然后输入 “Remote-SSH: Connect to Host”。

  8. 在出现的列表中,选择你在 config 文件中定义的远程主机别名(如 myremotehostmyserver)。

  9. VS Code 将使用你指定的私钥文件尝试连接到远程主机。如果连接成功,你将看到一个新的 VS Code 窗口,其中打开了远程主机上的文件夹。

现在,你已经成功使用私钥通过 VS Code 的 SSH Remote 插件连接到了远程主机。你可以在 VS Code 中编辑、保存和运行远程主机上的文件和项目了。

如果在连接过程中遇到任何问题,请确保:

  • 私钥文件的路径是正确的。
  • 私钥文件具有正确的权限设置(通常为 600400)。
  • 远程主机上启用了 SSH 服务,并且防火墙允许 SSH 连接。

如果问题仍然存在,你可以尝试使用 ssh -i path/to/your/private/key your-username@your-remote-host-ip-or-domain 命令在终端中手动连接到远程主机,以排查可能的问题。

安装tailscale

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up启动,然后授权加入tailscale网络

安装Golang

卸载旧版:sudo rm -rf /usr/local/go
在自己的本地主机上下载最新版Golang Download and install - The Go Programming Language
在tailscale设置中启用Taildrop · Tailscale Docs,右键
在远程主机上运行 sudo tailscale file get .,接收的文件在当前目录。
解压Go到相应目录:sudo tar -C /usr/local -xzf $HOME/go<最新版本号>.linux-amd64.tar.gz

配置Golang自动运行

sudo code ~/.profile
末尾粘贴以下代码配置GO的路径,并保存

1
2
3
4
5
export GOROOT=/usr/local/go
export GOPATH=/usr/local/gopath
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOROOT/bin
export PATH=$PATH:$GOPATH/bin

使新配置生效:sudo source ~/.profile
输入go version,如出现版本信息,则配置成功。

安装 tailscale derp 服务

建立目录:sudo mkdir -p /usr/local/gopath/bin

分别输入并回车以下两行代码,设置go代理+安装

go env -w GOPROXY=https://goproxy.cn,direct

go install tailscale.com/cmd/derper@main

修改 derp 以跳过域名需求

通过 VS code 访问文件 /usr/local/gopath/pkg/mod/tailscale.com@v1.67.0-pre.0.20240510224123-fc1ae97e1037/cmd/derper/cert.go
如果你安装的tailscale版本、在profile中配置的go目录(tailscale derp下载在go 目录下面)不同,请做相应的修改。也可以使用VS Code搜索该文件。
对cert.go做如下修改并保存:

重新编译修改过的derp

切换到cert.go该文件的路径下

重新编译修改过的derp:go build -o /etc/derp/derper
在/etc/derp路径下检查derper以验证编译结果。

自签域名(不会被验证)

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"

这个命令生成了一个自签名的SSL/TLS证书,使用RSA算法和4096位私钥,有效期为10年。证书的主题和主题备用名称都设置为 derp.myself.com。生成的私钥和证书分别保存在 /etc/derp/derp.myself.com.key 和 /etc/derp/derp.myself.com.cn.crt 文件中。

配置修改后的Derp并启动

code /etc/systemd/system/derp.service
输入以下配置用于启动derp服务(已经配置了只允许tailscale 客户端连接 –verify-clients)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=no domain 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


启用derp服务:systemctl daemon-reload
systemctl restart derp
检查derp状态
systemctl status derp
设置开机自启
systemctl enable derp
打开阿里云ECS所属的安全组的相应端口(比如示例中设置的33445)
网页中输入阿里云ip : “https://xxx.xxx.xxx.xxx:33445“ ,出现“Client sent an HTTP request to an HTTPS server.”字样则成功。

在tailscale控制台中启动配置好的derp中继

https://login.tailscale.com/admin/acls/file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Example/default ACLs for unrestricted connections.
{
// Declare static groups of users beyond those in the identity service.
"Groups": {
"group:example": ["user1@example.com", "user2@example.com"],
},
// Declare convenient hostname aliases to use in place of IP addresses.
"Hosts": {
"example-host-1": "100.100.100.100",
},
"ACLs": [
// Match absolutely everything. Comment out this section if you want
// to define specific ACL restrictions.
{"Action": "accept", "Users": ["*"], "Ports": ["*:*"]},
],
"derpMap": {
//"OmitDefaultRegions": true,
"Regions": {
"901": {
"RegionID": 901,
"RegionCode": "XXXXX",
"RegionName": "XXXXX",
"Nodes": [{
"Name": "XXXXX",
"RegionID": 901,
"IPv4": "XXX.XXX.XXX.XXX",
"DERPPort": 33445,
"InsecureForTests": true,
}],
},
},
},
}


本地机器在命令行中运行tailscale netcheck tailscale status,看到自己的derp即成功。
可以通过tailscale ping xxx.xxx.xxx.xxx判断流量路径。

在开始搭建之前,我们需要准备一台阿里云ECS实例,并且配置好VS Code的Remote-SSH插件,以便于远程管理服务器。接下来,我们将在ECS上安装Tailscale客户端,并配置Subnet Router和Exit Node,以实现不同的流量转发策略。

搭建DERP服务器的核心步骤包括:编译安装Derp可执行文件、生成自签名SSL/TLS证书、创建Systemd服务文件等。在这个过程中,我们需要安装Go编译环境,并且合理配置Derp服务器的各项参数,如监听端口、证书路径等。

完成搭建后,我们还需要在Tailscale管理控制台添加Derp节点,并在客户端连接该节点,以验证服务器的可用性。同时,我们还要学会如何检查Derp服务的运行状态,以及排查可能出现的问题,如服务无法启动、节点间无法连通等。

在实践过程中,我遇到了一些技术难点,例如:配置Go环境变量、生成兼容Derp的自签名证书、编写正确的Systemd服务文件等。通过不断尝试和查阅资料,我逐一解决了这些问题,并总结出了一套完整的搭建流程。

其他几种方法实现外网访问NAS及优缺点对比

Tailscale vs. Zerotier ONE

优势:
同为无需将自己的NAS暴露在公网上带来的方案,安全性均较高。

  • 简单性: Tailscale更易于设置和使用,用户友好。
  • 可能的性能优势:Tailscale 使用 WireGuard 协议,该协议以简单、高效、易于审计而闻名,这有助于其性能优势。这通常可以使 Tailscale 更快,特别是在设备不在同一子网中的配置中(WunderTech )。另一方面,ZeroTier 采用自己的基于 UDP 的协议,该协议可能无法与 WireGuard 的速度相匹配,但可提供强大的性能以及设置私有根服务器的灵活性​(WunderTech )(​​ TechCult )。
    参考:无公网IP搞定群晖+ZEROTIER ONE实现内网穿透_NAS存储_什么值得买

Tailscale vs. DDNS、Quick Connect

优势: 同为实现外网访问NAS的方案,Tailscale在多个关键领域表现优于DDNS,具体优势如下:

  • 简单性: Tailscale的设置和使用过程更为简单直接。用户只需在NAS上安装Tailscale客户端,并登录账户即可实现设备间的自动连接,无需手动处理IP地址和端口转发设置。
  • 安全性: Tailscale利用WireGuard协议,为数据传输提供端到端加密,大大增强了通信的安全性。相比之下,DDNS需通过端口转发实现远程访问,这可能会暴露网络端口给潜在的网络攻击。
  • 稳定性: Tailscale的连接稳定性更优,不受动态IP变化的影响。DDNS服务依赖于及时的IP地址更新,如果DNS更新有延迟,可能会导致服务中断。
  • 管理与维护: Tailscale提供中央管理界面,用户可以轻松管理设备和权限配置。DDNS配置较为分散,每次IP变更可能都需要手动检查和调整设置。

Tailscale vs. 公网IP

优势:

  • 安全:无需暴露家庭NAS在公网上。
  • 易用和门槛: 不是所有地区和运营商均可以提供固定的公网IP,但Tailscale开箱即用。
  • 成本: 固定的公网IP通常需要较高的费用。
    劣势: 直连可能更稳定高速。

Tailscale with subnet router

subnet router 子网路由

  • 配置相对复杂,需要仔细规划子网划分和路由规则。
  • 可能需要调整现有网络的IP地址分配。

Tailscale with Exit Node

  • 优势:
    • 配置简单,将所有流量转发到指定节点,无需考虑子网划分。
    • 适合为整个Tailscale网络提供统一的出口。
  • 劣势:
    • 所有流量都经过Exit Node,可能导致网络性能下降和出口节点压力增大。
    • 出口节点故障可能影响整个网络的连通性。
    • 隐私性相对较低,Exit Node可以监视和控制所有流量。