
Обычно NAT сохраняет публичную конечную точку локальной конечной точки одинаковой для всех пакетов, которые приходят с него, что делает возможным легкое проникновение в UDP. Однако некоторые NAT сопоставляют локальную конечную точку с другой публичной для каждого отдельного хоста, на который отправляется пакет, что делает невозможным проникновение в UDP.
Единственный способ сделать традиционный UDP-пробив — угадать удаленную конечную точку. Однако, поскольку портов более 65 000, этот метод не очень надежен. Поэтому я читал, что приложения вроде Skype, которые, как известно, способны общаться практически через любой тип NAT, используют для этого ретранслятор. Вот мои вопросы:
Реле — это просто сокет, который переносит входящие данные из одного сокета в другой, верно? Есть ли другие способы сделать UDP-дырокол через непослушные NAT, не прибегая к диким догадкам или не используя реле (что тогда уже не является «дыроколами»)?
решение1
Термин «нехорошо себя ведающие NAT» неверен — любое устройство NAT, использующее PAT (перевод адресов портов) для объединения нескольких частных адресов в один публичный адрес, будет переназначать исходные порты. Это то, что «адрес порта» означает в PAT.
Было бы невозможно, чтобы два внутренних устройства использовали один и тот же адрес источника для одного и того же пункта назначения и ожидали, что порт источника останется тем же после NAT, и это не пойдет на пользу положению безопасности, если пытаться сохранить порт источника постоянным при нацеливании на несколько пунктов назначения. Так что это, как правило, не та цель, которую брандмауэры преследуют при своей конструкции.
Конечно, это не поможет здесь, где вы хотите узнать исходный порт соединения, не получая никаких пакетов из этого источника. Ретранслятор — очевидный вариант, когда конечные точки общаются через третью сторону (да, ретранслятор просто передает пакеты между сокетами, как вы предполагаете — реализация, вероятно, гораздо сложнее в серверах Skype, но в принципе это то же самое).
Трудно представить, как можно было бы сделать это каким-либо другим способом, поскольку конечные точки не знают о преобразованиях, которые происходят «на лету», поэтому они даже не могут сообщить свой исходный порт через какой-либо побочный канал (например, просто зарегистрировав порт на центральном сервере, но взаимодействуя напрямую).