Pull to refresh

Comments 20

Для такого простого примера можно было и не использовать unsafe. Достаточно было просто объявить

let mut buf = [0; 512];

а потом ниже использовать как

match recv_sock.recv(&mut buf) {
    Ok(n) => {
        let buf = &buf[..n];

Каждый роутер, переадресующий пакет, уменьшает значение TTL на 1.

Увы, это как раз не догма. Обычно - да, но не всегда.

Роутер запросто может не изменять TTL. Как правило, используется, чтобы спрятать узел маршрутизации, а то и целый сегмент, если таких роутеров в трассе несколько. По факту узел есть, но трассировка не покажет его.

Реже встречается обратная ситуация - роутер уменьшает TTL более чем на 1. Например, как способ сделать "более дорогим" путь через себя для протоколов динамической маршрутизации и немного разгрузиться. В этом случае такой узел будет присутствовать в отчёте на нескольких хопах подряд.

"более дорогим" путь через себя для протоколов динамической маршрутизации

Что это за протоколы маршрутизации такие???

Я никогда не понимал, как именно traceroute обнаруживает каждый сетевой переход. Оказывается, всё дело в хитром трюке с TTL

Хотя это довольно-таки прозрачно описано в документации и даже находило отклик в фольклоре:

Traceroute
Представь себе, что ты живешь на 9м этаже и хочешь узнать всех жильцов которые живут от тебя до Клавки с 3го. Ты берешь взрывпакет и, исходя из формулы свободного падения, рассчитываешь время взрыва пакета над 8м этажом. Это TTL=1. После того как пакет ибанет - выглянет озверевшая рожа соседа с 8го этажа. Время реакции зависит от загруженности сервера, т.е. от занятости соседа и от шейпов, т.е. в воздухе ли ваша система или ты живешь на планете, где атмосфера жидкий азот. Так вот, если вообще не дождешься ответа - твой сосед глухой - у него запрещены icmp ответы, либо он запретил их только для тебя если его уже подзаебали твои финты и он научился тебя игнорировать. Дальше выставляешь TTL=2 и т.д. Не забывай, что если Клавка живет выше тебя – это No route to host

Больше народного творчества

DHCP
Вы проснулись после дикой пьянки. Первые ваши слова «кто я?» и «где я?». Сосед, который не запивал водку пивом, вам сообщает все ваши параметры: кто вы и где. Этот сосед выступает в роли DHCP-сервера. Учтите, что в сети могут быть так называемые «ложные DHCP-сервера», например жена – на ваш вопрос «кто я?» она выдаст неверную информацию: «алкоголик ты проклятый». Так что не всегда динамическая выдача параметров безопасна, рекомендуется записывать свои параметры (как зовут, ваш адрес и т.д.) на бумажке.

Маршрут по умолчанию
Подойдите к прохожему и спросите «не подскажете ли вы как пройти к моргу имени Немировича-Данченко?». С большой долей вероятности вас пошлют нахуй. Так вот это и есть маршрут по умолчанию, другими словами - если адрес назначения не известен, то пакеты посылаются на маршрут по умолчанию (синонимы: шлюз по умолчанию, default gateway).

Понятие TTL
Представьте себе, что вам 5 лет и вы хотите кушать. Вы идете к папе и говорите: «Папа, я хочу кушать». Ваш папа смотрит телевизор, согласно таблице маршрутизации о посылает вас к маме. Вы идете к ней и просите «Мамааа, я хочу кушать». Мама болтает с подругой по телефону и согласно своей таблице маршрутизации посылает вас к папе. И так вы ходите как дурак от папы к маме и обратно, туда-сюда, туда-сюда, а все потому что криворукие админы (родители папы и мамы) неправильно настроили таблицу маршрутизации. Чтобы защититься от таких ситуаций придумали понятие TTL (Time To Live), что применительно к нашей ситуации означает количество терпения у мальчика, пока он не скажет «заебало» и не упадет перед ногами мамы или папы в беспомощном состоянии. Последний, по правилам (стандарты – это «так заведено в семье»), обязан послать короткий нелестный отзыв адрес того, кто послал мальчика кушать. Это так называемый icmp-пакет «мальчик издох»

Ping
Вы конечно бывали в ситуации «сам дурак». Вы кричите «Петя, ты еблан», а в ответ слышите «Вася, сам еблан». Это простеший пинг. Вы только что пропинговали Васю. Не все отвечают на пинги, особо культурные, например Microsoft.com не утруждают себя реагированием на ваши запросы. С такими переругиваться бесполезно, мы знаем, что они слышат и злятся, но реакции добиться не можем. Тем не менее, пинг – неплохой способ узнать жив ли хост, ведь пиная труп ногами не добьешься реакции «сам дурак»

Traceroute
Представь себе, что ты живешь на 9м этаже и хочешь узнать всех жильцов которые живут от тебя до Клавки с 3го. Ты берешь взрывпакет и, исходя из формулы свободного падения, рассчитываешь время взрыва пакета над 8м этажом. Это TTL=1. После того как пакет ибанет - выглянет озверевшая рожа соседа с 8го этажа. Время реакции зависит от загруженности сервера, т.е. от занятости соседа и от шейпов, т.е. в воздухе ли ваша система или ты живешь на планете, где атмосфера жидкий азот. Так вот, если вообще не дождешься ответа - твой сосед глухой - у него запрещены icmp ответы, либо он запретил их только для тебя если его уже подзаебали твои финты и он научился тебя игнорировать. Дальше выставляешь TTL=2 и т.д. Не забывай, что если Клавка живет выше тебя – это No route to host

DNS
Представь, что на дворе 17й год, ты - вождь мирового пролетариат и тебе нужно срочно попасть в одно место. Ты поднимаешь трубку и начинаешь орать "Але, багышня, багышня, мне Смольный!" Если ты слышишь, как "багышня" начинает орать: "Дуськ, а Дуськ? Опять этот мудак картавый звонит! Где эта су... Лизавета Павловна... Смольный на ейном участке?" Это рекурсивный ДНС- сервер. Если она молча передает трубку Дуське, а та, выслушав тебя, Лизавете Павловне - сервер нерекурсивный.

Не совсем понятно, как будет проходить обратный ICMP-пакет через NAT?

Особенно, если на промежуточных роутерах включен Symmetric NAT или Port Restricted NAT или Adress Restricted NAT?

Не совсем понятно, как будет проходить обратный ICMP-пакет через NAT?

Stateful packet inspection (SPI) for NAT. Если есть трансляция, открытая исходящим пакетом, и разрешено прохождение пакетов, относящихся к этому соединению, то оповещения ICMP, принятые маршрутизатором с NAT, будут перенаправлены этим маршрутизатором отправителю исходного пакета. Относится ли пакет с оповещением ICMP к какому-либо ранее открытому соединению, или нет, маршрутизатор узнаёт путём анализа вложенного в этот пакет исходного пакета (с уже транслированными им адресами/портами).

Например, в iptables для SPI предназначен модуль conntrack, и если в таблицу FORWARD добавить правило c разрешением (--jump ACCEPT) прохождения пакетов, связанных (RELATED) с состоянием соединения (connection state, --cstate): -m conntrack --cstate RELATED --jump ACCEPT, то это разрешит прохождение ответов ICMP даже в том случае, когда исходный пакет соединения был подвергнут трансляции адресов/портов.

Особенно, если на промежуточных роутерах включен Symmetric NAT или Port Restricted NAT или Adress Restricted NAT?

Виды NAT не имеют отношения к прохождению через них оповещений ICMP. Для прохождению ответов ICMP требуется, чтобы на этих самых промежуточных маршрутизаторах была включена и правильно настроена SPI for NAT для трафика, связанного с состоянием соединения.

Ого!

Т.е. исходящий проброс будет открыт NAT на шлюзе для UDP, но обратно он будет пропускать и ICMP-ответы?

Но кое-что всё равно не ясно:

Вот послали мы UDP-пакет на некий IP на порт 33434. Но ответ при достижении TTL=0 придет совсем с другого IP.

Т.е., даже если включен на шлюзе Symmetric NAT или Adress Restricted NAT, то такой ICMP-ответ не будет сходу отброшен (как ответ для неизвестного вопрошающего), а сначала будет вскрыт, узнан порт исходящего UDP-соединения, адрес вопрошающего и ему туда ответ будет перенаправлен. Правильно понимаю?

Вот послали мы UDP-пакет на некий IP на порт 33434. Но ответ при достижении TTL=0 придет совсем с другого IP.

Ответ в рамках того же соединения не придёт, придёт оповещение ICMP, а это уже совершенно другой протокол, который в установленное ранее соединение уже не вписывается. То есть, межсетевой экран (МСЭ) на маршрутизаторе знает про соединение, например, TCP/UDP A.A.A.A:PortA <—> B.B.B.B:PortB, а ему внезапно прилетит ICMP C.C.C.C/TTL expired, которое и не TCP, и не UDP, и адрес отправителя в нём не B.B.B.B, ну и про порты в нём вообще ничего нет.

МСЭ, который не умеет SPI, такой пакет просто тупо удавит. Чтобы не сломать интернет, таким МСЭ приходится разрешать пропуск вообще любых ICMP TTL expired, admin prohibited и всё семейство unreachable откуда угодно, что представляет собой определённый риск.

А вот МСЭ, который умеет SPI, и у которого эта самая SPI включена, ловко расковыривает любое оповещение ICMP, достаёт из него оригинальный пакет, устанавливает по нему сведения о протоколе, а также те самые A.A.A.A:PortA, B.B.B.B:PortB, находит по ним соединение в своей таблице соединений и понимает, что он должен отправить оповещение ICMP в адрес инициатора соединения A.A.A.A. Ну или давит это оповещение ICMP, если искомое соединение в своей таблице он так и не нашёл.

C SPI для NAT просто добавляется ещё один шаг. Найдя совпадающее соединение, МСЭ затем смотрит в дополнительные поля записи таблицы соединений, в которых хранятся оригинальные адреса/номера портов до трансляции, выбирает из нужного поля оригинальный адрес инициатора соединения и отправляет оповещение уже ему.

Т.е., даже если включен на шлюзе Symmetric NAT или Adress Restricted NAT, то такой ICMP-ответ не будет сходу отброшен (как ответ для неизвестного вопрошающего), а сначала будет вскрыт, узнан порт исходящего UDP-соединения, адрес вопрошающего и ему туда ответ будет перенаправлен. Правильно понимаю?

Правильно понимаете. SPI — это великое изобретение, существенно упрощающее настройку МСЭ, а на его изобретателей вообще надо молиться :)

МСЭ, который не умеет SPI, такой пакет просто тупо удавит.

Забавно, но я таких со своей стороны практически не встречал. Трейс в интранет всегда работал корректно через все бытовые (и не очень) NATы на роутерах, шлюзах на основе всяких OS (были и Linux и FreeBSD и даже Windows). Можете назвать реальный пример такого, чтобы самому пощупать?

Забавно, но я таких со своей стороны практически не встречал.

Ну так я ж давно живу. Я ещё ipchains настраивал, в них никакого conntrack'а не было. И древние циски родом из 90-х годов прошлого века тоже настраивал, в которых даже расширенных ACL не было, не говоря уже о CBAC или ZFW.

Трейс в интранет всегда работал корректно через все бытовые (и не очень) NATы на роутерах, шлюзах на основе всяких OS (были и Linux и FreeBSD и даже Windows).

Что совершенно неудивительно, потому что в них уже был встроен SPI с поддержкой NAT. Я ж говорю, создателям SPI надо памятник при жизни поставить.

Можете назвать реальный пример такого, чтобы самому пощупать?

Самый простой вариант заключается в том, чтобы взять любой работающий линуксовый МСЭ на iptables, удалить из его таблиц все правила, в которых фигурирует conntrack, после чего можно будет поглядеть на отвалившийся PMTUD и на неработающую трассировку.

Команда для удаления всех правил, в которых упомянут conntrack:

sudo iptables -S \
| sed -nEe '/\<conntrack\>/ s!^-A\>!iptables -D!p' \
| sudo /bin/sh

Если хочется приобщиться к старине, найдите где-нибудь древний маршрутизатор Cisco, разработанный и выпущенный в конце 90-х ­— начале 00-х, поставьте на него не менее древний Cisco IOS, в feature set которого отсутствуют упоминания о Context-Based Access Control (CBAC) и Zone-Based Policy Firewall (ZFW), ну или хотя бы не включайте их, если они там есть, и насладитесь оригинальным устойчивым вкусом. Cisco ASA не подойдут, они сделаны на базе линуха с IPtables, и потому в них SPI была изначально, и сразу с NATом.

любой работающий линуксовый МСЭ на iptables, удалить из его таблиц все правила, в которых фигурирует conntrack

А что на счёт FreeBSD и ipfw?

А что на счёт FreeBSD и ipfw?

А насчёт ipfw, да и любых других МСЭ можно получить вполне исчерпывающую консультацию гугловского ИИ, поискав в гугле "<название МСЭ> stateful packet inspection", возможно, "with examples". Из объяснений вполне можно понять, какие правила из конфигурации МСЭ надо исключить, чтобы эту самую SPI в нём отключить, или, наоборот, какие — добавить, чтобы её включить. Вот, например: "ipfw stateful packet inspection with examples".

Ну да, универсальный ответ "тебя что, в гугле забанили?" (с)

Ну да, универсальный ответ "тебя что, в гугле забанили?" (с)

Нормальный ответ, я считаю. Мне всё равно приходится консультироваться по поводу деталей в этом самом гугле, чтобы не наврать в своих ответах, так почему бы и не устранить лишнее звено в моём лице из процесса получения знаний?

Спасибо. Это именно то, что я хотел уточнить.

Но вот я тут подумал и понял, что не понимаю, как организован исходящий NAT для ICMP.

Раз портов в ICMP нет, то нужно опираться на какие-то другие характеристики пакета. Например на ID ICMP-пакета.

Но вот в статье https://habr.com/ru/companies/ruvds/articles/763600/#diy автор утверждает, что в Windows у всех ICMP-пакетов одинаковый ID. И как тогда не путается комп с Window, пингуя одновременно несколько внешних хостов?

То ли автор той статьи чего-то не понял, то ли не нашел реального механизма сопоставления.

Но вот я тут подумал и понял, что не понимаю, как организован исходящий NAT для ICMP.

Вы хотели спросить, как работает SPI для NAT в случае ICMP, если у ICMP нет портов? Портов нет, но есть типы и коды сообщений, и единственный тип сообщения ICMP, для которого можно организовать псевдосоединение — это тип Echo request. Когда МСЭ с SPI для NAT обрабатывает такой пакет, он открывает псевдосоединение, в котором ждёт в ответ Echo reply с того же адреса, на который через него прошёл Echo request.

Раз портов в ICMP нет, то нужно опираться на какие-то другие характеристики пакета. Например на ID ICMP-пакета.

Совершенно верно!

Но вот в статье https://habr.com/ru/companies/ruvds/articles/763600/#diy автор утверждает, что в Windows у всех ICMP-пакетов одинаковый ID.

И у линуха, ЧСХ, тоже одинаковые.

И как тогда не путается комп с Window, пингуя одновременно несколько внешних хостов?

Автор той статьи этого не понимает, потому что его, как обычно, в гугле забанили. А меня в гугле не забанили, поэтому на первой же странице запроса "icmp packet identifier field NAT" первым же ответом я получил ссылку на RFC 5508 NAT Behavioral Requirements for ICMP, а в п. 3.1. ICMP Query Mapping, размещённом на странице 6 этого документа, получил ответ на тот самый вселенский вопрос о смысле жизни и всего остального об ID ICMP пакета с пояснениями, цитирую:

A NAPT device further translates the ICMP Query Id and the associated checksum in the ICMP header prior to forwarding. NAT mapping of ICMP Query Identifiers SHOULD be external-host independent. Say, an internal host A sent an ICMP Query out to an external host B using Query Id X. And, say, the NAT assigned this an external mapping of Query Id X' on the NAT's public address. If host A reused the Query Id X to send ICMP Queries to the same or different external host, the NAT device SHOULD reuse the same Query Id mapping (i.e., map the private host's Query Id X to Query Id X' on NAT's public IP address) instead of assigning a different mapping. This is similar to the "endpoint independent mapping" requirement specified in the TCP and UDP requirement documents [BEH-UDP], [BEH-TCP].

NAPT device — это устройство с тем самым МСЭ с SPI для NAT, и, вкратце, такое устройство, в соответствии с вышеупомянутым RFC 5508, должно подменять не только адрес отправителя эхо-запроса, но и этот самый злосчастный неизменный ID, точно так же, как оно подменяет в пакетах UDP и TCP не только адрес инициатора соединения, но и номер исходящего порта того самого соединения, чтобы потом не перепутать ответы от одной и той же цели соединения разным отправителям внутри обслуживаемой им сети.

Само собой, я всё это проверил, пропинговав DNS гугла с двух разных машин в своей сети, и получил на своем граничном маршрутизаторе именно то, что ожидал увидеть: у двух разных соединений с этих двух разных машин в таблице соединений МСЭ были разные ICMP ID.

P.S. Граждане, не стесняйтесь спрашивать у гугла непонятные Вам вещи, гугл обязательно Вам их разъяснит! Это были сарказм и ирония.

Когда МСЭ с SPI для NAT обрабатывает такой пакет, он открывает псевдосоединение, в котором ждёт в ответ Echo reply с того же адреса, на который через него прошёл Echo request.

Но когда мы юзаем tracert, нам не приходит Echo request с целевого хоста. Нам приходит Time Exceeded совсем с другого промежуточного хоста.

Как тогда шлюз узнает, что этот ICMP-ответ и куда нужно транслировать, а не отвергать?

... у двух разных соединений с этих двух разных машин в таблице соединений МСЭ были разные ICMP ID.

Это Вы с двух разных внутренних хостов пинговали один внешний. А если наоборот - с одного внутреннего хоста пинговать разные внешние? Как тогда внутренний хост узнаёт, от какого внешнего хоста какой ответ пришёл?

... ответ на тот самый вселенский вопрос о смысле жизни и всего остального ...

Неужели, "42"?

Как тогда шлюз узнает, что этот ICMP-ответ и куда нужно транслировать, а не отвергать?

Вы внимательно читали мои пояснения? ICMP TTL Exceeded — это не ICMP ответ, это ICMP оповещение, у него внутри находится оригинальный пакет, который прибил промежуточный маршрутизатор, вот по нему и по своей таблице соединений, где хранятся и оригинальные, и транслированные адреса, номера портов, ICMP ID, устройство с SPI и определяет, кому во внутренней сети надо направить ICMP TTL Exceeded (с оригинальным пакетом внутри, в котором устройство с SPI точно так же должно подменить адрес/порт/ICMP ID на оригинальные по своей таблице соединений и трансляций).

Это Вы с двух разных внутренних хостов пинговали один внешний. А если наоборот - с одного внутреннего хоста пинговать разные внешние?

У них будут разные транслированные ICMP ID.

Как тогда внутренний хост узнаёт, от какого внешнего хоста какой ответ пришёл?

Внутренний хост? По тем же самым разным ICMP ID, но уже восстановленным в ICMP ответах (ICMP Echo reply) устройством с SPI для NAT. А если этот внутренний хост настолько ипанутый, что всегда рожает ICMP Echo Request'ы с одним и тем же ICMP ID в разные адреса, то — по этим самым адресам, с которых к нему придут ICMP Echo Reply.

В общем, Wireshark Вам в руки, и — вперёд, самостоятельно исследовать поведение ICMP, а мне и мою работу работать надо :)

UFO landed and left these words here
UFO landed and left these words here
Sign up to leave a comment.

Articles