Skip to content
twinkling.top服务Tailscale Subnet RouterEN
板型any Pi 4 or 5; a Zero 2 W works for light use
内核6.6.51+rpt-rpi-v8
空闲温度48 °C
内核架构arm64
参考机:Pi 4B 8GB / Bookworm 64-bit

服务卡片 · 网络与访问

给装不了 WireGuard 的人准备的 Tailscale 子网路由

WireGuard 是这个家自己的隧道,在对搭建者重要的一切方面都更好。但对一位没法加端口转发、也没法在受管控的工作笔记本上安装客户端配置的家人来说,它毫无用处。子网路由是一种让步:一个节点把整个局域网宣告给一个 tailnet,让某位远程家人不需要任何人改路由器设置就能看 Jellyfin。

tailscale/tailscale:v1.80.2 · 2026-10-15 ·

Tailscale Subnet Router rack plate: board stack and host ports
服务参数
容器镜像tailscale/tailscale:v1.80.2
宿主端口:41641/udp
数据目录/srv/homelab/tailscale/state
内存预留95 MB
CPU 上限0.30 vCPU (cpus: "0.30")
更新节奏monthly for the security fixes, and the node key expires after a hundred and eighty days unless expiry is disabled in the admin console
ARM 兼容arm64 native; the userspace networking mode is not used here because the kernel mode performs far better on ARM
端口映射与暴露面
宿主容器proto暴露用途
:4164141641udp仅局域网WireGuard-based transport, outbound only; nothing is forwarded at the router for this

部署步骤

  1. 在管理台创建带标签的一次性认证密钥

    可复用密钥就是那种会被复制进脚本、然后复制进仓库的密钥。一次性加标签,意味着节点一上来就已经被 tailnet 的 ACL 限定好了。

    run
    # 管理台 -> Settings -> Keys -> 生成认证密钥
    #   可复用:关   临时:关   标签:tag:rack
    echo "TS_AUTHKEY=tskey-auth-..." >> /srv/homelab/.env
  2. 启动容器并批准宣告的路由

    未批准的路由会安静地什么都不做:节点显示已连接、子网却不可达,除了管理台之外没有任何地方报错。

    run
    sysctl net.ipv4.ip_forward
    # 子网路由要求宿主机上这个值为 1
    cd /srv/homelab/tailscale && docker compose up -d
    docker exec tailscale tailscale status
  3. 专门为这个节点关闭密钥过期

    一个放在柜子里、没人会看的节点,如果不关掉过期,会在一百八十天后从 tailnet 里静静消失。这是逐节点的设置。

    run
    # 管理台 -> Machines -> 该节点 -> ... -> 关闭密钥过期
    docker exec tailscale tailscale status --json | grep -i keyexpiry

两条隧道,以及为什么两条都要

家里用 WireGuard,因为它在我们掌控之中、没有协调服务器、配置放在 git 仓库里。子网路由只为一个人存在:一位工作笔记本只允许装 Tailscale、别的都不行、而她又应该能在不用打电话求助的情况下看到照片库的家人。

两条并存不是为冗余而冗余。它们回答的是不同问题:WireGuard 回答「我怎么到我的机架」,Tailscale 回答「别人怎么在我什么都不用做的情况下到那儿」。

WireGuardTailscale
谁负责配置搭机架的人想访问的人
链路里有第三方吗没有有协调服务器,但不在数据路径上
在运营商大内网后面能用吗不能能
每加一台设备的配置成本一个新的对端和一张二维码无

宣告路由就是这整套功能的全部

子网路由把局域网的 CIDR 段宣告给 tailnet,此后 tailnet 里其它设备就能直接访问 192.168.10.20,而它们上面什么都不用装。这就是「一个节点的配置让整个机架可达」的原理。

路由必须在管理台里手工批准。这是个好的默认:被攻陷的节点没法悄悄宣告另一个子网、把流量从自己这里绕一圈。

shell
# 在派上确认宣告了什么
docker exec tailscale tailscale status
docker exec tailscale tailscale ip -4
docker exec tailscale tailscale debug prefs | grep -i route

出口节点的问题

把这个节点宣告为出口节点,能让 tailnet 设备把所有流量都从家里出去。它只对一个场景有用:有人在酒店 wifi 上,希望自己的流量从一个熟悉的地址离开。

它同时也是最容易让人烦的设置,因为家里的上行带宽会变成那台设备一切操作的天花板。这里宣告了它,一年大约会用到两次。

密钥过期是那个坑

Tailscale 节点密钥默认一百八十天后过期,过期之后节点会从 tailnet 里静静消失,直到有人登录重新认证。对一个放在柜子里、没人会去看的节点来说,这就是五个月后来自亲戚的一通求助电话。

在管理台里专门为这个节点关闭密钥过期。它是逐节点设置,也是「一个服务」和「一件周期性家务」之间的差别。

shell
# 管理台 -> Machines -> 该节点 -> ... -> 关闭密钥过期
# 然后在派上确认:
docker exec tailscale tailscale status --json | grep -i keyexpiry

compose 文件

整份文件放在 /srv/homelab/tailscale-subnet-router/compose.yaml。标签固定版本号,不用 latest——树莓派上回滚比升级麻烦得多。

compose.yaml
services:
  tailscale:
    image: tailscale/tailscale:v1.80.2
    container_name: tailscale
    restart: unless-stopped
    environment:
      TZ: Asia/Shanghai
      TS_AUTHKEY: ${TS_AUTHKEY}
      TS_STATE_DIR: /var/lib/tailscale
      TS_ROUTES: 192.168.10.0/24
      TS_EXTRA_ARGS: --advertise-exit-node --advertise-routes=192.168.10.0/24
      TS_USERSPACE: "false"
    volumes:
      - /srv/homelab/tailscale/state:/var/lib/tailscale
      - /dev/net/tun:/dev/net/tun
    cap_add:
      - NET_ADMIN
      - NET_RAW
    networks: [rack]

networks:
  rack:
    external: true

加固清单

  • 节点密钥设为不过期,并在 Tailscale 管理台里用 ACL 限制哪些 tailnet 用户能访问家里这个子网
  • 认证密钥是带标签的、预先授权的、一次性的,存在 env 文件里,而不是默认的可复用密钥
  • 路由在管理台里手动批准,节点宣告的子网必须有人同意才会生效
  • 容器只带子网路由所需的最小能力,不用 host 网络

备份方案

状态文件里是节点身份和宣告的路由。丢了它意味着要在浏览器里重新认证这个节点,一分钟的事;宣告的路由清单在 compose 文件和 git 里,所以其实什么都没丢。

上线后验证

  • 一台从没见过这个局域网的 tailnet 设备能打开 Jellyfin 地址并拿到登录页
  • 宣告的路由在管理台里显示为已批准
  • 派上的 tailscale status 列出每一台 tailnet 机器,包括离线的
  • JSON 状态输出里显示密钥过期已关闭

踩过的坑

  • 未批准的路由会安静地什么都不做。节点显示已连接、子网却不可达,而除了管理台之外没有任何地方报错。
  • 重装之后复用认证密钥会重新生成节点身份。首次注册用一次性密钥,之后就靠节点自己持久化的状态文件。
  • 子网路由要在 tailnet 和局域网之间转发流量,宿主机必须开启 IP 转发。光有容器的能力还不够。
  • 宣告了出口节点又忘了它,会把家里的上行链路变成别人的瓶颈。如果宣告了,就该有个写在某处的理由。

硬件与选型问答

相比只用 WireGuard,这是不是一种安全上的妥协?
这是一次取舍而不是妥协。Tailscale 看得到你的 tailnet 上有哪些设备,并协调它们的密钥;它看不到流量,因为流量是端到端加密的。你放弃的是「建立连接的过程中没有第三方参与」这一点。对一个替代方案是「转发端口加公开登录页」的家庭来说,这显然是改善。
为什么不直接在派上装 Tailscale 应用?
可以,在专用机器上那样更简单。跑在容器里能让机架的服务保持统一:一切都是同一个仓库里的 compose 文件,备份和升级的故事都一样,宿主机的网络配置也完全不必动。
Tailscale 出故障会怎样?
tailnet 设备之间已有的连接继续可用,因为数据路径是直连的,协调服务器只在建立新连接时才需要。家里自己的 WireGuard 隧道则完全不受影响。这正是子网路由只是补充、而不是主路径的原因。