Learning Platform
Глоссарий Troubleshooting
Урок 07.03 · 19 мин
Начальный
NATPort MappingHole PunchingCGNATPAT

NAT — как ваш домашний роутер прячет 50 устройств за одним IP

В вашем доме могут быть 30+ устройств с интернетом: ноутбук, телефон, планшет, умные лампочки, телевизор, робот-пылесос. У каждого свой IP-адрес вида 192.168.X.X. А ваш провайдер выдал вам один публичный IP. Как все они одновременно ходят в интернет, и сайты их различают?

Ответ: NAT (Network Address Translation). Ваш роутер переписывает заголовки уходящих пакетов так, что для внешнего мира они все выглядят как идущие от одного публичного IP. Когда ответ возвращается — роутер по своей таблице определяет, какому именно устройству он принадлежит.

В этом уроке разберём, как именно работает NAT, чем отличаются типы (full cone, restricted, symmetric), что такое port mapping, как работает hole punching для WebRTC и P2P-приложений. NAT — это hack, который спас IPv4 от смерти в 1990-х, но он усложнил многое: его особенности влияют на работу видеозвонков, файловых обменов, игровых серверов.

Bridge network и публикация портов

Зачем NAT появился

К середине 1990-х стало ясно: IPv4-адресов не хватит на всех. Спроектировали IPv6 (1995), но внедрение шло медленно. Нужно было «дотянуть» IPv4. Решение — NAT.

Идея: вместо того, чтобы каждое устройство имело публичный IP, дать им приватные IP (10/8, 172.16/12, 192.168/16) и сделать один публичный IP на всю организацию. Роутер на границе переписывает заголовки пакетов.

NAT -- один IP скрывает много устройств
Laptop192.168.1.42 -- приватный IP. Никогда не виден в интернете
Phone192.168.1.43 -- приватный
TV192.168.1.44 -- приватный
NAT routerВнутри -- видит приватные IP. На выходе -- использует свой публичный IP 87.123.45.6. Хранит таблицу 'кому что'
Public IP87.123.45.6 -- единственный публичный. Все запросы из дома выглядят как от него для внешнего мира
InternetВнешние серверы не знают про 50 устройств за NAT. Видят только публичный IP

Что NAT делает с пакетом:

  1. Уходящий пакет от ноутбука: src 192.168.1.42:54321, dst 140.82.121.4:443.
  2. NAT-роутер видит — src приватный, нужно переписать. Выбирает свой публичный src port (например, 61000). Запоминает в таблице: (внутр 192.168.1.42:54321) <-> (внеш 87.123.45.6:61000) -> (140.82.121.4:443).
  3. Меняет src в пакете на 87.123.45.6:61000. Отправляет в интернет.
  4. Сервер отвечает на 87.123.45.6:61000 (свой src + dst NAT’a).
  5. NAT-роутер видит пакет с dst 87.123.45.6:61000. По таблице узнаёт — это для 192.168.1.42:54321. Переписывает dst, отправляет внутрь.

Это PAT (Port Address Translation) или NAPT (Network Address Port Translation) — по сути NAT, мультиплексирующий по портам. То что обычно называют просто «NAT» в домашних роутерах — именно PAT.


Типы NAT

Когда говорят о «типах NAT», обычно имеют в виду как роутер обращается с входящими пакетами. Это влияет на возможность принимать соединения извне (важно для VoIP, P2P, игр).

1. Full Cone NAT. Самый простой и открытый.

  • Любой внешний хост может слать пакеты на (публ IP, мапнутый порт).
  • NAT принимает и форвардит внутрь по таблице.
  • Используется в старых домашних роутерах. Лучший для P2P.

2. Restricted Cone NAT.

  • Внешний хост может слать только если внутренний хост уже что-то ему отправлял.
  • Фильтрация по src IP внешнего хоста.

3. Port-Restricted Cone NAT.

  • То же что Restricted, но проверяется и src port.
  • Чуть более строгий.

4. Symmetric NAT. Самый строгий.

  • Для каждого внешнего (dst IP, dst port) NAT использует разный внешний src port.
  • Внешние хосты могут отвечать только на тот же IP:port, который они получили.
  • Делает P2P и hole punching сложным — два узла не могут согласовать порт.
Типы NAT -- от открытого к строгому
Full ConeВнутренний (A:p_int) всегда мапится на (NAT:p_ext). Любой внешний может писать на p_ext
Restricted ConeВнешний B может писать на p_ext только если внутренний A уже отправлял на B (любой port B)
Port-RestrictedТо же, но проверяется и port. B:p_b может слать на p_ext только если A слал на B:p_b
SymmetricДля разных (B, p_b) NAT использует разные p_ext. Внешний мир видит разные порты. P2P невозможен

Современные домашние роутеры обычно делают что-то между Cone и Symmetric. Иногда называют «open NAT», «moderate NAT», «strict NAT» (в игровых консолях).

Узнать свой тип NAT можно через STUN-сервер (RFC 5389) или специальные онлайн-сервисы.


Port forwarding — проброс порта

Что если вы хотите запустить домашний сервер (Minecraft, домашняя камера, личный сайт)? Извне на ваш публичный IP никто не достучится — NAT не пропускает входящие соединения, для которых нет записи в таблице.

Решение — port forwarding: вручную прописать в NAT-таблице «входящие на public IP:8080 -> 192.168.1.100:80». Теперь когда кто-то снаружи стучится на 87.123.45.6:8080, NAT перенаправляет на ваш домашний сервер.

# Пример настройки на Linux (iptables):
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80
iptables -t nat -A POSTROUTING -p tcp -d 192.168.1.100 --dport 80 -j MASQUERADE

# В домашних роутерах есть UI -- Settings -> Port Forwarding:
# External port | Internal IP   | Internal port | Protocol
# 8080          | 192.168.1.100 | 80            | TCP

Минусы:

  • Нужно вручную настроить.
  • Работает только если у вас публичный IP. Не работает за CGNAT (вы не можете «открыть» порт чужого NAT’a провайдера).

UPnP / NAT-PMP / PCP — автоматические протоколы, по которым приложение само просит роутер пробросить порт. Скайп, BitTorrent, игры используют это. Если в роутере включён UPnP, программы получают порты автоматически.

# Узнать, поддерживает ли роутер UPnP:
upnpc -l   # покажет статус UPnP

# Пробросить порт через UPnP:
upnpc -a 192.168.1.100 80 8080 tcp

Hole punching — P2P через два NAT

Что если два устройства за разными NAT хотят соединиться напрямую (без сервера-посредника)? Например, видеозвонок WebRTC между A и B, оба дома.

Прямое соединение невозможно: ни A, ни B не могут принимать входящие connection’ы (NAT блокирует). Решение — NAT hole punching.

Hole punching -- два NAT, прямое P2P
A behind NATДома за NAT 1. Хочет говорить с B напрямую
STUN serverСервер где-то в интернете. Помогает узнать публичный IP/port. Не передаёт данные
B behind NATДома за NAT 2. Тоже хочет с A
1. A -> STUNA шлёт UDP на STUN. STUN видит src = (NAT 1 public IP, port X). Возвращает 'ты выглядишь как X'
A знает свой ext IP(NAT1 IP:X). Этот port открыт в NAT1 для STUN'а, но он 'cone' и для всех желающих
2. B -> STUNТо же. B узнаёт свой public (NAT2 IP:Y)
Обмен IP/portЧерез signaling server (не STUN, а отдельный, например WebSocket) A и B обмениваются полученной информацией
3. A -> B:YA шлёт UDP пакет на (NAT2 IP, Y). NAT2 видит входящее, не знает, дропает. Но NAT1 открывает дырку для исходящего
4. B -> A:XB шлёт на (NAT1 IP, X). NAT1 видит -- мы недавно отправляли на B:Y, разрешаем. Соединение установлено!

Алгоритм:

  1. A и B оба узнают свои публичные адреса через STUN-сервер.
  2. Через сигнальный сервер (отдельный) обмениваются этой информацией.
  3. Одновременно начинают слать пакеты друг другу. Первые пакеты дропаются NAT-ами (нет открытой записи). Но они открывают записи в своих NAT.
  4. После пары round-trips NAT уже разрешает пакеты в обе стороны.

Hole punching работает для UDP и часто для TCP (но сложнее). Лучше всего с full cone NAT. С symmetric NAT — не работает (порты разные для каждого target). В этом случае нужен TURN-сервер — сервер-relay, через который идёт весь трафик.

Это вся индустрия WebRTC: STUN + сигнальный сервер + TURN fallback. Zoom, Discord, Telegram-звонки — всё построено на этом.


CGNAT — NAT на уровне провайдера

CGNAT (Carrier-Grade NAT) — то же самое, но на уровне провайдера. Когда у провайдера тоже не хватает публичных IP, он ставит NAT на своей границе.

[Ваш дом] - [Дом-NAT] - [Провайдер-CGNAT] - [Интернет]

Внутри дома — ваш приватный IP (192.168.X.X). На вашем модеме — приватный IP провайдера (часто 100.64.X.X из RFC 6598). На выходе провайдера — их публичный IP.

Признак CGNAT:

# Узнать свой "публичный" IP с точки зрения интернета:
curl ifconfig.me
# 87.123.45.6

# Узнать IP вашего модема (на странице админки -- 192.168.1.1):
# Если IP модема НЕ совпадает с curl ifconfig.me -- значит CGNAT
# Если ваш модемный IP в 100.64.0.0/10 -- точно CGNAT

# Также можно посмотреть в traceroute -- первый хоп после вашего роутера будет
# в диапазоне 10/8 или 100.64/10 -- это NAT провайдера

Минусы CGNAT для пользователя:

  1. Нельзя пробросить порт. Хостить серверы из дома невозможно. Никакой UPnP не поможет.
  2. P2P-приложения хуже работают. Hole punching становится менее эффективным.
  3. Provider видит весь трафик. Точнее, NAT-логи провайдера показывают, кто и куда ходил.
  4. Множественные пользователи — один IP. Если кто-то с вашим IP заблокирован (например, забанен на форуме), банится все остальные.

В России CGNAT широко используется кабельными и особенно мобильными провайдерами. В США в основном Tier-3 операторы. Решение для активных пользователей — купить выделенный публичный IP (доплата 200-500 руб/мес).


Hairpinning / NAT loopback

Сценарий: у вас домашний сервер с port forward. Снаружи на 87.123.45.6:8080 все ходят нормально. А вы изнутри дома пытаетесь зайти на свой же сервер по публичному IP: curl http://87.123.45.6:8080. Работает? Часто нет.

Причина: пакет от вас идёт с приватного IP на публичный (свой же). Роутер видит «dst = мой публичный IP» — должен бы понять, что это его port forward, и отправить на 192.168.1.100. Но многие домашние роутеры этого не делают — называется отсутствие NAT hairpinning.

Решения:

  • В админке роутера включить «NAT loopback» / «hairpin NAT» если есть такая опция.
  • Использовать внутренний IP сервера (192.168.1.100:80) изнутри дома.
  • Использовать split-DNS (внутри — внутренний IP, снаружи — публичный).

В корпоративных файрволах (pfSense, OPNsense) hairpinning обычно работает из коробки.


NAT и сложности с приложениями

Не все протоколы дружат с NAT. Известные проблемные:

1. FTP active mode. В active FTP клиент говорит «приходи ко мне на порт X для данных». Через NAT не работает — сервер не знает, как достучаться через NAT клиента. Решение — passive mode (клиент инициирует все соединения).

2. SIP (VoIP). SIP передаёт IP в заголовках сообщений. Через NAT IP в сообщении — приватный, ничего не работает. Решение — SIP ALG (Application Level Gateway) на роутере, который переписывает IP в заголовках. Но SIP ALG часто работает плохо — лучше отключить и использовать STUN.

3. IPsec. Шифрованные пакеты не позволяют NAT переписать headers TCP/UDP внутри. Решение — IPsec NAT-T (NAT Traversal) — инкапсулирует IPsec в UDP, который NAT уже может правильно обработать.

4. SCTP / DCCP. Многие NAT-устройства не понимают эти транспортные протоколы.

5. WebRTC. Работает, но требует STUN/TURN-инфраструктуры (см. выше).


NAT vs Firewall

NAT и firewall — разные вещи, хотя в практике совмещены:

  • NAT — переписывает адреса/порты. По сути translation.
  • Firewall — разрешает или дропает пакеты по правилам. По сути filtering.

NAT даёт побочный эффект firewall’а: входящие соединения, не инициированные изнутри, не имеют записи в NAT-таблице и дропаются. Это и есть «бесплатный firewall» в IPv4.

В IPv6, где NAT обычно нет, каждое устройство имеет публичный IP, и нужен явный firewall (не положиться на NAT). Это часто проблема — забывают настроить firewall в IPv6, и устройства торчат наружу.

# Просмотр NAT-таблицы Linux:
sudo iptables -t nat -L -n -v

# Просмотр текущих NAT-маппингов (conntrack):
sudo conntrack -L
# Показывает все активные соединения и их NAT-translation

Попробуй сам

# 1. Узнать ваш публичный IP:
curl ifconfig.me

# 2. Сравнить с локальным:
ip addr show     # ваш приватный IP

# 3. Понять, есть ли CGNAT:
# - Откройте админку роутера, посмотрите его WAN IP
# - Сравните с curl ifconfig.me
# - Если разные -- между вами и интернетом ещё один NAT (CGNAT провайдера)

# 4. Посмотреть текущие NAT-translations (если у вас Linux-роутер):
sudo conntrack -L | head

# 5. Симулировать port forwarding:
# Запустить тестовый сервис локально:
python3 -m http.server 8000 --bind 192.168.1.42
# В админке роутера: External 8080 -> 192.168.1.42:8000
# Извне (например с телефона по 4G): curl http://YOUR_PUBLIC_IP:8080

# 6. Проверить, какой у вас тип NAT (через online STUN tester):
# https://test.webrtc.org/ -- покажет NAT type
# или приложение для STUN-теста

# 7. Посмотреть hairpin:
# Когда у вас есть port forward, попробуйте curl с публичного IP изнутри дома:
curl http://YOUR_PUBLIC_IP:8080
# Если работает -- роутер поддерживает hairpin. Если нет -- нужен внутренний IP.

# 8. На Linux-машине с NAT (например, гипервизор):
sudo iptables -t nat -L -n
# Увидите цепочки PREROUTING (входящий NAT -- port forward) и POSTROUTING (исходящий NAT -- masquerade)

# 9. Посмотреть, сколько NAT-сессий открыто:
cat /proc/net/nf_conntrack | wc -l   # на современных Linux
# или
sudo conntrack -C

Проверка знанийKnowledge check
Вы делаете видеозвонок через WebRTC-сервис (например, Google Meet) с мобильного интернета. Замечаете, что звонок 1-на-1 иногда идёт через relay-сервер (TURN) -- видно в WebRTC-stats. Качество хуже, задержки выше. Что технически происходит и как это починить?
ОтветAnswer
Симптомы указывают на CGNAT провайдера, скорее всего symmetric NAT. WebRTC пытается установить P2P-соединение через STUN+ICE (hole punching). Когда оба клиента за обычными NAT (cone-type) -- работает напрямую, минимальная задержка. Но мобильные провайдеры почти всегда ставят клиентов за CGNAT с symmetric поведением: для каждого outbound (dst IP, dst port) NAT использует РАЗНЫЙ внешний src port. Hole punching требует, чтобы оба узла знали внешний port партнёра -- но при symmetric NAT этот port предсказать нельзя (он зависит от dst, который при punching ещё не известен). ICE не может установить direct connection, fallback на TURN-relay: весь трафик идёт через TURN-сервер. Это работает (NAT пропускает -- ваш клиент сам инициировал к TURN), но добавляет 1-2 промежуточных хопа, увеличивает latency и нагружает сервер. Как починить: 1) Использовать IPv6 если оба клиента поддерживают -- там нет NAT, P2P работает прямо. 2) Купить публичный IP у мобильного оператора (некоторые предлагают за доплату). 3) Сменить провайдера на того, кто без CGNAT (домашний кабельный обычно лучше). 4) Со стороны разработки -- использовать ICE TCP probes, не только UDP, иногда срабатывает. Большинство пользователей не могут это починить и работают через TURN -- именно поэтому WebRTC-сервисы держат огромную TURN-инфраструктуру (Google Meet, Zoom).

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 5. Как именно NAT позволяет 30 устройствам в доме делить один публичный IP?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4