Skip to content

Tailscale — sing-box

sing-box 可以加入 Tailscale tailnet,并将其 暴露为可路由的端点。该节点默认运行在用户态 gVisor 网络栈上,因此不需要 系统的 Tailscale 守护进程;将 system_interface 设为 true 可改用真实的 TUN 设备。将 control_url 指向自托管的 Headscale,即可使用替代的协调 服务器。

端点,而非出站

在 sing-box 中,Tailscale 配置为端点而非出站。该块位于根 endpoints[] 数组下、type: "tailscale",并像任何具名出站一样被 路由规则引用。

端点选项

type: "tailscale",位于 endpoints[] 下:

字段类型默认值允许值描述
state_directorystringtailscale<directory path>节点持久化其状态与密钥的目录,相对于工作目录解析。跨重启重用它可保持相同的 tailnet 身份。
auth_keystring(unset)<auth key>用于无头、非交互式登录的 Tailscale(或 Headscale)认证密钥。无人值守节点所必需。
control_urlstringcontrolplane.tailscale.com<URL>协调服务器 URL。将其指向自托管的 Headscale 即可使用替代的控制平面。
ephemeralboolfalsetrue | false注册为临时节点,一旦离线即被协调服务器自动移除。
hostnamestring(OS hostname)<string>要在 tailnet 上注册的节点名称。默认使用操作系统主机名。
accept_routesboolfalsetrue | false接受其他 tailnet 节点通告的子网路由。需主动启用。
exit_nodestring(unset)<node name or IP>将此 tailnet 节点用作出口节点来路由流量。
exit_node_allow_lan_accessboolfalsetrue | false在使用出口节点时允许直接访问 LAN。
advertise_routes[]netip.Prefix[][<CIDR>]向 tailnet 通告的子网路由,使本节点成为子网路由器。
advertise_exit_nodeboolfalsetrue | false将本节点通告为出口节点,供其他 tailnet 成员路由。
advertise_tagsbadoption.Listable[string](unset)[<tag>]为本节点通告的 ACL 标签(如 tag:server),供 tailnet 访问策略使用。
relay_server_port*uint16(unset)<port>在此 UDP 端口上运行内置的对等中继服务器,帮助其他节点穿透 NAT。
relay_server_static_endpoints[]netip.AddrPort(unset)[<ip:port>]当中继服务器的公网地址无法自动发现时,为其静态通告的 ip:port 端点。
system_interfaceboolfalsetrue | false使用真实的系统 TUN 接口,而非用户态 gVisor 网络栈。更快,但需要更高权限。
system_interface_namestring(auto)<string>启用 system_interface 时,系统 TUN 接口的名称。
system_interface_mtuuint32(auto)<bytes>启用 system_interface 时,系统 TUN 接口的 MTU。
udp_timeoutUDPTimeoutCompat5m<duration>端点处理的 UDP 会话的空闲超时。

源码: option/tailscale.go:13-32 · 锚定版本 v1.13.11 (553cfa1)

该结构还内嵌 DialerOptions 用于底层套接字——bind_interfacerouting_markdetour 等。

示例

使用无头认证密钥加入 tailnet 的最简端点:

json
{
  "endpoints": [
    {
      "type": "tailscale",
      "tag": "ts-ep",
      "auth_key": "tskey-auth-xxxxxxxxxxxx"
    }
  ]
}

通过 tailnet 出口节点路由选定流量:

json
{
  "endpoints": [
    {
      "type": "tailscale",
      "tag": "ts-ep",
      "auth_key": "tskey-auth-xxxxxxxxxxxx",
      "hostname": "sing-box-node",
      "exit_node": "us-exit-1",
      "exit_node_allow_lan_access": true,
      "accept_routes": true
    }
  ],
  "route": {
    "rules": [
      { "domain_suffix": [".example.com"], "outbound": "ts-ep" }
    ]
  }
}

针对自托管的 Headscale 协调服务器,并使用专用状态目录:

json
{
  "endpoints": [
    {
      "type": "tailscale",
      "tag": "ts-headscale",
      "auth_key": "<headscale pre-auth key>",
      "control_url": "https://headscale.example.com",
      "state_directory": "tailscale-state"
    }
  ]
}

说明

  • Tailscale 端点仅编译进启用 gVisor 的构建。在不含 gVisor 的构建中, tailscale 类型不会被注册。
  • auth_key 启用无头(非交互式)登录——无人值守节点所必需。没有它, 节点无法自行认证。
  • state_directory 默认为 tailscale,相对于工作目录解析。节点在此 持久化其密钥与机器身份,因此重用同一目录可在重启后保持相同的 tailnet 身份。
  • ephemeral: true 注册一个一旦离线即被协调服务器自动移除的节点—— 适用于短生命周期或容器化实例。
  • accept_routes 需主动启用:除非启用,否则其他节点通告的子网路由会被 忽略。反之,advertise_routes / advertise_exit_node 使本节点成为 tailnet 的子网路由器 / 出口节点。
  • system_interface: false(默认)完全经由 gVisor 在用户态运行——无需 特权但较慢。system_interface: true 绑定真实 TUN 设备以获得更高吞吐, 代价是需要更高权限。
  • 可以通过在 dns 块中添加 tailscale DNS 服务器来使用 Tailscale 的 MagicDNS,它会经由该节点解析 *.ts.net 名称。

跨内核说明

  • mihomo 将 Tailscale 暴露为出站proxies[]type: tailscale), 使用连字符字段名而非端点。参见 Tailscale — mihomo
  • Xray-core 没有 Tailscale 支持。

源码: option/tailscale.go:13-32 · v1.13.11 (553cfa1)

由 Argsment 出品的 Core Tutorial