Tailscale serve и funnel: в чем разница
Разбираем отличия Tailscale serve и funnel. Узнайте, как открыть локальный порт только для своей сети или сделать сервис доступным всему интернету, и как обойти ACL-ограничения.
tailscale serve и funnel: кто имеет доступ к URL
Разница между tailscale serve и tailscale funnel заключается исключительно в целевой аудитории. serve создает HTTPS-интерфейс (hypertext transfer protocol secure) для локального порта и публикует его только внутри вашей tailnet. funnel публикует этот же локальный порт в общедоступном интернете через ретрансляционные серверы Tailscale. Обе команды принимают одинаковые флаги и цели. Одно слово отделяет приватную панель управления от ресурса, доступного всему миру.
Обе команды предоставляют сертификат, которому уже доверяют браузеры, с именем, заканчивающимся на ts.net, и ни одна из них не требует открытия входящего порта на брандмауэре вашего VPS. Ваш демон tailscaled уже поддерживает исходящее соединение с tailnet, поэтому трафик поступает через него. Подключение сервера к tailnet — это одна задача, и настройка VPS в качестве exit node Tailscale или анонсирование subnet router для частной сети решают её. Публикация сервиса, который уже находится в tailnet, — это данная задача.
Что необходимо для работы команд
- Tailscale версии 1.38.3 или новее на VPS, с выполненным входом в вашу tailnet. Проверьте это с помощью
tailscale versionиtailscale status. - Включенный MagicDNS. MagicDNS — это встроенная в Tailscale система доменных имен (DNS), которая присваивает машине имя вида
blog-vps.your-tailnet.ts.netвместо использования только адреса100.x. - Включенные HTTPS-сертификаты для tailnet на странице DNS в панели администратора. Без этого у вас не будет сертификата для использования перед вашим портом.
- Только для
funnel: атрибут узлаfunnelв файле политики tailnet. Именно на этом этапе чаще всего возникают трудности при первых попытках, поэтому ниже это разобрано подробно.
Каждая команда здесь начинается с sudo, так как CLI взаимодействует с tailscaled через сокет, доступный для записи только пользователю root. Чтобы разрешить одному пользователю выполнять команды без этого:
sudo tailscale set --operator=$USERПубликация в tailnet с помощью tailscale serve
Укажите serve на локальный порт, и утилита выполнит остальную работу.
sudo tailscale serve 3000Available within your tailnet:
https://amelie-workstation.pango-lin.ts.net
|-- / proxy http://127.0.0.1:3000
Press Ctrl+C to exit.Команда 3000 в чистом виде — это сокращение для http://127.0.0.1:3000. Tailscale ожидает соединений на 443 порту по адресу машины в tailnet, завершает TLS (transport layer security) с использованием сертификата ts.net и перенаправляет обычный HTTP на ваш локальный порт. Вашему приложению не нужно знать о существовании сертификата; это основная причина использовать данный метод для панели администратора, которую в противном случае пришлось бы оставить доступной по обычному HTTP.
Теперь посмотрите на последнюю строку: Press Ctrl+C to exit. Команда выполняется в интерактивном режиме, и привязка существует только внутри этого процесса. Закройте терминал, и URL перестанет работать, так как настройки не были записаны на диск. Добавьте --bg, и привязка будет сохранена в конфигурации serve узла, которая переживет как закрытие терминала, так и перезагрузку.
sudo tailscale serve --bg 3000Команда serve принимает не только номер порта. --set-path монтирует сервис по подпути, поэтому несколько приложений могут использовать одно имя хоста:
sudo tailscale serve --bg --set-path=/grafana 3000
sudo tailscale serve --bg --set-path=/metrics 9090Целью также может быть каталог со статическими файлами или бэкенд, который уже использует TLS с сертификатом, проверку которого вы хотите пропустить:
sudo tailscale serve --bg /srv/reports
sudo tailscale serve --bg https+insecure://localhost:8443Функционал не ограничивается только HTTP. --tcp=<port> перенаправляет поток TCP (transmission control protocol) в исходном виде, а --tls-terminated-tcp=<port> завершает TLS на вашем узле и передает данные в открытом виде. Это позволяет использовать доверенный сертификат перед сервисом, который вообще не поддерживает HTTP:
sudo tailscale serve --bg --tls-terminated-tcp=443 tcp://127.0.0.1:9899Почему Funnel сообщает, что атрибут узла не задан?
По умолчанию Funnel отключен для всей tailnet. При первом запуске выводится это сообщение, после чего работа прекращается:
Funnel not available; "funnel" node attribute not set. See https://tailscale.com/kb/1223/tailscale-funnel/.Команда была введена верно. Политика tailnet не предоставила данному узлу разрешение на публикацию, поэтому клиент прерывает работу до обращения к реле. Отредактируйте файл политики tailnet в панели администратора в разделе Access Controls и добавьте атрибут:
"nodeAttrs": [
{
"target": ["autogroup:member"],
"attr": ["funnel"],
},
],autogroup:member предоставляет это право всем участникам tailnet. Если публиковать данные должен только один узел, присвойте ему тег и укажите его в правиле, например tag:public. Сохраните политику и повторно выполните команду funnel.
Если ваша учетная запись обладает правами администратора tailnet, в новых версиях клиентов доступен быстрый способ: CLI выводит URL для подтверждения в login.tailscale.com. Переход по этой ссылке активирует HTTPS-сертификаты и автоматически добавляет нужный атрибут. Если вы не являетесь администратором, эта ссылка не поможет. Внесение изменений требует доступа к управлению политиками.
Публикация в интернет с помощью Tailscale Funnel
После установки атрибута используйте уже знакомую вам команду, изменив в ней только глагол.
sudo tailscale funnel --bg 3000Available on the internet:
https://amelie-workstation.pango-lin.ts.net
|-- / proxy http://127.0.0.1:3000
Press Ctrl+C to exit.Внимательно читайте первую строку каждый раз. Available within your tailnet и Available on the internet — единственное заметное различие между приватным и публичным сервисом, а команды для их создания различаются всего на одно слово.
По состоянию на август 2026 года, Funnel прослушивает только порты 443, 8443 или 10000. Порт 443 используется по умолчанию, а --https=8443 или --https=10000 являются альтернативами. Использование любого другого порта приведет к отказу, так как ретрансляторы Funnel принимают соединения только на указанных портах. Именно поэтому URL-адрес Funnel всегда представляет собой либо просто имя хоста, либо имя хоста с добавленным в конце :8443.
Как узнать, что опубликовано в данный момент?
Гадания — причина, по которой панель управления может оставаться публичной целый месяц. Вместо этого запросите состояние узла.
tailscale serve status
tailscale funnel status
tailscale serve status --jsonОбе команды статуса считывают одну и ту же конфигурацию, поэтому любая из них дает полную картину. Используйте форму --json в скриптах или при плановых проверках, так как обычный вывод предназначен для чтения людьми. Если ничего не настроено, вы увидите одну строку:
No serve configЕсли вы видите это после настройки, которая ранее работала, значит, отображение было создано в интерактивном режиме, а процесс завершился. Воссоздайте его с помощью --bg.
Чтобы удалить одно отображение, повторите команду, которая его создала, добавив off в конце. Чтобы очистить все отображения serve и funnel на узле, используйте reset.
sudo tailscale funnel --https=443 3000 off
sudo tailscale serve resetЗапустите tailscale serve status еще раз после выполнения любой из этих команд и ознакомьтесь с результатом, вместо того чтобы предполагать, что система выполнила именно то, что вы ожидали.
Что вы получаете и чем жертвуете
Преимущества очевидны, и именно поэтому пользователи выбирают это решение вместо reverse proxy.
- Сертификат, которому доверяют браузеры, обновляется автоматически. Не нужно устанавливать ACME (automatic certificate management environment) клиент и следить за задачами по обновлению.
- Не нужно открывать входящие порты на firewall VPS.
tailscaledустанавливает исходящие соединения, поэтому настройки firewall по умолчанию (deny) на вашем VPS могут оставаться такими же строгими, как и раньше. - Не нужно покупать DNS-записи, настраивать их и ждать обновления.
- Не требуется проброс портов (port forwarding), что является ключевым моментом для машин за NAT (network address translation), а не для VPS с публичным IP.
Недостатки столь же реальны, и все они связаны с использованием funnel.
- Имя домена вам не принадлежит. Посетители видят
host.your-tailnet.ts.net. Funnel не поддерживает пользовательские домены, поэтому вы не сможете поставитьapp.example.comперед ним. - Путь трафика не под вашим контролем. Трафик сначала попадает на ретранслятор Tailscale, который проксирует поток на ваш узел через tailnet. Tailscale заявляет, что трафик funnel ограничен по пропускной способности, но эти лимиты не публикуются и не настраиваются, поэтому измерьте свою пропускную способность самостоятельно, прежде чем полагаться на конкретные показатели.
- Отсутствие инструментов управления. В reverse proxy, который вы запускаете сами, есть access logs, rate limits, ограничения на размер запроса и возможность настроить аутентификацию. Funnel предоставляет только URL. Всё остальное должно быть реализовано внутри вашего приложения.
- Список портов ограничен, как указано выше.
Обе функции зависят от инфраструктуры, управляемой Tailscale: выдача сертификатов для имени ts.net и сами ретрансляторы funnel. Если вы рассматриваете самостоятельно развернутый сервер управления Headscale, не стоит полагать, что эти функции будут доступны. Проверяйте примечания к выпуску (release notes) для той версии Headscale, которую вы планируете использовать.
Что выбрать?
Правило простое.
Используйте serve для любых внутренних ресурсов: административных панелей, дашбордов, интерфейсов метрик, которые не должны индексироваться, или тестовых копий сайтов. Участие в tailnet само по себе является механизмом контроля доступа, и весьма надежным. Устройство, не подключенное к tailnet, даже не сможет разрешить имя хоста.
Используйте funnel для демонстрационных ссылок, обработчиков вебхуков, на которые сторонние сервисы должны отправлять POST-запросы, или для OAuth callback в процессе разработки. Это самый быстрый способ получить публичный HTTPS URL, а одна команда off мгновенно его закрывает. Однако «публичный» означает именно публичный: имя хоста не является секретом, и funnel перед приложением без авторизации делает сервис открытым для всех. Всё, что находится за ним, должно самостоятельно проверять подлинность запросов с той же тщательностью, которая требуется для открытого API Ollama.
Используйте полноценный reverse proxy для всего, что вы считаете продуктовой средой. Ваш домен, ваш сертификат, ваши логи, ваши лимиты запросов и отсутствие посредников в пути прохождения трафика. В статье Сравнение nginx, Caddy и Traefik в качестве reverse proxy рассматриваются критерии выбора подходящего решения.
Режимы сбоев и соответствующие сообщения
Funnel не запускается. Funnel not available; "funnel" node attribute not set. указывает на проблему с политиками, а не с командой. Добавьте атрибут funnel в файл политик tailnet, сохраните его и повторите попытку.
Всё работало, но теперь tailscale serve status выдаёт No serve config. Отображение было создано в интерактивном режиме, и этот процесс завершился. Запустите ту же команду повторно с флагом --bg.
Имя разрешается, но ответа нет. Прокси-серверы Funnel перенаправляют запросы на указанный вами целевой объект, поэтому, если там никто не ожидает соединений, проксировать некуда. Проверьте это с помощью ss -ltnp | grep 3000 на той же машине, где запущен tailscaled. Частая причина заключается в том, что контейнер публикует порт на адресе Docker bridge вместо 127.0.0.1, из-за чего хост не видит слушающего процесса там, где вы его ожидали. В Принципы работы сети в Docker Compose описано, где именно оказываются опубликованные порты.
Ошибки сертификатов для имени ts.net. Вероятнее всего, HTTPS-сертификаты не включены для tailnet. Включите их в консоли администратора, а затем выполните этап получения сертификата отдельно, чтобы его ошибки не смешивались с выводом команды serve:
sudo tailscale cert your-host.your-tailnet.ts.netFunnel загружается через мобильную сеть, но работает иначе, чем с вашего ноутбука. Ваш ноутбук находится в tailnet, поэтому MagicDNS разрешает имя в адрес 100.x, и вы обращаетесь к сервису напрямую, не задействуя ретранслятор. Это корректное поведение, означающее, что ваш ноутбук не может проверить публичную доступность. Используйте curl с машины, которая не подключена к tailnet.
FAQ
В чем разница между tailscale serve и tailscale funnel?
Разница заключается в том, кто имеет доступ к результату. tailscale serve публикует локальный порт по HTTPS-адресу, доступному только устройствам в вашей tailnet. tailscale funnel публикует тот же порт по адресу, доступному любому пользователю в Интернете через ретрансляционные серверы (relay servers), управляемые Tailscale. Флаги и целевые объекты у них общие. Первая строка вывода сообщает, какой именно режим задействован: Available within your tailnet или Available on the internet.
Почему tailscale funnel сообщает, что атрибут узла не задан?
Потому что функция funnel отключена для tailnet, пока её кто-нибудь не активирует. Сообщение выглядит как Funnel not available; "funnel" node attribute not set. и поступает от вашего собственного клиента еще до обращения к ретранслятору. Добавьте запись nodeAttrs, предоставляющую атрибут funnel для autogroup:member (или для тега, если публиковать данные должна только одна машина), в файл политики tailnet в разделе Access Controls. Администратор tailnet может также перейти по URL для подтверждения, который выводит CLI.
Какие порты может использовать Tailscale Funnel?
Только 443, 8443 и 10000. По умолчанию используется 443, другой порт можно выбрать с помощью --https=8443 или --https=10000. Это ограничение ретрансляторов funnel, а не вашего сервера, поэтому изменение настроек брандмауэра или конфигурации на VPS его не снимет. У tailscale serve таких ограничений нет, так как трафик не покидает пределы вашей tailnet.
Сохраняется ли URL serve или funnel после перезагрузки?
Только если вы использовали --bg. Без него команда выполняется в интерактивном режиме (foreground), выводит Press Ctrl+C to exit., и при завершении процесса сопоставление исчезает. С флагом --bg сопоставление записывается в конфигурацию serve узла и восстанавливается вместе с tailscaled после перезагрузки. Проверить состояние можно командой tailscale serve status, которая выводит No serve config, если настройки отсутствуют.
Безопасно ли оставлять funnel запущенным?
Это безопасно с точки зрения транспорта: соединение защищено HTTPS, а порты на брандмауэре не открываются. Однако это небезопасно в обычном понимании, так как URL является публичным, а значит, и приложение за ним становится публичным. Оставляйте funnel включенным только перед сервисами, которые самостоятельно аутентифицируют запросы, и отключайте его после завершения демонстрации или тестирования вебхуков, используя команду, которой он был создан, с добавлением off в конце.
Источники информации о поведении команд: документация Tailscale Serve and Funnel и справочник CLI на сайте tailscale.com/docs.