Одобрение в консоли администратора выглядит последним шагом, но им не является. Сначала приложение завершается по тайм-ауту, и только потом вы обнаруживаете, что маршрутизатор в сети, а маршрут одобрен. Одобрение — это шаг распространения, а не разрешение и не гарантия пересылки. Четыре этапа должны совпасть, прежде чем пакет дойдёт до хоста за маршрутизатором подсети, и каждый может пройти, пока следующий срывается. Пройдите их по порядку и остановитесь на первом этапе, который не держится.

Четыре этапа, один сбой

Маршрутизатор объявляет префикс, tailnet одобряет это объявление, клиент принимает полученный маршрут, а политика доступа разрешает конкретное соединение. Это четыре отдельных решения, которые принимают три разных компонента. Поэтому одобренный маршрут говорит лишь о том, что сеть теперь входит в таблицу маршрутизации tailnet.

Четвёртый этап пропускают чаще всего, потому что первые три дают видимое состояние. Разрешение, покрывающее собственный адрес маршрутизатора в tailnet, не покрывает автоматически частную подсеть за ним. Это разные назначения, и политика оценивается для каждого назначения отдельно.

В Linux у третьего этапа есть и значение по умолчанию, которое удивляет: приём маршрутов к подсетям включается вручную. Несколько клиентов с графическим интерфейсом принимают объявленные маршруты по умолчанию, поэтому в смешанном парке одна машина может сбоить, пока остальные работают.

Проверьте настройку на сбоящей машине, а не предполагайте платформу. Маршрут никогда не был недостающей частью на работающих машинах, поэтому пусть они докажут, что сторона tailnet здорова. Документация Tailscale о маршрутизаторах подсетей охватывает одобрение, приём маршрутов клиентом и этап политики.

Проверьте маршрут там, где работает клиент

Начните со сбоящего клиента, а не с маршрутизатора. Убедитесь, что маршрут присутствует и что настройка клиента вообще разрешает принимать маршруты.

tailscale status
tailscale debug prefs | grep -i route
ip route get 10.20.0.42

Первая команда показывает список узлов и доступность маршрутизатора подсети, вторая печатает настройки клиента, включая флаг приёма маршрутов, а третья спрашивает ядро, какой интерфейс оно использовало бы для реального хоста в подсети. Если последняя команда называет физический интерфейс вместо интерфейса Tailscale, маршрут так и не попал в таблицу. Отсутствующий маршрут — это проблема на стороне клиента, а не одобрения. Исправьте её, прежде чем смотреть на политику.

Чтобы принимать маршруты в Linux, переподключитесь с флагом, а не предполагайте, что он установлен: tailscale up --accept-routes. Клиент, подключённый с другими флагами, сохраняет их, пока их не изменят, поэтому проверьте текущую настройку, прежде чем добавлять ещё одну. Повторный запуск первой команды после изменения должен показать маршрут в таблице.

Докажите пересылку и обратный путь

Одобрение не настраивает маршрутизатор на пересылку пакетов и не обеспечивает ответ. И то и другое — вопросы уровня хоста на стороне LAN маршрутизатора. Проверяйте их на маршрутизаторе, а не на клиенте.

sysctl net.ipv4.ip_forward
iptables -t nat -L POSTROUTING -n -v
tcpdump -ni any host 10.20.0.42 and port 443

Первая команда должна сообщить 1, иначе ядро отбросит пересланный пакет. Вторая показывает, переписывает ли маскирование маршрута к подсети источник, что является поведением по умолчанию и обычно именно тем, что нужно. Третья показывает, доходит ли запрос до назначения и возвращается ли что-нибудь; запрос без ответа — это проблема обратного пути, а не одобрения. Прочитайте три результата вместе, прежде чем менять любой из них.

Если маскирование отключено, сети назначения нужен маршрут обратно к адресам tailnet, и каждый промежуточный переход должен о нём знать. Включить маскирование снова — самое быстрое исправление для одной службы, но ценой сокрытия исходного адреса клиента от назначения. Этот компромисс важен, когда назначение журналирует адреса источника для аудита, поэтому решайте осознанно, а не переключайте флаг во время инцидента. Задокументируйте выбор, потому что следующий человек увидит только одно из двух поведений.

Прочитайте правило доступа к ресурсу

Когда маршрут есть и пересылка доказана, оставшийся подозреваемый — политика. Прочитайте разрешение, которое должно допускать соединение, и проверьте его назначение, а не только источник. Идентичность самого клиента тоже должна совпадать с селектором политики, поэтому зафиксируйте её на той же машине, которая сбоит.

tailscale status --json | head -40
tailscale ping <router-name-or-tailnet-ip>
ping -c 3 10.20.0.42

Вывод состояния определяет собственные адреса клиента и узлы, которые он видит, и с этим должен совпадать селектор источника политики. tailscale ping доказывает путь tailnet до самого маршрутизатора подсети; он разрешает имена узлов и адреса tailnet, а не хосты внутри объявленной подсети. Третья команда отправляет обычный эхо-запрос ICMP через маршрут к подсети, поэтому её результат описывает назначение, а не маршрутизатор. Отказ на уровне tailnet обычно возвращается как отказ, тогда как пакет, который уходит и никогда не возвращается, завершается тайм-аутом.

Сбой имени — это другой вопрос, чем сбой адреса; разрешите хост напрямую, прежде чем винить маршрут. Пишите разрешение под фактическую потребность ресурса, а не под всю подсеть. Открыть целую /24, чтобы работало одно приложение, — это путь, которым узкий запрос превращается в широкое разрешение, которое потом никто не решается убрать.

Если целью был выход в интернет, а не частная подсеть, правильный компонент — узел выхода, а не маршрутизатор подсети, и политика с маршрутизацией отличаются соответственно. Проверьте это решение, прежде чем расширять разрешение. Узел выхода меняет маршрут по умолчанию; маршрутизатор подсети лишь объявляет префикс.

Похожие статьи