Skip to content

Tailscale — sing-box

sing-box может подключиться к tailnet Tailscale и предоставить его как маршрутизируемую конечную точку. По умолчанию узел работает на пользовательском сетевом стеке gVisor, поэтому системный демон Tailscale не нужен; задайте system_interface: true, чтобы использовать настоящее TUN-устройство. Укажите в control_url самостоятельно размещённый Headscale, чтобы использовать альтернативный координационный сервер.

Конечная точка, а не исходящий

Tailscale настраивается в sing-box как конечная точка, а не как исходящий. Блок располагается в корневом массиве 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Разрешить прямой доступ к локальной сети, пока используется выходной узел.
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>Запустить встроенный сервер ретрансляции (peer relay) на этом UDP-порту, чтобы помочь другим узлам обходить NAT.
relay_server_static_endpoints[]netip.AddrPort(unset)[<ip:port>]Статически анонсируемые конечные точки ip:port для сервера ретрансляции, когда его публичный адрес нельзя определить автоматически.
system_interfaceboolfalsetrue | falseИспользовать настоящий системный TUN-интерфейс вместо пользовательского сетевого стека gVisor. Быстрее, но требует повышенных привилегий.
system_interface_namestring(auto)<string>Имя системного TUN-интерфейса, когда включён system_interface.
system_interface_mtuuint32(auto)<bytes>MTU системного TUN-интерфейса, когда включён system_interface.
udp_timeoutUDPTimeoutCompat5m<duration>Тайм-аут простоя для UDP-сессий, обрабатываемых конечной точкой.

Исходный код: option/tailscale.go:13-32 · зафиксировано на v1.13.15 (3708fa1)

Структура также встраивает DialerOptions для нижележащего сокета — bind_interface, routing_mark, detour и т. д.

Примеры

Минимальная конечная точка, подключающаяся к 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-устройство ради большей пропускной способности ценой повышенных привилегий.
  • MagicDNS от Tailscale можно использовать, добавив DNS-сервер tailscale в блок dns, — он разрешает имена *.ts.net через узел.

Сравнение с другими ядрами

  • mihomo предоставляет Tailscale как исходящий (proxies[] с type: tailscale) с именами полей через дефис, а не как конечную точку. См. Tailscale — mihomo.
  • Xray-core не поддерживает Tailscale.

Исходный код: option/tailscale.go:13-32 · v1.13.15 (3708fa1)

Core Tutorial от Argsment