Двойной NAT у клиента: почему сервис работает у всех, кроме одного человека
Тикет от одного-единственного клиента: видеозвонок у него не устанавливается, картинка виснет через десять секунд, а иногда просто "connecting..." до бесконечности. У остальных пользователей того же сервиса всё в порядке — жалоб больше нет ни от кого. Первая мысль обычно про сервер: слушать логи, смотреть на нагрузку, подозревать регион. Но если проблема стабильно воспроизводится у одного человека и стабильно отсутствует у сотен других, сервер почти наверняка ни при чём — дело в сети на стороне этого конкретного клиента, и очень часто конкретно в двойном NAT.
Содержание
Почему стоит подозревать NAT именно на стороне клиента
Логика простая: если бы дело было в сервере, ломалось бы у всех примерно одинаково или хотя бы у заметной доли пользователей. Если ломается ровно у одного — переменная, которая отличает его от остальных, находится где-то между его устройством и вашим сервером, и чаще всего это ближайший к нему участок сети — домашний роутер, оборудование мобильного оператора или корпоративный интернет.
NAT (Network Address Translation) — механизм, который подменяет адреса на границе сети, чтобы много устройств могло выходить в интернет через один публичный IP: подробно, с таблицей трансляций и разбором типов NAT, это разобрано в статье про то, как работает NAT и почему устройства не видят друг друга. Здесь важно другое: NAT создаёт запись в своей таблице только в ответ на исходящий пакет, и обычный веб-сёрфинг, чтение почты, запросы к REST API — всё это укладывается в схему "клиент сам инициировал соединение, сервер ответил" и через NAT проходит без проблем, даже если уровней трансляции несколько. А вот P2P-звонок, где оба участника должны в какой-то момент "достучаться" друг до друга напрямую, требует куда более капризной механики — и именно она в двойном NAT чаще всего и ломается.
Двойной NAT: два уровня трансляции вместо одного
Двойной NAT — это когда пакет от устройства клиента проходит не одну, а две (иногда больше) трансляции адреса подряд, прежде чем попасть в интернет. Типичная схема для дома или small office: провайдер выдаёт роутеру не совсем прямой публичный адрес, а роутер провайдера (модем в режиме моста-не-моста, ONT с встроенным NAT, или отдельный "роутер провайдера") уже сам делает NAT наружу, а домашний Wi-Fi-роутер клиента, подключённый к нему, делает NAT ещё раз для своей локальной сети.
Получается цепочка: устройство клиента (192.168.1.x) → домашний роутер (NAT №1, часто тоже приватный адрес вида 192.168.0.x на WAN-порту) → роутер/оборудование провайдера (NAT №2, вот тут уже настоящий публичный IP) → интернет. Каждый уровень трансляции — это отдельная таблица соответствий, отдельный набор таймаутов и отдельная логика выбора внешнего порта. С точки зрения любого стороннего сервера всё это выглядит как один-единственный публичный IP, и никакой намёк на то, что за ним прячется не один, а два вложенных NAT, снаружи не виден.
Частая причина такой схемы — пользователь сам не отключил NAT на оборудовании провайдера, когда подключал собственный роутер: провайдерский модем в режиме роутера плюс домашний Wi-Fi-роутер, оба со включённым DHCP и NAT, — классика, которая объясняет львиную долю "у клиента почему-то не работает то, что работает у всех остальных". Иногда добавляется третий уровень: гостевой Wi-Fi с изоляцией клиентов, VPN-клиент самого пользователя, корпоративный прокси — каждый добавляет свою трансляцию или свои ограничения поверх уже имеющихся.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверCGNAT: с точки зрения пользователя — тот же двойной NAT
Отдельный и сегодня, пожалуй, более распространённый случай — CGNAT (Carrier-Grade NAT), когда дополнительный уровень трансляции стоит не на домашнем оборудовании, а на стороне самого провайдера или мобильного оператора. IPv4-адресов физически не хватает на всех абонентов, и оператор транслирует адреса тысяч клиентов в существенно меньшее число реальных публичных IP уже на своём собственном оборудовании — это тот же принцип, что домашний NAT, просто на порядок выше по масштабу.
Технически это выглядит так: устройству или домашнему роутеру клиента выдаётся не публичный, а приватный адрес — обычно из специально зарезервированного под это диапазона 100.64.0.0/10 (RFC 6598), не пересекающегося с обычными 192.168.0.0/16 или 10.0.0.0/8, — и уже сам оператор на своём узле транслирует этот адрес в реальный публичный. Мобильные операторы почти поголовно работают именно так уже много лет; часть провайдеров фиксированного интернета — там, где своих блоков IPv4 на всех абонентов физически не хватает, — тоже переходит на CGNAT, и по состоянию на 2026 год эта практика скорее расширяется, чем сокращается.
Разница между "просто домашним NAT" и CGNAT в первую очередь в контроле: домашний NAT настраивает сам пользователь на своём роутере, а CGNAT полностью находится на стороне оператора — клиент не может залезть в его настройки, изменить таймауты трансляции или тем более попросить статический проброс порта в общем случае. А если у клиента ещё и свой домашний роутер стоит перед этим CGNAT (то есть он сам делает NAT для своей домашней сети, а оператор поверх этого делает CGNAT), получается уже тройной NAT — и вероятность проблем с P2P растёт кратно.
Почему это ломает именно P2P, VoIP и WebRTC
Обычный клиент-серверный трафик (HTTP-запрос, загрузка страницы, API-вызов) под двойным NAT работает почти всегда нормально: соединение инициирует клиент, оно проходит наружу через оба уровня трансляции, сервер отвечает, оба NAT видят "ожидаемый ответ" и пропускают пакет обратно. Проблемы начинаются там, где нужна одна из двух вещей: входящее соединение снаружи или прямое P2P-соединение между двумя клиентами, каждый из которых сидит за собственным NAT.
Несколько конкретных механизмов, которые двойной NAT и CGNAT ломают или делают непредсказуемыми:
- Истощение и нехватка портов. У NAT ограниченный диапазон внешних портов на один публичный IP, а под CGNAT провайдер часто дополнительно ограничивает число одновременных трансляций на абонента — точное число у каждого оператора своё и обычно нигде не публикуется. У активного пользователя с десятком фоновых приложений, каждое из которых держит свои TCP/UDP-сессии, лимит может исчерпываться, и новые соединения (в том числе то самое видеосоединение) начинают получать отказ или зависать в ожидании свободного порта.
- Непредсказуемое поведение хеша соединений на промежуточных узлах. Двойная трансляция означает, что исходный
IP:portклиента дважды переписывается прежде, чем пакет попадёт наружу, и на каждом уровне может использоваться свой алгоритм выбора внешнего порта. Это ломает предположения некоторых приложений о "стабильности" внешнего адреса на время сессии, а на CGNAT-узлах с балансировкой нагрузки один и тот же клиент в разные моменты времени может обслуживаться разными физическими узлами трансляции — из-за чего время жизни NAT-записи и сама привязка адреса ведут себя не так, как на домашнем роутере с одной таблицей. - Проблемы STUN/TURN у WebRTC. WebRTC для установления P2P-соединения полагается на протокол ICE: STUN-сервер сообщает клиенту, какой у него внешний
IP:portвиден снаружи, оба участника обмениваются этими адресами и пытаются "пробить" (hole punching) прямое соединение друг к другу. При двойном NAT STUN-запрос проходит оба уровня трансляции, и клиент узнаёт внешнийIP:portвторого, самого дальнего NAT — но сам он физически находится ещё и за первым NAT, о существовании которого STUN-сервер даже не подозревает. Если хотя бы один из уровней ведёт себя как symmetric NAT (для каждого адресата новый внешний порт), адрес, который увидел STUN, окажется бесполезен для прямого соединения со вторым участником звонка — и hole punching просто не сработает. - Полная невозможность входящих соединений без участия оператора. Проброс порта на домашнем роутере клиента бессмысленен, если следующий уровень — CGNAT: правило "снаружи на такой-то порт — на такой-то локальный адрес" работает только в пределах одного уровня NAT, а второй, за которым и находится настоящий публичный IP, клиенту недоступен вообще никак.
Как диагностировать со стороны поддержки
Диагностика двойного NAT и CGNAT со стороны службы поддержки или самого пользователя занимает несколько минут и не требует доступа к оборудованию оператора.
Шаг 1. Сравните внешний IP, который видит интернет, с тем, что видит роутер клиента. Попросите пользователя открыть в браузере два-три независимых сервиса:
https://ifconfig.me
https://ipinfo.io/ip
https://whatismyipaddress.com
Дальше — зайти в веб-интерфейс своего роутера (обычно 192.168.0.1 или 192.168.1.1) и посмотреть, какой адрес роутер получил от провайдера на WAN-интерфейсе. Если этот адрес совпадает с тем, что показали сайты — NAT у клиента только один, домашний, и P2P-проблемы стоит искать в другом месте. Если адреса разные — это прямой признак дополнительного уровня трансляции на стороне провайдера. Отдельный явный маркер: если адрес на WAN-интерфейсе роутера попадает в диапазон 100.64.0.0 – 100.127.255.255 — это стопроцентный CGNAT-адрес по RFC 6598, провайдер сознательно не выдаёт публичную адресацию.
Шаг 2. Traceroute с несколькими приватными адресами на разных хопах. Попросите клиента выполнить трассировку до вашего сервера:
# Windows
tracert ваш-сервер.example.com
# macOS / Linux
traceroute ваш-сервер.example.com
В обычном случае с одним домашним NAT первый хоп — это локальный роутер (192.168.x.1 или похожий), а дальше сразу идут публичные адреса сети провайдера. Если в трассировке видно два и более хопа подряд с приватными или CGNAT-адресами (192.168.x.x, 10.x.x.x, 100.64.x.x–100.127.x.x) прежде чем появится первый по-настоящему публичный адрес — это прямое подтверждение нескольких уровней NAT на пути. Это не то же самое, что рост числа хопов через VPN-туннель (тот случай подробно разобран в статье про чтение traceroute и ping через VPN) — там дополнительные хопы объясняются самим туннелем, а не вложенным NAT, и различить эти две причины как раз и помогает то, публичные это адреса или приватные.
Шаг 3. Проверьте на другой сети. Попросите повторить тот же тест звонка на мобильных данных вместо домашнего Wi-Fi (либо наоборот). Если на другой сети всё работает — причина именно в конкретной сети клиента, а не в его устройстве, приложении или аккаунте.
Шаг 4. Спросите провайдера. У некоторых операторов CGNAT можно отключить или получить статический публичный IP за отдельную плату — это стоит уточнить, если сценарий клиента регулярно требует стабильного P2P.
Что делать: TURN-relay и отказ от расчёта на проброс портов
Когда причина подтверждена, у стороны, которая эксплуатирует P2P-сервис (видеозвонки, игровой матчмейкинг, любое приложение с WebRTC), реальных рычагов повлиять на сеть клиента нет — и рассчитывать на то, что клиент сам себе что-то настроит, не стоит.
- Держите TURN-сервер как обязательный fallback, а не опциональную роскошь. Если STUN и hole punching не сработали за разумное время, соединение должно автоматически откатываться на TURN-relay — сервер, через который весь трафик звонка идёт как обычное исходящее соединение с обеих сторон, что проходит через любое число уровней NAT одинаково надёжно. Минус — дополнительная задержка и нагрузка на TURN-сервер трафиком обоих участников, но без него часть звонков с клиентами за двойным NAT или CGNAT просто не устанавливается в принципе.
- Никогда не проектируйте сценарий, который требует проброса порта именно на стороне клиента. Это работает у части технически подкованных пользователей с одним уровнем NAT, но полностью недоступно клиентам за CGNAT и ненадёжно даже для домашнего NAT с динамическим IP. Симметрично: если вы сами разворачиваете сервер за домашним NAT и полагаетесь на проброс порта, у вас точно такая же уязвимость — этот сценарий подробно разобран в статье про проброс портов для VPN-сервера за NAT.
- Ограничивайте число одновременных UDP/TCP-сессий на клиента внутри своего приложения, если это в вашей власти. Двойной NAT и CGNAT сами по себе имеют ограниченный бюджет портов на абонента, и приложение, которое неэкономно открывает лишние параллельные соединения, приближает клиента к этому потолку быстрее — похожий сценарий, когда один клиент исчерпывает лимиты общей NAT-таблицы на шлюзе, разобран в статье про потолок NAT и ёмкость на одного клиента, хотя там речь про сторону сервера — механика исчерпания портов одинакова с обеих сторон.
- Не обещайте клиенту, что "мы починим со своей стороны". Если корень проблемы — сеть провайдера клиента, реалистичные варианты только два: TURN-relay в приложении (в вашей власти) или клиент сам договаривается с оператором об отключении CGNAT (не в вашей власти). Честно объяснить это в ответе на тикет обычно снимает вопрос быстрее, чем бесконечные попытки "ещё раз перепроверить настройки сервера".
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Как отличить двойной NAT от обычной нестабильности домашнего интернета?
По traceroute и по повторяемости: если проблема воспроизводится стабильно именно на P2P-функциях (звонки, игры, WebRTC), а обычный веб-сёрфинг и загрузка файлов работают нормально — это специфический паттерн NAT, а не общая нестабильность канала. Общая нестабильность обычно ломает вообще всё, включая простую загрузку страниц.
Может ли VPN на стороне клиента решить проблему двойного NAT?
Иногда да, но не как надёжное системное решение — результат зависит от конкретного VPN-провайдера и того, даёт ли он клиенту фактически один уровень NAT вместо двух. Полагаться на это как на решение для всех пользователей нельзя, это в лучшем случае обходной путь для отдельного технически подкованного человека.
Стоит ли просить клиента отключить NAT на роутере провайдера и оставить только домашний?
Если провайдер это разрешает (перевод оборудования в режим моста, bridge mode) — да, это снимает один уровень трансляции и часто решает проблему полностью, если второй уровень был именно домашним NAT, а не CGNAT оператора. Если провайдер использует CGNAT, отключение домашнего NAT ничего не даст — второй уровень всё равно останется на стороне оператора и клиенту недоступен.
CGNAT — это всегда двойной NAT для конкретного пользователя?
Почти всегда да, если у пользователя есть собственный домашний роутер: роутер делает NAT для локальной сети (NAT №1), а провайдер поверх этого делает CGNAT (NAT №2). Исключение — устройство подключено к сети оператора напрямую, без промежуточного домашнего роутера (например, отдельный модем в режиме моста без своего NAT, или мобильный телефон в мобильной сети без Wi-Fi-роутера между ним и оператором) — тогда с точки зрения устройства это только один уровень трансляции, просто он принадлежит оператору, а не пользователю.
Почему у одного клиента с CGNAT звонки работают, а у другого с тем же CGNAT — нет?
Поведение CGNAT зависит от текущей загруженности конкретного узла трансляции у оператора, от того, symmetric или cone NAT используется на этом узле, и от того, сколько сессий уже открыто у абонента в моменте. Два клиента одного оператора физически могут обслуживаться разными узлами CGNAT с разной конфигурацией, поэтому одинаковый тип подключения не гарантирует одинаковое поведение.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →