Архитектура
TailSocks обеспечивает стабильную и высокопроизводительную работу Tailscale на Android, запуская сетевой движок в пользовательском пространстве (userspace). На этой странице подробно описаны технические решения, применяемые для преодоления системных ограничений платформы Android.
Гибридный мост связи
Заголовок раздела «Гибридный мост связи»Система разделена на три функциональных слоя:
- Tailscale Демон (Ядро): Разделяемая библиотека формата Position Independent Executable (PIE) (
libtailscale.so), скомпилированная из официальных исходников Tailscale с флагами сборки, исключающими немобильные компоненты (D-Bus, Kubernetes, AWS и т. д.). Тот же файл — и CLI: с апстримовским тегомts_include_cliон работает какtailscale, когда его вызывают под этим именем (Консоль) или сTS_BE_CLI=1(обёртка Root-режима). - Мост Управления (
appctr): Контроллер на языке Go, взаимодействующий с демоном через локальные Unix-сокеты (tailscaled.sock) и предоставляющий удобный JNI-интерфейс для Android-слоя. - UI на Kotlin / Jetpack Compose: Слой представления, отвечающий за пользовательские настройки, визуализацию состояния и отображение диагностики в реальном времени.
Мультиаккаунтная изоляция профилей
Заголовок раздела «Мультиаккаунтная изоляция профилей»Для поддержки нескольких профилей Tailscale на одном устройстве TailSocks реализует строгую изоляцию файловой системы и конфигураций:
- Перенаправление Состояния (State Redirection): Каждому аккаунту присваивается уникальный ID, привязанный к изолированному каталогу состояния в
files/states/{id}. Это гарантирует, что ключи устройств и кэши сетевых карт (netmap) разных аккаунтов никогда не пересекаются. - Кэш карты сети: tailscaled 1.104+ хранит последнюю карту сети в
files/states/{id}/profile-data/<профиль>/netmap-cache/и запускается по ней, не дожидаясь ответа сервера координации, — если сервер выдал узлу атрибутcache-network-maps. В «Настройки → Обход блокировок» его можно выключить (TS_USE_CACHED_NETMAP=false) и очистить; в резервные копии он не попадает. - Изоляция Настроек: Параметры приложения сохраняются в индивидуальных контейнерах
SharedPreferences(appctr_{id}). - Жизненный Цикл Процесса: При смене аккаунта выполняется полная остановка демона и его повторная инициализация, что исключает утечку состояния между профилями.
Нативный движок DNS и реактивная синхронизация
Заголовок раздела «Нативный движок DNS и реактивная синхронизация»Стандартные приложения Android не способны маршрутизировать UDP-пакеты в сеть userspace без использования системного TUN-интерфейса. TailSocks решает эту проблему с помощью реактивной многоступенчатой логики разрешения имен:
- Синхронизация Шины IPN (IPN Bus Synchronization): Go-мост поддерживает постоянное соединение со встроенной шиной уведомлений демона (
mask=1032). Это позволяет отслеживать измененияNetMap, суффиксы MagicDNS и маршрутыSplitDNSRoutesв режиме реального времени. - Разрешение Имен Узлов в Памяти: Все узлы сети кэшируются в памяти по FQDN и коротким именам. Разрешение имен в доменной зоне
*.ts.netпроисходит за 0 мс путем прямого обращения к кэшу в памяти. - Split DNS (TCP-over-SOCKS5): Для доменов, соответствующих корпоративным маршрутам (например,
company.internal), мост инкапсулирует UDP-запросы в TCP-фреймы и туннелирует их через SOCKS5 к внутреннему resolver IP, предоставленному в netmap. - Умный Фолбэк Публичных Запросов (Smart Upstream Fallback): Публичные запросы (например,
google.com) сначала отправляются через APIdns-queryв Tailscale. Если демон возвращаетSERVFAIL(характерно для режима userspace), мост автоматически переключается на настраиваемые пользователем системные или DoH (DNS-over-HTTPS) резолверы. - Кэш ответов: Каждый ответ шагов 3–4 хранится на время своего TTL (не меньше 10 с, не дольше 1 ч; NXDOMAIN и NODATA — 30 с или минимум из SOA, если он меньше). При попадании ответ получает ID транзакции клиента, а TTL записей уменьшаются на прошедшее время. Кэш сбрасывается вместе с кэшем узлов и при любом изменении маршрутов Split DNS, чтобы устаревший маршрут не отдавал старый ответ. Каждый запрос пишется в лог на уровне debug с полем
cached=true|false.
Нативная диагностика (Netcheck)
Заголовок раздела «Нативная диагностика (Netcheck)»- Ограничения Android: Ограничения прав доступа (
netlinkrib: permission denied) препятствуют тому, чтобы демонtailscaledсамостоятельно опрашивал сетевые интерфейсы, что приводит к сбоям диагностики в ядре. - Решение: Мост
appctrреализует нативный методGetNetcheckFromAPI, запускающий пакетtailscale.com/net/netcheckнепосредственно внутри процесса приложения. - Синхронизация Интерфейсов: С помощью переменной окружения
TS_NET_STATEмост передает состояния сетевых интерфейсов (передаваемые из Kotlin) в ядро. Сетевой мониторNewStaticиспользует эти данные для формирования точных отчетов STUN/DERP в обход ограничений демона.
Taildrop и Files API
Заголовок раздела «Taildrop и Files API»TailSocks включает надежный менеджер передачи файлов:
- Входящие Файлы: Переменная окружения
TS_TAILDROP_DIRуказывает ядру наfiles/taildrop/<account>(core/TaildropPaths.kt) — каталог только с пользовательскими файлами, отдельно от ключей узла вfiles/states/. - DocumentsProvider:
TailsocksFileProviderпредоставляет для Android Storage Access Framework (SAF) именно эти каталоги Taildrop (и общие папки Taildrive по WebDAV). Это позволяет просматривать полученные через Taildrop файлы в системном приложении «Файлы». - Исходящие Файлы: Через SAF приложение читает файлы и передает их в
file-putAPI демона через мост с корректным экранированием путей URL.
Самовосстановление и декларативная конфигурация (Stateless Configuration)
Заголовок раздела «Самовосстановление и декларативная конфигурация (Stateless Configuration)»Для устранения проблем с «зависанием» маршрутов в userspace-движках:
- Явное Управление Состоянием: Каждая операция обновления конфигурации включает явные сбрасывающие флаги (например,
--exit-node=) для принудительной очистки старых параметров, не выбранных в UI. Для Serve/Funnel применяется паттерн «Reset-then-Apply» (отправка{}перед применением новой конфигурации). - Цикл Проверки Здоровья: Фоновая задача периодически проверяет наличие выбранного Exit Node в текущей сетевой карте аккаунта. Если узел становится недоступен или недействителен, конфигурация автоматически очищается.
- Прокси Управляющего Сервера: Поддерживается работа через глобальные SOCKS5/HTTP-прокси для связи с сервером координации. Трафик SOCKS5 принудительно направляется через
ALL_PROXYс очисткойHTTP_PROXYво избежание протокольных ошибок (например, “unknown Socks version”).
Анализ патчей ядра и зависимости
Заголовок раздела «Анализ патчей ядра и зависимости»TailSocks поддерживает минимальный набор атомарных патчей для оригинального ядра Tailscale для обеспечения мобильной совместимости. Патчи располагаются в директории appctr/patches/ и внедряют возможности, недоступные через внешний LocalAPI:
01-enable-socks-android: Включает поддержку SOCKS5 в режиме userspace-networking на Android.02-socks5-auth: Добавляет поляUsername/Passwordв исходящий SOCKS5-слушатель (значения считываются из переменных окружения).03-taildrop-monolithic-fs: РегистрируетfsFileOpsна чистом Go во избежание JNI-паник в Android и направляет Taildrop в изолированную директорию приложения. Ещё возвращает подсчёт байт при приёме файла (send.go), чтобыNotify.IncomingFilesпоказывал прогресс — начиная с 1.84 апстрим копирует мимо счётчика.04-vip-services: Добавляет виртуальные сервисы (VIP) в структуруHostInfo, делая их видимыми для сервера координации.05-localapi-cert: Включает компиляцию эндпоинта/certдля Android.06-android-netmon: Реализует кастомныйnetmon.InterfaceGetterдля обхода ограниченийnetlinkна Android 10+ и по умолчанию представляет узел серверу координации как Linux-клиент командной строки (OS = linux,App = tailscale-cli,DeviceModel = Tailsocks). При включённом «Сообщать настоящую ОС» (TS_HONEST_HOSTINFO=1) сообщает настоящее Android-устройство; в самом клиенте от этих полей ничего не зависит.07-taildrive-android: Адаптации Taildrive для платформы Android.08-netstack-cgnat: Исправление маршрутизации CGNAT в netstack.09-netstack-loopback: Loopback-маршрутизация пакетов, адресованных самому себе в netstack.10-taildrive-userspace-dial: Маршрутизация WebDAV удаленных пиров черезtsdial.Dialer.11-noop-dns-fallback: Внедрение переменной окружения DNS fallback во избежание ошибок SERVFAIL.