Как настроить доступ к NAS через Tailscale без портов
Используйте Tailscale для доступа к домашнему серверу без проброса портов на роутере. Узнайте, как работает обход NAT, когда трафик идет через реле и почему это безопасно.
Нужен ли Tailscale проброс портов?
Tailscale не требует проброса портов; для доступа к собственным устройствам он полностью заменяет эту технологию. Каждое устройство в вашей tailnet (частной сети, которую Tailscale создает между вашими устройствами) устанавливает собственные исходящие соединения. Настройки домашнего маршрутизатора менять не нужно: не требуется ни проброс портов, ни хост в DMZ (демилитаризованной зоне), ни записи dynamic DNS, ни публичный IP-адрес. NAS (сетевое хранилище), Raspberry Pi или игровой сервер за маршрутизатором ipTIME или Fritz!Box становятся доступными с вашего ноутбука из любой точки мира по их частным адресам, при этом входящие порты маршрутизатора остаются закрытыми.
Список того, чего Tailscale не делает, также невелик. Tailscale соединяет только те устройства, которые авторизованы в вашей tailnet или были добавлены в неё через общий доступ. Посторонний пользователь из интернета или знакомый, не присоединившийся к сети, не сможет получить доступ к ресурсам через неё. Публикация сервиса для всего интернета — это другая задача, она рассматривается ближе к концу руководства.
Как Tailscale обходит NAT без проброса портов
Проброс портов существует из-за NAT (network address translation). Ваш маршрутизатор владеет одним публичным IPv4-адресом, а все устройства за ним — частными. Входящий пакет, приходящий на маршрутизатор, не содержит информации о том, какому частному устройству он предназначен, поэтому маршрутизатор отбрасывает его. Проброс порта — это правило, которое вручную задает соответствие: «порт 25565 принадлежит 192.168.0.20». Tailscale достигает того же результата без правил, выполняя четыре шага.
Во-первых, каждый узел инициирует исходящее соединение. При запуске tailscaled открывает HTTPS-соединение с сервером координации по TCP 443. Узел передает свой публичный ключ WireGuard и получает публичные ключи и адреса всех остальных узлов в tailnet. Сервер координации никогда не передает ваш трафик, только ключи и адресную книгу.
Во-вторых, каждый узел определяет, как он выглядит извне. Он отправляет STUN-запрос (session traversal utilities for NAT) по протоколу UDP на порт 3478 серверов ретрансляции Tailscale. Ответ содержит публичный IP-адрес и порт, которые маршрутизатор назначил этому исходящему пакету. Это именно то соответствие, которое создается при ручном пробросе портов, только здесь маршрутизатор создал его самостоятельно для исходящего потока. Если маршрутизатор поддерживает UPnP или NAT-PMP, Tailscale также автоматически запрашивает у него создание соответствия, что помогает, но работа системы от этого не зависит.
В-третьих, обе стороны выполняют «пробивку» (punching). Узел A и узел B узнают публичные конечные точки друг друга через сервер координации. Оба узла одновременно отправляют UDP-пакеты со своего слушающего порта (по умолчанию 41641) на публичную конечную точку другой стороны. В маршрутизаторе каждого узла уже существует исходящее соответствие для своего узла, поэтому пакет, приходящий с другой стороны, соответствует этому правилу и пропускается внутрь. С этого момента два узла общаются напрямую через WireGuard, при этом в маршрутизаторе по-прежнему нет никаких правил.
В-четвертых, если «пробивка» не удается, трафик передается через ретранслятор. CGNAT (carrier-grade NAT, где провайдер помещает вас за второй NAT, который он контролирует) и симметричный NAT (где маршрутизатор выбирает новый порт для каждого направления, из-за чего ответ STUN становится бесполезным) препятствуют выполнению третьего шага, как и корпоративный брандмауэр, блокирующий UDP. В этом случае Tailscale отправляет зашифрованные пакеты WireGuard через сервер DERP (designated encrypted relay for packets) по протоколу TCP 443. Ретранслятор видит только зашифрованные данные. Это также влияет на задержки и пропускную способность, а в статье почему ретранслируемое соединение Tailscale работает медленно и как добиться прямого подключения описано, как определить тип соединения и что можно изменить.
Ни один из этих четырех шагов не является входящим соединением на ваш маршрутизатор. Именно поэтому проброс портов не требуется.
Установка клиента и проверка пути
Установка состоит из одного скрипта и одного входа в систему на каждом устройстве.
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
tailscale ip -4tailscale up выводит URL для входа. Откройте его, авторизуйтесь, и устройство будет добавлено в tailnet. tailscale ip -4 выводит адрес устройства в tailnet из диапазона 100.64.0.0/10. Этот адрес остается неизменным после перезагрузок и смены сетей, поэтому именно его следует указывать в конфигурациях SSH и игровых клиентах.
Со второго устройства в tailnet проверьте путь к первому:
tailscale ping nasИспользуйте имя хоста или адрес в tailnet. Первый ответ часто содержит via DERP, так как прямой путь еще согласовывается. В течение нескольких секунд ответы должны смениться на публичный IP и порт, что означает успешное выполнение hole punch. Если ответы по-прежнему содержат via DERP спустя минуту, это означает, что одна из сторон находится за NAT, который не удалось преодолеть, и соединение осуществляется через ретранслятор.
Единственное правило брандмауэра, которое стоит добавить
Tailscale работает без изменения настроек брандмауэра в большинстве сетей, так как исходящий UDP-трафик обычно разрешен. Одно дополнительное правило повышает вероятность установления прямого соединения: разрешите UDP-порт 41641.
На домашнем роутере или корпоративном брандмауэре это означает разрешение исходящего UDP-трафика на порт 41641, а также на порт 3478 для STUN, если исходящий UDP хоть как-то ограничен. Большинство домашних роутеров уже разрешают это, поэтому делать ничего не нужно.
На VPS полезно настроить входящие соединения. У VPS есть публичный IP-адрес и нет NAT перед ним, поэтому входящее правило для UDP 41641 делает VPS легкодоступным для любого узла: попытка соединения от узла всегда будет успешной, даже если NAT самого узла работает в сложном режиме. При использовании ufw:
sudo ufw allow 41641/udp
sudo ufw statusufw status должен отображать 41641/udp как ALLOW из Anywhere. Провайдеры, которые используют отдельный сетевой брандмауэр в панели управления, требуют настройки такого же правила и там, так как пакет, заблокированный на границе сети провайдера, никогда не дойдет до ufw. Это правило — вопрос удобства, а не обязательное требование. Даже с закрытым портом VPS останется в tailnet, и узлы смогут подключаться к нему, хотя некоторые из них будут использовать ретранслятор вместо прямого соединения.
Доступ к домашнему NAS или Raspberry Pi извне
Первый сценарий — самый простой, и именно его большинство пользователей подразумевают под «пробросом портов с Tailscale»: получение доступа к домашнему устройству с ноутбука или телефона, находящегося вне дома.
Установите клиент на домашнее устройство и на ноутбук. Это вся настройка. Теперь NAS или Pi отвечает по своему адресу в tailnet для всех запущенных сервисов, при этом ничего пробрасывать не нужно:
ssh pi@100.101.102.103
curl -I http://100.101.102.103:8080/Замените адрес на вывод команды tailscale ip -4, выполненной на домашнем устройстве. Вход по SSH должен работать точно так же, как в домашней сети Wi-Fi, а curl -I должен вывести HTTP-статус любого веб-приложения, запущенного на устройстве. Поскольку соединение аутентифицируется ключами WireGuard, привязанными к авторизованному устройству, использование сервисов, которые были бы небезопасны при открытом порте (например, SMB-ресурсы или панели веб-администрирования), становится допустимым: только ваши собственные устройства могут отправить на них пакет. Маршрутизатор ipTIME или Fritz!Box не видит входящих соединений и не требует изменений. Если ваш провайдер использует CGNAT, это решение всё равно будет работать, так как домашнее устройство только инициирует исходящие соединения, а в худшем случае трафик пойдет через ретранслятор.
MagicDNS, включенный по умолчанию в новых tailnet, также присваивает каждому узлу имя, поэтому команда ssh pi@nas будет работать, как только ноутбук подключится к tailnet.
Когда устройство не поддерживает Tailscale: subnet router
Некоторые устройства не позволяют запустить клиент: принтеры, IP-камеры, старые NAS с закрытой операционной системой или Smart TV. Эту проблему решает subnet router. Одна машина в домашней сети, на которой можно запустить Tailscale (достаточно даже Raspberry Pi), анонсирует всю домашнюю подсеть, и другие устройства в tailnet направляют трафик в эту подсеть через неё.
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-tailscale.conf
sudo sysctl --system
sudo tailscale up --advertise-routes=192.168.0.0/24Используйте вашу реальную домашнюю подсеть. После этого маршрут необходимо одобрить в консоли администратора в настройках маршрутов устройства, а клиенты на Linux должны активировать его с помощью sudo tailscale set --accept-routes. После этого ping 192.168.0.50 с ноутбука будет достигать камеры дома. Параметр forwarding в sysctl обязателен, так как без него Pi будет отбрасывать все пакеты, адресованные не ему, и маршрут будет отображаться как одобренный, хотя устройства за ним не будут отвечать. Этап одобрения, активация на стороне клиента и другие причины, по которым маршрут может быть одобрен, но недоступен, описаны в запуске Tailscale subnet router. В руководстве используется VPS в качестве маршрутизатора, но всё описанное применимо и к Pi в вашей гостиной.
Предоставление друзьям доступа к серверу Minecraft без открытия портов на роутере
Второй случай: сервер Minecraft на домашнем ПК и друзья, которые хотят к нему подключиться. Старый способ — проброс порта TCP 25565 на роутере и передача друзьям вашего публичного IP-адреса, который при этом становится доступен всем сканерам в интернете. Tailscale заменяет это решение функцией совместного доступа (sharing).
Существует два варианта. Первый — пригласить друзей в ваш tailnet в качестве пользователей. Это работает, но количество мест для пользователей в бесплатном тарифе ограничено, к тому же это предоставляет им доступ ко всей вашей сети, что избыточно для игры. Второй и более предпочтительный вариант — совместный доступ к узлу (node sharing). В панели управления откройте страницу Machines, найдите игровой ПК, откройте его меню и выберите Share. Tailscale создаст ссылку-приглашение. Каждому другу потребуется собственный бесплатный аккаунт Tailscale, который сделает их владельцами их собственных небольших tailnet, и они примут ссылку из своих аккаунтов. После этого общий узел появится в их списке устройств, и только он один. Совместный доступ предоставляет получателю доступ только к этому узлу и ни к чему больше в вашем tailnet. Общий узел по умолчанию изолирован: он может отвечать на соединения из tailnet друга, но не может инициировать их самостоятельно.
Друзья добавляют сервер в Minecraft, используя его адрес в tailnet, 100.101.102.103:25565, или просто адрес, если порт стандартный. Игровой ПК работает без проброшенных портов, настройки роутера остаются нетронутыми. Общие узлы не анонсируют маршруты подсетей (subnet routes), поэтому совместный доступ подходит для сервисов, запущенных непосредственно на самом общем узле, что в точности соответствует случаю с игровым сервером.
Ограничение заключается в том, что каждый игрок должен установить Tailscale и принять приглашение. Для группы друзей это приемлемо. Для публичного сервера, к которому может присоединиться кто угодно, этот способ не подходит, и следующие два раздела предлагают решение.
Запуск игрового сервера на VPS с RCON в tailnet
Другой способ избежать проброса портов — отказаться от хостинга игры дома. У VPS есть публичный IP-адрес и отсутствует NAT, поэтому игровой порт открыт для всех без участия маршрутизатора. В руководстве Запуск сервера Minecraft на VPS описаны выбор конфигурации, флаги Java, резервное копирование и unit-файл systemd. В данном контексте важно то, какие именно порты смотрят в интернет.
Сервер Minecraft открывает два порта. TCP 25565 предназначен для игры, и он необходим игрокам. TCP 25575 — это RCON (удаленная консоль), которая принимает пароль и позволяет выполнять любые команды сервера, включая op и stop. RCON-порт, открытый в интернет, становится целью для подбора пароля. Добавьте VPS в свой tailnet и настройте для этих портов разные правила:
sudo ufw allow OpenSSH
sudo ufw allow 25565/tcp
sudo ufw allow in on tailscale0 to any port 25575 proto tcp
sudo ufw enable
sudo ufw statusВторое правило открывает доступ к игре для всех. Третье правило открывает RCON только для пакетов, поступающих через интерфейс tailscale0, что означает доступ только с устройств внутри вашего tailnet. Публичный IP-адрес по-прежнему отвечает на порту 25565, а попытки подключения к порту 25575 извне отбрасываются политикой по умолчанию в ufw. Проверьте оба варианта со своего ноутбука, который находится в tailnet:
nc -zv 100.101.102.103 25575
nc -zv <vps-public-ip> 25575Первая команда должна вывести succeeded. Вторая должна зависнуть, а затем выдать тайм-аут, так как пакет поступил через публичный интерфейс и не подошел ни под одно разрешающее правило. Тот же подход применим к SSH, веб-карте, базе данных или панели мониторинга: публичный порт на публичном IP, административные порты — только на tailscale0.
Публикация сервиса в интернете: Funnel или обратный туннель через VPS
Третий сценарий — это то, что Tailscale сам по себе не решает. Блог, публичный API, игровой сервер или страница статуса: посетители не входят в вашу tailnet и никогда не войдут. С этой задачей справляются два инструмента, и каждому из них посвящена отдельная статья.
Tailscale Funnel публикует HTTPS-сервис с узла в публичный интернет через реле Tailscale. Он работает только по протоколу TLS (transport layer security) и только на портах 443, 8443 и 10000, поэтому он подходит для веб-приложений, но не для игровых протоколов, работающих, например, на порту 25565. В Tailscale Serve против Funnel объясняется, что именно и для кого открывает каждый из этих инструментов.
Обратный туннель через VPS решает все остальные задачи. Домашний сервер открывает исходящий туннель к VPS с публичным IP-адресом, а VPS перенаправляет публичный порт обратно через этот туннель (TCP или UDP, на любом номере порта). Это подходящий инструмент для публичного сервера Minecraft, размещенного дома за CGNAT, и в обратном туннеле через VPS для домашнего сервера за CGNAT приведено пошаговое руководство. Выберите один из этих двух вариантов и прекратите искать в настройках Tailscale опцию для открытия порта во внешний мир. Её не существует.
Чего не делает Tailscale
- Он не перенаправляет порты для произвольных публичных клиентов. Пакет от пользователя вне tailnet никогда не достигнет вашего узла, так как для него нет ключа WireGuard, а пакет WireGuard без корректного ключа отбрасывается без ответа.
- Он не предоставляет публичного доступа. Пользователи должны быть участниками вашей tailnet или принять приглашение к общему узлу.
- Он не гарантирует прямое соединение. При работе через сложные NAT соединение передается через ретранслятор, что снижает скорость.
- Он не открывает порты на маршрутизаторе. Маршрутизатор остается закрытым, в этом и заключается смысл работы.
FAQ
Нужен ли Tailscale проброс портов?
Нет. Каждый узел Tailscale выполняет только исходящие соединения. Он обращается к координационному серверу по протоколу HTTPS через TCP 443 и определяет свой публичный адрес с помощью STUN через UDP 3478. Прямые соединения между узлами устанавливаются методом UDP hole punching на порту 41641. Если этот метод не срабатывает, трафик передается через ретранслятор DERP по протоколу TCP 443, что также является исходящим соединением. Домашнему роутеру не требуется проброс портов или настройка DMZ, а устройство, находящееся за CGNAT, подключается аналогичным образом.
Может ли Tailscale заменить проброс портов для сервера Minecraft?
Да, если сервер предназначен для игры с друзьями. Установите Tailscale на игровой ПК, предоставьте доступ к этой машине каждому другу через страницу Machines в панели администратора, и они смогут подключиться к его адресу в tailnet по порту 25565 без проброса портов. Это решение не заменяет проброс портов для публичного сервера, так как игроки вне вашего tailnet не смогут получить доступ к узлу. В таком случае разместите сервер на VPS с публичным IP, а RCON оставьте в tailnet, либо используйте обратный туннель с домашнего компьютера на VPS.
Какие порты использует Tailscale?
Три. Исходящий TCP 443 используется для связи с координационным сервером и передачи трафика через ретрансляторы DERP. Исходящий UDP 3478 используется для STUN, который определяет публичный адрес. UDP 41641 — это порт по умолчанию для прослушивания WireGuard при прямых соединениях; его можно изменить, если порт 41641 занят. Ни один из этих портов не требует открытия для входящих соединений. Разрешение входящего трафика по UDP 41641 на VPS является опциональным и позволяет чаще устанавливать прямые соединения между узлами.
Почему мое соединение Tailscale работает через ретранслятор, а не напрямую?
tailscale ping продолжает отвечать via DERP, если процедура UDP hole punching не может завершиться успешно. Основные причины — это NAT, который не пропускает пакеты (например, CGNAT или симметричный NAT, назначающий новый порт для каждого направления), либо файрвол, блокирующий исходящий UDP-трафик. Исправьте то, что находится под вашим контролем: разрешите исходящий UDP-трафик на портах 41641 и 3478 или разместите один из узлов на VPS с открытым входящим портом UDP 41641, чтобы у процесса установки соединения всегда была фиксированная цель.