Как работает NAT и почему два устройства не видят друг друга
Видеозвонок не устанавливается, игра пишет "не удалось подключиться к хосту", торрент годами висит на одной скорости, а проброшенный порт на роутере почему-то не работает — и всё это одна и та же причина: NAT. Он честно делает свою работу — экономит IPv4-адреса — но заодно ломает саму идею "два устройства подключаются друг к другу напрямую". Разберёмся, как он устроен внутри и почему без специальных фокусов входящее соединение снаружи до вашего компьютера просто не доходит.
Содержание
- Что такое NAT и какую проблему он решает
- Как работает трансляция: таблица NAT изнутри роутера
- Почему входящие соединения не работают без проброса порта
- Двойной NAT и CGNAT у провайдера: когда всё ещё хуже
- Как проверить свой публичный IP и понять, есть ли у вас CGNAT
- Почему два устройства за NAT не видят друг друга: STUN, TURN и hole punching
Что такое NAT и какую проблему он решает
NAT (Network Address Translation) — это подмена адресов на границе сети. У вас дома или в офисе десятки устройств с адресами из приватных диапазонов: 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12 (все три диапазона зарезервированы RFC 1918 именно под локальные сети и в интернете не маршрутизируются). А публичный IP, который провайдер выдал на роутер, обычно один. NAT — это механизм, который позволяет всем этим устройствам выходить в интернet через один-единственный публичный адрес.
Причина появления NAT прозаична: свободных адресов IPv4 давно не хватает на все устройства мира, и провайдеры вынуждены экономить их NAT'ом вместо того, чтобы выдавать по публичному адресу каждому абоненту. IPv6 с его огромным адресным пространством должен был снять проблему полностью, но на практике многие провайдеры, домашние роутеры и особенно мобильные сети продолжают использовать NAT — частично по инерции, частично потому что IPv6 всё ещё не везде доведён до полноценной сквозной маршрутизации.
Технически большинство домашних и офисных роутеров делают source NAT (SNAT) — подменяют исходящий адрес пакета. Есть и обратная задача — destination NAT (DNAT), когда входящий пакет, наоборот, перенаправляется с публичного адреса на адрес внутри сети (это то, что происходит при пробросе порта). Дальше в статье — в основном про SNAT, потому что именно он создаёт проблему "меня не видно снаружи".
Как работает трансляция: таблица NAT изнутри роутера
Возьмём конкретный пример. Ваш ноутбук с адресом 192.168.1.50 открывает соединение к серверу 93.184.216.34 на порт 443 (условный HTTPS). Пакет уходит с исходным адресом и портом 192.168.1.50:54321.
Роутер перехватывает этот пакет на выходе и делает подмену:
- Заменяет source IP
192.168.1.50на свой публичный адрес, например85.140.20.10. - Заменяет source port
54321на какой-то свободный порт из своего диапазона, например61000(порт может как совпасть с исходным, так и нет — зависит от того, свободен ли он на публичном адресе роутера). - Записывает соответствие в таблицу трансляций (NAT table):
192.168.1.50:54321 ⇄ 85.140.20.10:61000, вместе с адресом назначения и протоколом.
Сервер 93.184.216.34 видит входящий пакет от 85.140.20.10:61000 и понятия не имеет, что за этим адресом стоит ещё десяток устройств. Он отвечает на 85.140.20.10:61000 — и роутер, получив ответ, смотрит в таблицу трансляций, находит запись и переправляет пакет обратно на 192.168.1.50:54321.
Ключевой момент: запись в таблице появляется только тогда, когда исходящий пакет инициировал соединение изнутри. У записи есть таймаут — обычно от нескольких десятков секунд до нескольких минут для UDP и дольше для установленных TCP-сессий (конкретные значения различаются между производителями роутеров и провайдерским оборудованием, и часто их можно настроить). Если пакетов по этому направлению долго не было, запись удаляется — отсюда, кстати, известная особенность долгих SSH-сессий или VPN-туннелей "затыкаться" без keepalive: NAT просто забыл про соединение.
Разные типы NAT ведут себя по-разному в деталях этого сопоставления:
| Тип NAT | Как выбирается внешний порт | Кто может достучаться в ответ |
|---|---|---|
| Full cone | Один и тот же внешний порт для всех адресатов | Любой внешний хост, знающий IP:port |
| Restricted cone | Тот же порт, но принимает ответ только с IP, куда сами писали | Только тот IP, куда было исходящее соединение |
| Port-restricted cone | То же плюс проверка порта источника | Только тот же IP:port, куда писали |
| Symmetric | Для каждого адресата — новый внешний порт | Практически никто, кроме точного адресата исходного соединения |
Symmetric NAT — самый жёсткий вариант, и именно он чаще всего ломает P2P-технологии, о которых речь пойдёт дальше.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать VPSПочему входящие соединения не работают без проброса порта
Вот тут и кроется главная практическая проблема. Таблица трансляций в предыдущем разделе создаётся только в ответ на исходящий пакет. Если снаружи кто-то попробует написать первым — постучаться на 85.140.20.10:61000 без того, чтобы изнутри туда что-то посылали, — роутер просто не найдёт соответствующую запись в таблице и отбросит пакет. С точки зрения внешнего мира вашего устройства как будто не существует: нет ни одного адреса, по которому к нему можно обратиться напрямую.
Это не баг, а прямое следствие механики NAT: он умеет сопоставлять "было исходящее — жду ответ", но не умеет угадывать "кому из десяти устройств за NAT отправить этот незапрошенный входящий пакет". У него просто нет для этого информации.
Отсюда два стандартных способа всё же принимать входящие соединения:
Проброс порта (port forwarding). Вы вручную создаёте статическое правило в NAT-таблице роутера: "всё, что приходит на публичный 85.140.20.10:22, всегда отправлять на 192.168.1.50:22", независимо от того, было ли исходящее соединение. Это классика для домашнего сервера, IP-камеры, игрового сервера или, например, для того, чтобы поднять свой VPN-сервер за домашним NAT — мы подробно разбирали это в статье про проброс портов для VPN-сервера за NAT. Здесь же полезно свериться, какие порты вообще открыты на устройстве, прежде чем что-то пробрасывать наружу.
UPnP / NAT-PMP. Приложение само просит роутер открыть проброс на время своей работы — это то, что делают многие торрент-клиенты и игровые консоли, чтобы не заставлять пользователя лезть в настройки роутера руками. Работает удобно, но требует, чтобы UPnP был включён на роутере (часто он отключён из соображений безопасности — незнакомое приложение в сети теоретически тоже может попросить открыть порт).
Оба способа объединяет одно: они требуют контроля над NAT-устройством. А вот если NAT стоит не у вас дома, а у провайдера — контроля у вас нет вообще, и это следующая, более неприятная история.
Двойной NAT и CGNAT у провайдера: когда всё ещё хуже
Домашний NAT — это один уровень трансляции. Но у мобильных операторов и у многих провайдеров фиксированного интернета (особенно там, где не хватает выделяемых блоков IPv4) есть ещё один уровень выше — CGNAT (Carrier-Grade NAT). Провайдер выдаёт вашему домашнему роутеру не публичный, а тоже приватный адрес — обычно из специально зарезервированного под это диапазона 100.64.0.0/10 (RFC 6598), — и уже сам провайдер на своём оборудовании транслирует тысячи таких абонентских адресов в небольшое количество реальных публичных IP.
Получается двойной NAT: ваше устройство → домашний роутер (NAT №1) → оборудование провайдера (NAT №2, он же CGNAT) → интернет. И тут начинаются настоящие проблемы:
- Проброс порта на домашнем роутере перестаёт работать сам по себе. Правило "снаружи на 22-й порт — на мой сервер" бесполезно, потому что снаружи для вашего роутера — это CGNAT провайдера, а не настоящий интернет. Чтобы всё заработало, провайдер должен ещё и на своей стороне пробросить порт с *его* публичного адреса на ваш адрес в CGNAT-диапазоне — а это почти никогда не делается по умолчанию для массовых тарифов.
- Один публичный IP провайдера обслуживает сотни или тысячи абонентов одновременно. Если кто-то из них шлёт спам или ломится куда-то с этого же адреса, под блокировку рискует попасть весь пул — и вы вместе с ним, хотя лично не при чём.
- Диагностика усложняется: сайт, определяющий ваш IP, покажет адрес CGNAT-узла провайдера, а не что-то, что реально принадлежит вам, и этот адрес может периодически меняться между сессиями.
Практическое следствие для тех, кому нужен именно входящий доступ снаружи (свой VPN-сервер, игровой сервер, удалённое видеонаблюдение, приём вебхуков): проброс портов через CGNAT в подавляющем большинстве случаев физически не работает, и никакие настройки домашнего роутера этого не изменят. Здесь два рабочих пути: либо просить провайдера выделить отдельный публичный (часто платно и не для всех тарифов доступно), либо перенести сервис на VPS с изначально белым, выделенным IP-адресом — тогда проблема CGNAT просто не возникает, потому что сервер стоит не за вашим домашним интернетом, а в дата-центре с прямой публичной адресацией.
Как проверить свой публичный IP и понять, есть ли у вас CGNAT
Проверка занимает пару минут и не требует специальных инструментов.
Шаг 1. Узнайте, какой публичный IP видит интернет. Откройте в браузере любой из сервисов:
https://ifconfig.me
https://ipinfo.io/ip
https://whatismyipaddress.com
Это и есть адрес, с которым ваш трафик выходит наружу с точки зрения внешних серверов.
Шаг 2. Посмотрите, какой WAN-адрес видит сам роутер. Зайдите в веб-интерфейс роутера (обычно 192.168.0.1 или 192.168.1.1, данные для входа — на наклейке на корпусе или в документации от провайдера) и найдите раздел статуса интернет-соединения / WAN. Там будет показан адрес, который роутер получил от провайдера по DHCP или PPPoE.
Шаг 3. Сравните два адреса.
- Если адрес из шага 1 совпадает с адресом из шага 2 — у вас настоящий публичный IP, NAT только один (домашний), и проброс портов должен работать штатно.
- Если адреса разные — вы за CGNAT или за дополнительным уровнем NAT провайдера. Отдельный явный признак: если адрес на WAN-интерфейсе роутера попадает в диапазон
100.64.0.0–100.127.255.255— это стопроцентный CGNAT-адрес по стандарту RFC 6598, и провайдер сознательно не выдаёт вам публичную адресацию.
Полезно также свериться, как проверить IP после туннеля, если вы уже используете VPN или прокси — методика та же самая, просто сравнивать нужно то, что видит сайт, с тем адресом, который действительно должен быть виден с той стороны, куда вы подключаетесь.
Ещё один способ проверки: поднять простейший тестовый сервис на внешнем хосте и попробовать достучаться до своего домашнего IP на нестандартный порт. Если снаружи открыть соединение не получается даже при настроенном пробросе — это ещё одно подтверждение CGNAT или блокировки входящих у провайдера.
Почему два устройства за NAT не видят друг друга: STUN, TURN и hole punching
Теперь главный практический вопрос: если оба собеседника сидят каждый за своим NAT (а иногда ещё и за CGNAT), как вообще работают видеозвонки, P2P-игры и файлообмен напрямую между двумя пользователями — ведь ни один из них не может первым принять входящее соединение?
Ответ — набор технологий, объединённых в протокол ICE (Interactive Connectivity Establishment), который используется, в частности, в WebRTC (то, на чём построены Google Meet, WhatsApp-звонки в браузере и многие другие видеозвонки):
STUN (Session Traversal Utilities for NAT). Устройство обращается к STUN-серверу в интернете и спрашивает: "как ты меня видишь снаружи?" STUN-сервер отвечает публичным IP:port, под которым пришёл запрос — то есть тем самым отображением, которое NAT создал в своей таблице трансляций. Оба участника звонка узнают свои "внешние" адреса и обмениваются ими через сигнальный сервер (например, через сервер самого видеозвонка — по обычному, не P2P каналу).
Hole punching. Зная внешний IP:port друг друга, оба устройства одновременно отправляют пакеты друг другу напрямую. Момент важен: у каждого локальный NAT видит исходящий пакет к внешнему адресу собеседника и создаёт (или уже имеет) соответствующую запись в таблице трансляций — а значит, ответный пакет от собеседника пройдёт через NAT как "ожидаемый ответ на исходящее соединение", хотя по факту это независимая инициация с другой стороны. Оба NAT как бы "пробивают" друг другу дырку одновременно, отсюда и название.
Работает это надёжно для full cone и обычно неплохо для restricted/port-restricted cone NAT. А вот с symmetric NAT (см. таблицу в начале статьи) hole punching обычно не работает: внешний порт там разный для каждого адресата, поэтому тот IP:port, который STUN-сервер увидел в своём соединении, будет другим, чем тот, что понадобится для прямого соединения со вторым устройством, — NAT просто не создаст под него подходящую запись.
TURN (Traversal Using Relays around NAT) — запасной вариант на случай, если hole punching не удался (например, оба участника за symmetric NAT, что типично как раз для мобильных сетей и CGNAT). TURN-сервер работает как ретранслятор: оба устройства устанавливают к нему обычное исходящее соединение (это работает всегда), и весь трафик идёт через сервер туда-обратно. Минус очевиден — это уже не прямое P2P, а прокси через третью точку, что добавляет задержку и нагружает канал самого TURN-сервера трафиком обоих участников.
На практике сервисы видеозвонков и P2P-приложений сначала пробуют STUN + hole punching и только если это не удаётся за разумное время — откатываются на TURN. Поэтому качественные видеозвоночные сервисы держат целый парк TURN-серверов по миру: без них часть звонков между пользователями за жёстким NAT попросту не устанавливалась бы. Игровые платформы часто решают ту же проблему иначе — матчмейкингом через выделенный сервер вместо прямого P2P между игроками: сервер стоит на публичном IP, и оба игрока просто открывают к нему обычные исходящие соединения, которые проходят через любой NAT без hole punching.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать VPSНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
NAT — это то же самое, что файрвол?
Нет, хотя эффект похож. NAT транслирует адреса и как побочный эффект блокирует неожиданные входящие соединения, потому что для них просто нет записи в таблице трансляций. Файрвол — отдельный механизм, который целенаправленно разрешает или запрещает трафик по правилам, и он может стоять как до, так и после NAT, независимо от него.
Пробросил порт на роутере, но всё равно не работает — почему?
Частые причины: вы за CGNAT (проброс на домашнем роутере тогда бесполезен без проброса и на стороне провайдера), правило указывает не на тот локальный IP (он мог поменяться без статической привязки), или файрвол на самом устройстве блокирует вход уже после того, как NAT его пропустил.
IPv6 решает проблему NAT?
В теории да — при полноценной сквозной IPv6-адресации у каждого устройства есть собственный публичный адрес и NAT для трансляции не нужен в принципе. На практике многие провайдеры либо не выдают IPv6 вовсе, либо выдают его вместе с собственным файрволом по умолчанию, который всё равно блокирует нежданные входящие, — так что реального устранения проблемы это часто не даёт, разве что снимает вопрос "закончились адреса".
Почему на VPS с NAT-то же самое не происходит?
Потому что у VPS обычно с самого начала белый публичный IP без всякого NAT — трафик к серверу идёт напрямую, любой входящий порт, который вы открыли в файрволе, доступен снаружи сразу, без проброса, hole punching и прочих обходных манёвров.
Можно ли постоянно держать проброс порта на домашнем роутере вместо аренды сервера?
Технически да, если провайдер не использует CGNAT, но у этого подхода есть свои минусы: домашний IP обычно динамический (меняется при перезагрузке роутера), домашний канал не рассчитан на постоянную сетевую нагрузку и открытие портов на бытовом роутере на постоянку — дополнительный вектор атаки на домашнюю сеть.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →