Tailscale 部署

这个没什么好说的,按着官方手册正常进行就好了,有很方便的一键安装程序,安装完之后登录同一个账户即可。

Install Tailscale · Tailscale Docs

Linux 使用这个命令即可一键安装:

curl -fsSL https://tailscale.com/install.sh | sh

群晖 DSM 直接进套件中心搜索 Tailscale 即可安装。

Tailscale 套件

这里唯一需要注意的地方是,若在国内使用,账号登陆要选择国内可以直连的平台,例如微软或苹果,使用谷歌账号登陆会导致终端无法正常上线,除非可以解决网络问题。

Derper 中继节点

某些网络不佳的情况下,P2P 无法打洞成功,流量将通过 Tailscale 的中继节点,也称为 Derper,进行流量的转发。

但由于 Tailscale 在中国大陆境内并没有中继节点,会导致速度非常缓慢,影响使用体验。

可以通过自己搭建 Derper 节点来解决这个问题。

官方提供也提供了操作手册:

Custom DERP Servers · Tailscale Docs

Docker 部署 Derper

官方提供的操作手册步骤较为复杂,幸运的是,已经有大佬打包好了 Docker 镜像。

GitHub - fredliang44/derper-docker: tailscale‘s selfhosted derp-server docker image

根据文档,我的 Docker 容器配置如下:

version: '3.8'
services:
  derper:
    image: fredliang/derper
    container_name: derper
    restart: always
    environment:
      - DERP_CERT_MODE=manual  # 手动设置证书
      - DERP_ADDR=:13477  # 中转端口
      - DERP_HTTP_PORT=13476  # 用不到也可以填入 -1 关闭 HTTP 服务
      - DERP_STUN_PORT=13478  # STUN 打洞端口
      - DERP_DOMAIN=derper.example.com  # 服务器域名
      - DERP_VERIFY_CLIENTS=true  # 验证客户端身份,防止白嫖
    ports:
      - "13477:13477"
      - "13478:13478/udp"
    volumes:
      - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock  # tailscale 客户端进程,用于验证客户端身份
      - ./certs:/app/certs  # SSL 证书存放地址

以下是各变量功能的翻译:

环境变量是否必需描述默认值
DERP_DOMAINDERP 服务器的主机名your-hostname.com
DERP_CERT_DIR存储 LetsEncrypt 证书的目录(如果地址的端口是:443)/app/certs
DERP_CERT_MODE获取证书的模式,可选项:manual(手动),letsencryptletsencrypt
DERP_ADDR监听服务器地址:443
DERP_STUN也运行一个 STUN 服务器true
DERP_STUN_PORT提供 STUN 服务的 UDP 端口3478
DERP_HTTP_PORT提供 HTTP 服务的端口,设置为 -1 可禁用80
DERP_VERIFY_CLIENTS通过本地的 tailscaled 实例验证连接到此 DERP 服务器的客户端false
DERP_VERIFY_CLIENT_URL如果非空,指定允许客户端连接的准入控制器 URL""

如果不喜欢 compose,也有配置一样的命令版:

docker run -dit \
--name derper \
--restart always \
-v /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock \
-v ./certs:/app/certs \
-e DERP_CERT_MODE=manual \
-e DERP_ADDR=:13477 \
-e DERP_HTTP_PORT=13476 \
-e DERP_STUN_PORT=13478 \
-e DERP_DOMAIN=derper.example.com \
-e DERP_VERIFY_CLIENTS=true \
-p 13477:13477 \
-p 13478:13478/udp \
fredliang/derper

为了防止自己搭建的 Derper 被白嫖,这里选择开启 DERP_VERIFY_CLIENTS 客户端验证功能,服务器将通过本地的 Tailscale 客户端,验证使用 Derper 的是否为本账号下的客户端。

需要提前在服务器内运行一个 Tailscale 客户端,参考上面的客户端部署方法即可。

添加 Nginx 反向代理 (并不需要)

宝塔面板 - 网站 - 反向代理中,添加一个项目,使用 derper.example.com 域名,配置自动申请 Let’s Encrypt 证书。 (最后只用到了自动申请证书的功能)

location ^~ / {
  proxy_pass http://127.0.0.1:13476;
  proxy_set_header Host $http_host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Real-Port $remote_port;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header REMOTE-HOST $remote_addr;
  proxy_connect_timeout 60s;
  proxy_send_timeout 600s;
  proxy_read_timeout 600s;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection $connection_upgrade;
}

证书部署

证书命名格式为 derper.example.com.crtderper.example.com.key,放置在执行目录下的 certs 文件夹内即可。

我这里使用了 Let’s Encrypt 的证书,通过宝塔面板自动申请,通过计划任务每天自动更新一份到目录下:

#!/bin/bash

source_crt="/www/server/panel/vhost/cert/derper.example.com/fullchain.pem"
target_crt="/docker/derper/certs/derper.example.com.crt"

source_key="/www/server/panel/vhost/cert/derper.example.com/privkey.pem"
target_key="/docker/derper/certs/derper.example.com.key"

# 检查文件是否相同
if diff -q "$source_crt" "$target_crt" &> /dev/null; then
    echo "文件内容相同,无需复制。"
else
    cp "$source_crt" "$target_crt"
    cp "$source_key" "$target_key"
    echo "文件已复制。"
fi

添加 Access Controls 规则

进入 Tailscale 后台,选择 Access Controls 配置。

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

在下面的配置文件中,在最后添加自己的 Derper。

我的配置如下:

// Example/default ACLs for unrestricted connections.
{
 // Declare static groups of users. Use autogroups for all users or users with a specific role.
 // "groups": {
 //   "group:example": ["alice@example.com", "bob@example.com"],
 // },

 // Define the tags which can be applied to devices and by which users.
 // "tagOwners": {
 //   "tag:example": ["autogroup:admin"],
 // },

 // Define access control lists for users, groups, autogroups, tags,
 // Tailscale IP addresses, and subnet ranges.
 "acls": [
  // Allow all connections.
  // Comment this section out if you want to define specific restrictions.
  {"action": "accept", "src": ["*"], "dst": ["*:*"]},

  // Allow users in "group:example" to access "tag:example", but only from
  // devices that are running macOS and have enabled Tailscale client auto-updating.
  // {"action": "accept", "src": ["group:example"], "dst": ["tag:example:*"], "srcPosture":["posture:autoUpdateMac"]},
 ],

 // Define postures that will be applied to all rules without any specific
 // srcPosture definition.
 // "defaultSrcPosture": [
 //      "posture:anyMac",
 // ],

 // Define device posture rules requiring devices to meet
 // certain criteria to access parts of your system.
 // "postures": {
 //      // Require devices running macOS, a stable Tailscale
 //      // version and auto update enabled for Tailscale.
 //  "posture:autoUpdateMac": [
 //      "node:os == 'macos'",
 //      "node:tsReleaseTrack == 'stable'",
 //      "node:tsAutoUpdate",
 //  ],
 //      // Require devices running macOS and a stable
 //      // Tailscale version.
 //  "posture:anyMac": [
 //      "node:os == 'macos'",
 //      "node:tsReleaseTrack == 'stable'",
 //  ],
 // },

 // Define users and devices that can use Tailscale SSH.
 "ssh": [
  // Allow all users to SSH into their own devices in check mode.
  // Comment this section out if you want to define specific restrictions.
  {
   "action": "check",
   "src":    ["autogroup:member"],
   "dst":    ["autogroup:self"],
   "users":  ["autogroup:nonroot", "root"],
  },
 ],

 // Test access rules every time they're saved.
 // "tests": [
 //   {
 //    "src": "alice@example.com",
 //    "accept": ["tag:example"],
 //    "deny": ["100.101.102.103:443"],
 //   },
 // ],
 "derpMap": {
  "OmitDefaultRegions": false,
  "Regions": {
   "900": {
    "RegionID":   900,
    "RegionCode": "myderp",
    "RegionName": "Guangzhou",
    "Nodes": [
     {
      "Name":     "1",
      "RegionID": 900,
      "HostName": "derper.example.com",
      "DERPPort": 13477,
      "STUNPort": 13478,
      "STUNOnly": false,
     },
    ],
   },
  },
 },
}

测试 Derper

在客户端的终端中,输入

tailscale netcheck
tailscale ping 客户端名称

即可查看连接情况。

输出如下:

PowerShell 7.4.4
PS C:\Users\jacob> tailscale netcheck

Report:
        * UDP: true
        * IPv4: yes, 183.233.233.159:11451
        * IPv6: no, but OS has support
        * MappingVariesByDestIP: true
        * PortMapping:
        * CaptivePortal: false
        * Nearest DERP: Guangzhou
        * DERP latency:
                - myderp: 18ms    (Guangzhou)
                - blr: 133.9ms (Bangalore)
                - lax: 159.3ms (Los Angeles)
                - sea: 175.3ms (Seattle)
                - sfo: 185.4ms (San Francisco)
                - dfw: 190.4ms (Dallas)
                - den: 195.6ms (Denver)
                - tor: 215.7ms (Toronto)
                - fra: 222ms   (Frankfurt)
                - par: 222ms   (Paris)
                - lhr: 225.6ms (London)
                - mia: 227.3ms (Miami)
                - nyc: 228.9ms (New York City)
                - ord: 234.2ms (Chicago)
                - ams: 236.4ms (Amsterdam)
                - waw: 241.5ms (Warsaw)
                - hnl: 243.4ms (Honolulu)
                - tok: 244.1ms (Tokyo)
                - mad: 255.4ms (Madrid)
                - hkg: 283.4ms (Hong Kong)
                - sin: 302.4ms (Singapore)
                - dbi: 330.3ms (Dubai)
                - nai: 415.9ms (Nairobi)
                - jnb: 432.4ms (Johannesburg)
                - sao: 432.8ms (São Paulo)
                - syd: 547.2ms (Sydney)
PS C:\Users\jacob> tailscale ping diskstation
pong from diskstation (100.233.64.44) via 192.233.1.2:41641 in 755ms

参考文献