回到首页

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

背景

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

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

参考过的教程

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

本文与参考教程区别

前置准备

阿里云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 文件中,添加以下内容:

    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 替换为你的私钥文件的实际路径。

    例如:

    Host myserver     
    HostName 192.168.0.100    
    User john    
    IdentityFile ~/.ssh/id_rsa
  5. 保存 config 文件并关闭编辑器。

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

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

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

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

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

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

如果问题仍然存在,你可以尝试使用 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的路径,并保存

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)

[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

// 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 vs. DDNS、Quick Connect

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

Tailscale vs. 公网IP

优势:

Tailscale with subnet router

subnet router 子网路由

Tailscale with Exit Node

标签:群晖NAS、tailscale