Изменения

Перейти к: навигация, поиск

Преодоление барьера из двух симметричных NAT

152 байта добавлено, 12:27, 20 сентября 2009
Нет описания правки
<big>breakNAT</big> -  — ''как "проломить" «проломить» барьер из двух симметричных NAT''
[[wikipedia:Network Address Translation|NAT]] (от англ. ''Network Address Translation''  — «преобразование сетевых адресов»)  — механизм в сетях TCP/IP, позволяющий преобразовывать IP-адреса транзитных пакетов. Также имеет названия IP Masquerading, Network Masquerading и Native Address Translation.
'''===== Дано:''' два хоста host<sub>1</sub> и host<sub>2</sub>, подключённые к сети Internet через маршрутизаторы с публичными IP-адресами nat<sub>1</sub> и nat<sub>2</sub>, осуществляющие трансляцию сетевых адресов (NAT). Каждому новому исходящему соединению от первого хоста (host<sub>1</sub>) сопоставляется некоторый свободный порт известного IP-адреса маршрутизатора (nat<sub>1</sub>), аналогично host<sub>2</sub> и nat<sub>2</sub>. Присваиваемый номер порта зависит от порта источника, а также порта и IP-адреса назначения, т.е устройства nat<sub>1</sub> и nat<sub>2</sub> осуществляют симметричную трансляцию сетевых адресов ([[wikipedia:Network_address_translation#Different_types_of_NAT|Symmetric NAT]]) типа queued resource allocation или random port allocation <ref name="stun">Обход некоторых типов Symmetric NAT с помощью STUN: <a href="http://www.cs.cornell.edu/projects/stunt/draft-takeda-symmetric-nat-traversal-00.txt"><i>Symmetric NAT Traversal using STUN [draft-00]</i></a> (<a href="draft-taked-symmetric-nat-traversal-00.txt">зеркало</a>) (автор - Y.Takeda);</ref> (выбор порта из очереди свободных или выбор произвольного свободного порта).==
'''Задача:''' установить прямое IP соединение между Даны два хоста host<sub>1</sub> и host<sub>2</sub> (без пересылки всех пакетов , подключённые к сети Internet через третий хостмаршрутизаторы с публичными IP-адресами nat<sub>1</sub> и nat<sub>2</sub>, осуществляющие трансляцию сетевых адресов (NAT). Каждому новому исходящему соединению от первого хоста (host<sub>1</sub>) сопоставляется некоторый свободный порт известного IP-адреса маршрутизатора (nat<sub>1</sub>), аналогично host<sub>2</sub> и nat<sub>2</sub>. Присваиваемый номер порта зависит от порта источника, а также порта и IP-адреса назначения, т.е устройства nat<sub>1</sub> и nat<sub>2</sub> осуществляют симметричную трансляцию сетевых адресов ([[wikipedia:Network_address_translation#Different_types_of_NAT|Symmetric NAT]]) типа queued resource allocation или random port allocation <ref name="stun">Обход некоторых типов Symmetric NAT с помощью STUN: [http://www.cs.cornell.edu/projects/stunt/draft-takeda-symmetric-nat-traversal-00.txt Symmetric NAT Traversal using STUN [draft-00]] (автор — Y.Takeda);</ref> (выбор порта из очереди свободных или выбор произвольного свободного порта).
'''Решение:''' для некоторых случаев, когда возможно какое-либо "предсказание" стратегий выделения портов трансляторами адресов, описаны решения в <ref name="stun" />, <ref>[[wikipedia:Simple traversal of UDP over NATs]]</ref>, и <ref>[http://www.jdrosen.net/papers/draft-rosenberg-midcom-turn-08.txt Traversal Using Relay NAT (TURN) [draft-08]]</ref>, мы же рассматриваем общий случай - очередь или случайное выделение.==== Задача =====
Установить прямое IP соединение между host<sub>1</sub> и host<sub>2</sub> (без пересылки всех пакетов через третий хост). ===== Решение ===== Для некоторых случаев, когда возможно какое-либо «предсказание» стратегий выделения портов трансляторами адресов, описаны решения в <ref name="stun" />, <ref>[[wikipedia:Simple traversal of UDP over NATs]]</ref> и <ref>[http://www.jdrosen.net/papers/draft-rosenberg-midcom-turn-08.txt Traversal Using Relay NAT (TURN) [draft-08]]</ref>, мы же рассматриваем общий случай — очередь или случайное выделение. Итак, '''во-первых,''' очевидно, что в этом случае без "сторонней помощи" «сторонней помощи» хосты host<sub>1</sub> и host<sub>2</sub> с этой задачей справиться не смогут, т.к: (в рассуждениях (i,j) = (1,2) или (2,1)) # host<sub>i</sub> не может открыть соединение с host<sub>j</sub> напрямую, т.к из-за трансляции адресов во всех пакетах, направленных в Internet от host<sub>j</sub>, поле "источник" «источник» подменяется на адрес nat<sub>j</sub> и выбранный устройством nat<sub>j</sub> порт, назовём этот порт port<sub>j</sub>;
# аналогично host<sub>j</sub> не может открыть соединение с host<sub>i</sub>;
# чтобы host<sub>i</sub> и host<sub>j</sub> могли соединиться, они должны узнать номера портов port<sub>j</sub> и port<sub>i</sub> соответственно, то есть host<sub>i</sub> должен иметь возможность отправлять пакеты на nat<sub>j</sub>:port<sub>j</sub>;
# однако, до того момента как host<sub>i</sub> отправит первый пакет на host<sub>j</sub>:port<sub>j</sub>, сопоставления с port<sub>i</sub> вообще не существует;
# следовательно, чтобы host<sub>i</sub> мог отправить пакет host<sub>j</sub>, он должен знать port<sub>j</sub>, а чтобы знать port<sub>j</sub>, ему должен прийти хотя бы один пакет от host<sub>j</sub> (оттранслированного в nat<sub>j</sub>:port<sub>j</sub>), а чтобы ему этот пакет пришёл, host<sub>j</sub> должен знать port<sub>i</sub>, а чтобы знать port<sub>i</sub>, ему должен прийти хотя бы один пакет от host<sub>i</sub>... круг замкнулся;# то есть '''задача не имеет решения''' -  — без "сторонней помощи" «сторонней помощи» host<sub>i</sub> и host<sub>j</sub> действительно не могут открыть прямое соединение друг с другом.
Итак, мы показали, что без "сторонней помощи" «сторонней помощи» открыть прямое соединение друг с другом host<sub>i</sub> и host<sub>j</sub> не могут.
'''Во-вторых,''' с использованием некоторой сторонней помощи задача становится разрешима, пусть и не без труда: установление соединения может отнять более получаса времени. Это всё ещё не подходит для размещения за NAT'ом NAT’ом полноценного сервера, но для задач, предполагающих небольшое количество "долгоживущих" «долгоживущих» соединений (например, одного), это уже вполне допустимо. Примером такой задачи может служить установка VPN-соединения между двумя компьютерами, не имеющими прямого доступа к сети Internet.
Мы будем использовать третий хост, имеющий публичный IP-адрес host<sub>3</sub> в сети Internet. Будем также использовать протокол [[wikipedia:User_Datagram_Protocol|UDP]], который не гарантирует доставку пакетов, но зато и не требует постоянного отслеживания и согласования [[wikipedia:Transmission_Control_Protocol#Using_TCP|sequence number]]'ов.
Во-первых, мы будем предполагать, что всё время работы алгоритмы каждый хост host<sub>i</sub> имеет открытое "управляющее" «управляющее» соединение с host<sub>3</sub> и всё согласование работы алгоритма происходит именно через эти "управляющие" «управляющие» соединения.
Первым шагом к решению задачи будет определение "времени «времени жизни соединения" соединения» на каждом из устройств nat<sub>i</sub>.
"«''Время жизни соединения''" » life<sub>i</sub> на устройстве nat<sub>i</sub> есть максимально возможный интервал времени между двумя последовательными пакетами с хоста host<sub>i</sub> на один и тот же IP-адрес и порт, при котором port<sub>i</sub> не меняется.
Чтобы определить "время «время жизни соединения" соединения» на устройстве nat<sub>i</sub>:# Отправляем с хоста host<sub>i</sub> пакеты на заранее выбранный порт третьего хоста host<sub>3</sub> с возрастающими интервалами (1 сек, 2 сек, 3 сек, ...)# На host<sub>3</sub> при приходе первого пакета сохраняем номер порта источника, при приходе каждого последующего сравниваем сохранённый номер порта с портом, записанным в поле "источник" «источник» пришедшего пакета; если они не равны, значит, интервал превышен - превышен — сохраняем предыдущий интервал как life<sub>i</sub> и выходим из цикла.
Теперь рассмотрим сам алгоритм:
# На host<sub>3</sub> сохраняем порт источника, с которого приходит отправленный в предыдущем пункте пакет (обозначим этот порт за port<sub>1</sub>);
# Ждём (life<sub>1</sub>+1) секунд;
# С host<sub>2</sub> на nat<sub>1</sub>:port<sub>1</sub> начинаем отправлять пакеты с заранее известным содержимым и временными интервалами, равными (life<sub>1</sub>-1) секунд (или меньше - меньше — всё зависит от скорости канала между host<sub>2</sub> и nat<sub>1</sub>);
# Перебираем порты port<sub>2</sub> и отправляем с host<sub>3</sub> от имени host<sub>1</sub>:port<sub>1</sub> на адрес nat<sub>2</sub>:port<sub>2</sub> пакеты с номером порта port<sub>2</sub> в теле пакета;
# Ровно один пакет из отправленных в предыдущем пункте придёт хосту host<sub>2</sub>, после чего сообщаем с хоста host<sub>2</sub> хосту host<sub>3</sub> номер порта port<sub>2</sub>, указанный в теле пришедшего пакета, по управляющему соединению;
# С хоста host<sub>3</sub>, также используя управляющее соединение, сообщаем хосту host<sub>1</sub> номер порта port<sub>2</sub>;
# Самая долгая стадия процесса: начинаем отправлять пакеты с временным интервалом (life<sub>1</sub>+1) с хоста host<sub>1</sub> на адрес nat<sub>2</sub>:port<sub>2</sub>, "заставляя" «заставляя» устройство nat<sub>1</sub> снова выбрать порт port<sub>1</sub>;
# Т.к мы имеем дело с симметричным NAT, использующим либо очередь свободных портов, либо выбор случайного свободного порта, рано или поздно port<sub>1</sub> снова будет выбран устройством, хост host<sub>2</sub> получит пакет от хоста host<sub>1</sub>, и соединение будет установлено.
Очевидно, в таком виде алгоритм является алгоритмом сложности O(n), где n - n — число возможных портов для перебора (в наихудшем случае это 65536). Посмотрим, можно ли как-нибудь улучшить этот результат:
# Во-первых, можно делать всё то же самое, используя не один выбранный порт port<sub>1</sub>, а k > 1 одновременно, при этом в среднем мы ускорим результат в k раз (сложность снизится до O(n/k)); # Во-вторых, можно определить T - T — среднее количество новых соединений, через которое номер порта повторяется, и сразу после выполнения первого пункта алгоритма отправить m пакетов на разные IP-адреса и порты (где m - m — меньшее T, но сопоставимое с T число, например, T/2 или T*3/4), чтобы быстро "прокрутить" «прокрутить» очередь или датчик случайных чисел на устройстве nat<sub>1</sub>, не обращая внимания на результат. В этом случае сложность алгоритма снизится в среднем в T/(T-m) раз.
'''===== Заключение:''' Задача "преодоления" барьера в виде двух симметричных NAT разрешима алгоритмом сложности O(n), и хотя в реальных условиях преодоление такого барьера займёт достаточно долгое время, оно всё же возможно. Реализации алгоритма на данный момент не существует, то есть все рассуждения в статье - чисто теоретические, надеюсь, однако, что из-за этого не менее корректные.</p>=====
Задача «преодоления» барьера в виде двух симметричных NAT разрешима алгоритмом сложности O(n), и хотя в реальных условиях преодоление такого барьера займёт достаточно долгое время, оно всё же возможно. Реализации алгоритма на данный момент не существует, то есть все рассуждения в статье — чисто теоретические, надеюсь, однако, что из-за этого не менее корректные. ===== Ссылки =====
<references />
(c) [[Участник:VitaliyFilippov|Виталий Филиппов]] aka vitalif, 2007 г2007 г[[Категория:Статьи]][[Категория:Разработка]][[Категория:Перенесено с vmx.yourcmc.ru]]

Навигация