NAT

Материал из Викиконспекты
Перейти к: навигация, поиск

NAT — Network Address Translation, метод трансляции сетевых адресов, описан в стандарте RFC 3022, RFC 1631. RFC 3022 на русском языке.

Задачи

1. NAT решает проблему ограниченного диапазона IP-адресов, она существенна до тех пор, пока не произойдёт окончательный переход на IPv6.

2. Позволяет ограничить общение снаружи ко внутренним хостам, при этом возможность общаться изнутри наружу остаётся.

3. Даёт возможность скрыть внутренние сервисы внутренних хостов/серверов. Можно подменить внутренний порт официально зарегистрированной службы (например, 80-й порт TCP (HTTP-сервер) на внешний 54055-й). Таким образом, снаружи можно будет попасть на сайт по адресу вида http://example.org:54055, но на внутреннем сервере, находящемся за NAT, работа HTTP-сервера будет происходить на обычном 80-м порту, то есть 80-й порт сервера не будет доступным из Интернета для прямого входящего соединения.

Принцип работы

Компьютер может быть подключен к Интернету напрямую (белый IP-адрес, обычно при подключении непосредственно к модему), либо через NAT — тогда компьютер имеет локальный IP-адрес, из Интернета недоступный (частный, серый). К серым адресам относятся адреса из следующих диапазонов:

Диапазон Количество хостов
10.0.0.0 - 10.255.255.255/8 16 777 216 хостов
172.16.0.0 - 172.31.255.255/12 1 048 576 хостов
192.168.0.0 - 192.168.255.255/16 65 536 хостов

Преобразование адреса методом NAT может производиться почти любым маршрутизирующим устройством — маршрутизатором, сервером доступа, межсетевым экраном. Принимая пакет от локального компьютера, роутер смотрит на IP-адрес назначения. Если это локальный адрес, то пакет пересылается другому локальному компьютеру. Если нет, то пакет надо переслать наружу в интернет. Но ведь обратным адресом в пакете указан локальный адрес компьютера, который из интернета будет недоступен. Поэтому роутер «на лету» транслирует (подменяет) обратный IP-адрес пакета на свой внешний (видимый из интернета) IP-адрес и меняет номер порта (чтобы различать ответные пакеты, адресованные разным локальным компьютерам). Комбинацию, нужную для обратной подстановки, роутер сохраняет у себя во временной таблице. Через некоторое время после того, как клиент и сервер закончат обмениваться пакетами, роутер сотрет у себя в таблице запись о n-ом порте за сроком давности.

Пример

NATExample2.jpg


Типы NAT

Статический

Один внутренний адрес преобразуется в один внешний, все запросы, приходящие на внешний адрес будут транслироваться на внутренний, как будто хост и является обладателем белого IP-адреса. Такой подход бывает полезным, когда внутри частной сети есть сервер, к которому необходим полный доступ извне. Минус подхода в том, что он никак не помогает сохранить белые адреса.

Динамический

Есть пул белых адресов, например, провайдер выделил сеть 198.51.100.0/28 с 16-ю адресами. Два из них (первый и последний) — адрес сети и широковещательный, ещё два адреса назначаются на оборудование для обеспечения маршрутизации. Двенадцать оставшихся адресов можно использовать для NAT и выпускать через них своих пользователей.

Ситуация похожа на статический NAT — один приватный адрес транслируется на один внешний, — но теперь внешний не чётко зафиксирован, а будет выбираться динамически из заданного диапазона. Проблема подхода такая же, как и в случае со статическим NAT — не решается проблема ограниченности белых адресов.

Many-to-One

Следующий тип имеет несколько названий: NAT Overload, Port Address Translation (PAT), IP Masquerading, Many-to-One NAT. Суть этого типа в том, что через один внешний адрес выходит наружу много приватных. Этот подход, в отличие от предыдущих, позволяет решить проблему с нехваткой внешних адресов.

Проблемы NAT

  • Принцип сетевых адресов никак не вписывается в архитектуру IP, которая подразумевает, что каждый IP-адрес уникальным образом идентифицирует только одну машину в мире.
  • NAT нарушает «сквозной» принцип, согласно которому каждый хост должен уметь отправлять пакет любому другому хосту в любой момент времени. Поскольку отображение адресов в NAT задается исходящими пакетами, входящие пакеты не принимаются до тех пор, пока не отправлены исходящие.
  • NAT превращает Интернет из сети без установления соединения в нечто подобное сети, ориентированной на соединение. Проблема в том, что NAT-блок должен поддерживать таблицу отображения для всех соединений, проходящих через него. Запоминать состояние соединения — дело сетей, ориентированных на соединение, но никак не сетей без установления соединений.
  • При использовании NAT нарушается одно из фундаментальных правил построения многоуровневых протоколов: уровень [math]k[/math] не должен строить никаких предположений относительно того, что именно уровень [math]k + 1[/math] поместил в поле полезной нагрузки.
  • Процессы в Интернете вовсе не обязаны использовать только TCP или UDP. Если пользователь машины [math]A[/math] решит придумать новый протокол транспортного уровня для общения с пользователем машины [math]B[/math], то ему придется как-то бороться с тем, что NAT не сможет корректно обработать поле Порт источника TCP.

Hole punching

Hole punching — метод для прямого соединения двух хостов, которые находятся за NAT-ами. Для инициации соединения требуется третья сторона – сервер, который виден обоим компьютерам. Обычно используются публичные STUN-серверы.

STUN (сокр. от англ. Session Traversal Utilities for NAT, Утилиты прохождения сессий для NAT) — это сетевой протокол, который позволяет клиенту, находящемуся за сервером трансляции адресов (или за несколькими такими серверами), определить свой внешний IP-адрес, способ трансляции адреса и порта во внешней сети, связанный с определённым внутренним номером порта. Эта информация используется для установления соединения UDP между двумя хостами в случае, если они оба находятся за маршрутизатором NAT.

UDP hole punching

Алгоритм установления UDP сессии между 2 хостами находящимися за NAT

Hole punching предполагает, что два клиента, [math]A[/math] и [math]B[/math], уже имеют UDP сессию с сервером [math]S[/math]. Когда клиент начинает сессию с [math]S[/math], сервер сохраняет две пары значений для этого клиента: пару IP адрес и UDP порт, которые клиент указывает при отправке пакета в поле отправителя, чтобы говорить с [math]S[/math], и пару IP адрес и UDP порт отправителя, которые сервер наблюдает при получении пакета. Первую пару будем называть приватным адресом, а вторую публичным. Приватный адрес сервер может получить от самого клиента в теле сообщения в поле регистрации клиента, а публичный адрес клиента он может посмотреть в поле отправителя в заголовках IP и UDP этого сообщения. Если клиент не за NAT, то его приватный и публичный адрес должны совпадать.

Предположим , что клиент [math]A[/math] хочет установить UDP сессию непосредственно с клиентом [math]B[/math]. Hole punching происходит следующим образом :

  • [math]A[/math] изначально не знает , как связаться с [math]B[/math], поэтому [math]A[/math] просит помощи у [math]S[/math] в создании UDP сессии с [math]B[/math].
  • [math]S[/math] отвечает [math]A[/math] сообщением , содержащим приватный и публичный адрес [math]B[/math]. В то же время, [math]S[/math] отправляет сообщение [math]B[/math] с запросом на соединение, содержащее приватный и публичный адрес [math]A[/math]. После того, как эти сообщения будут получены, [math]A[/math] и [math]B[/math] знают приватные и публичный адреса друг друга.
  • Когда [math]A[/math] получает приватный и публиный адреса [math]B[/math] от [math]S[/math], [math]A[/math] начинает посылать UDP пакеты по обоим адресам, и фиксирует как правильный тот адрес, с которого первым пришел ответ от [math]B[/math]. Аналогичным образом, когда [math]B[/math] получает приватный и публичный адрес [math]A[/math], он начинает посылать UDP пакеты по обоим адресам. Порядок и время доставки этих сообщений не имеет решающего значения, так как они являются асинхронными.

Если [math]A[/math] и [math]B[/math] находятся за одним и тем же NAT-ом, то они соединятся через приватные адреса, иначе через публичные. На картинке показан пример, когда [math]A[/math] и [math]B[/math] находятся за разными NAT-ами.

UDPHolePunching.png

TCP hole punching

Алгоритм установления TCP соединения между 2 хостами находящимися за NAT

Предположим, что клиент [math]A[/math] хочет установить TCP соединение с клиентом [math]B[/math]. Как и в UDP, мы предполагаем, что у [math]A[/math] и [math]B[/math] уже есть TCP соединения с известным сервером [math]S[/math]. Сервер записывает приватный и публичный адреса каждого зарегистрированного клиента, так же как и для UDP. На уровне протокола, TCP hole punching работает почти так же, как для UDP:

  • Клиент [math]A[/math] использует TCP соединение с [math]S[/math], чтобы попросить о помощи для подключения к [math]B[/math].
  • [math]S[/math] отвечает [math]A[/math], отправляя приватный и публичный адреса [math]B[/math], и в то же время посылает [math]B[/math] приватный и публичный адреса [math]A[/math].
  • Из тех же самых локальных портов TCP, которые [math]A[/math] и [math]B[/math] используют для соединения с [math]S[/math], [math]A[/math] и [math]B[/math] каждый асинхронно совершают попытки подключения друг к другу по публичному и приватному адресам, и одновременно слушают эти порты на входящие соединения.
  • Когда TCP соединение устанавливается, клиенты идентифицируют друг друга, чтобы убедиться, что они подключены к нужному клиенту. Если проверка подлинности завершается неудачно, клиенты закрывают эту связь и продолжают ожидание. Клиенты используют первое успешное соединение.

В отличие от UDP, где каждый клиент только нуждается в одном сокете, чтобы взаимодействовать с [math]S[/math] и любым числом хостов одновременно, в TCP приложение должно управлять несколькими сокетами привязаными к одному локальному TCP порту на клиенте. Каждый клиент нуждается в сокете, который соединяет его с [math]S[/math], слушающем сокете, который будет принимать входящие соединения, и в двух дополнительных сокетах, с помощью которых клиент будет инициировать исходящие соединения с публичными и приватными TCP адресами другого клиента.

TCPHolePunching.png

Источники информации