Linux ping не фрагментировать пакеты

Ping – setting don’t fragment bit in Linux/FreeBSD/Solaris/Cisco/Juniper

Ping.
Many times while debugging network problems of various kinds you need to send some packets of desirable size and don’t fragment bit being set. I list below how to do it for the different equipment/OSes. Let’s start with the most popular operating system among network folks – Linux:

Linux

By default ping in any Linux-based system (It also means any distribution – Slackware, Ubuntu, CentOS etc) is sent with Don’t fragment (df) bit set . You don’t need to add any command line switches for that. Here is what you get by default ping in Linux:
Defaults:
Don’t fragment bitВ (in echo request)В — set
Ip packet size – 84 bytes
Sending intervalВ — 1 second

Some examples.
-В sending station:

-В В receiving station:
[root@darkstar

]#tcpdump -s 1500 -n -vv icmp

To change sent packet size: -sВ , bytes (8 bytes of ICMP header will be added automatically).

Sending host:
[root@darkstar

]#ping 10.99.99.158 -s 1300

Receiving host:
freeBSD#tcpdump -n -v -s 1500 icmp

To change sending interval (mostly used together with large packet size) :
-iВ

Sending host:
[root@darkstar

]#ping -s 1300 -i 0.2 10.99.99.158

Receiving host:
freeBSD#tcpdump -n -v -s 1500 icmp

To force Linux to send pings with DF bit cleared (i.e. not set):
ping –M don’t

]#ping -s 1300 -M dontВ 10.99.99.158

freeBSD#tcpdump -n -v -s 1500 icmp

SideNote: FreeBSD ping has a nice add-on (see below) – sweeping size of the packets, while Linux doesn’t have such extra feature, Below is script to emulate it on Linux:

Here:
size – size of data in ICMP packet (bytes);
-I 0.5 – interval of 5 seconds (optional);
-c 3 — number of pings in each size session (NOT optional – or you will enter an endless loop which even Ctrl-C won’t be able to stop )

See it in action:
[root@darkstar

]#awk ‘ BEGINВ to change
Don’t fragment bit — not setВ ;В use df-bit to set

Running with defaults:

Receiving host:
[root@darkstar

]# tcpdump -n -vВ -s 1500 icmp

Set df bit and size of the packet (Note – when you set size of the ping you set IP packet size and not ICMP data size as in Nix systems).
Repeat count is set to 3 .
Tokyo#ping 191.91.21.41 size 1300 df-bit rep 3

Receiving host:
[root@darkstar

]# tcpdump -n -vВ -s 1500 icmp

Sweeping ping size.
This feature is available from extended ping menu:

Juniper routers (JunOS):
Defaults:
Ip packet size : 84 bytes
Don’t fragment bit – not set; use do-not-fragment to set
IntervalВ — 1 sec;В use interval to change
Sending pings with df bit set and size 1470 bytes
root@Juniper> ping 192.168.37.29 do-not-fragment size 1470

If packet size is too large and df is set you get this:

root@Juniper> ping 192.168.37.29 do-not-fragment size 13000

Источник

Что такое MTU

На этом блоге неоднократно рассматривалось устройство сетей Ethernet, однако одно понятие до сих пор оставалось нетронутым — MTU. Что же такое MTU и как оно может влиять на вашу работу в интернете?

Аббревиатура MTU означает Maximum Transmission Unit — это можно перевести как максимальный размер пакета, передаваемого по сетям. Если точнее, то не самого пакета, а тех полезных данных, что в нем содержатся. Если вы читали про сетевые протоколы, то знаете, что передаваемые по сетям пакет содержит серию заголовков, позволяющих доставить его и также некоторые данные, переносимые в пакете. Так вот, каждым маршрутизатором накладывается ограничение на размер полезных данных в пакете, и это и есть MTU.

Откуда берутся такие ограничения? Дело в том, что стандартов Ethernet заложено, что размер Ethernet-пакета не может превышать 1518 байт. При этом 4 последние байта составляет проверочная сумма, позволяющая проверить корректность пакета, а первые 14 байт — MAC-заголовок, содержащий MAC-адрес устройства, которому направлен пакет. Тем самым, для Ethernet MTU составляет 1500, и это и есть то базовое ограничение, от которого все «пляшут». Но ведь Ethernet — это нижний уровень, даже в локальной сети обращение идет по IP-адресам, и это означает, что внутри «полезных данных» для Ethernet будут содержаться еще заголовки, тем самым, полезный размер, скажем, TCP-пакета, будет уже меньше.

Фрагментация пакетов

Безусловно, эта информация не означает, что нельзя передать по сети больший размер данных, это было бы просто смешно. Когда размер полезных данных больше, протокол генерирует множество последовательных пакетов, которые дополняют нужные данные. Это позволяет работать в условиях нестабильного интернета, небольшие пакеты успевают проходить.

Однако куда интересней может быть ситуация, когда какое-либо устройство вашей сети настроено передавать пакеты размером не больше некоторого заданного, а ему приходит пакет с большим размером полезных данных. Что с ним можно сделать. Существует два варианта:

  • Отброс пакета: пакет может быть просто проигнорирован. В таком случае находящаяся за устройством цель и не узнает, что ей что-то посылали.
  • Фрагментация пакета: внутри пакет бьется на два более маленьких и передается дальше. Это приводит к более высокой нагрузке на сеть, поэтому часто эта опция отключена. Кроме того, следует помнить, что не все протоколы поддерживают получение и сборку фрагментированных пакетов.

Для определения максимального размера пакета, который можно послать к устройству, можно использовать так называемый ping-test. Посылайте ping с дополнительными опциями — запретить фрагментацию и указать размер пакета. Для Windows такая команда дается как ping host -f -l size, для Linux ping host -M do -s size.

MTU и VPN

Чаще всего проблемы с MTU могут возникать, когда вы подключаетесь куда-нибудь по VPN. Сами вы их, скорей всего решить не сможете, но у вас есть вариант попросить что-то изменить провайдера или цель подключения, например, на вашей работе. Так что же может происходить. Допустим, у провайдера задан какой-то MTU, например 1460. Они могли так занизить когда-то в прошлом, по просьбе некоторых клиентов или когда у них использовался какой-то специфический механизм авторизации. А на работе у вас, допустим, стоит MTU 1420. Но вы подключаетесь по VPN, и поэтому чтобы все могло работать, все заголоски VPN должны поместиться в 40 байт.

Могут поместиться, а могут и нет. Если вы используете PPTP, то, кажется, должны поместиться. А если, например, L2TP/IPSEC, то он задействует протокол ESP для шифрования, и у него довольно большие заголовки. В таком случае у вас подключиться не получится. Проявляться это будет так — вы можете вводить пароль, у вас будет начинать устанавливаться соединение, и дальше процесс подключения будет засыпать. А на сервере в логах будут периодические запросы к вашему компьютеру. Он даже ответы будет слать, но до сервера они не дойдут.

Что делать в таких случаях? Варианта два. 1) Просить поднять MTU у провайдера. 2) Просить опустить MTU на работе. Ну и, конечно, есть еще множество вариантов типа «забить», «поменять провайдера» и «поменять работу»,

Надеюсь, эта статья была полезной. Если есть вопросы, пишите!

Источник

Мониторинг сети в Linux (ping, traceroute, mtr)

Существует несколько хороших утилит, позволяющих искать неисправности в сети на уровне TCP/IP. Большинство из них выдает низкоуровневую информацию, поэтому для того чтобы пользоваться ими, нужно хорошо понимать принципы работы протоколов TCP/IP и маршрутизации. В этой статье мы рассмотрим основные инструменты поиска неисправностей в сети: утилитами ping, traceroute и mtr.

Утилита ping

Проверка доступности компьютера

Утилита ping предназначена для того, чтобы при помощи отправки ICMP пакетов убедиться в работоспособности хоста. Команда ping посылает запрос (ICMP ECHO_REQUEST) конкретному компьютеру и фиксирует поступающие ответы (ICMP ECHO_RESPONSE). Её можно применять для работоспособности отдельных компьютеров и сегментов сети. В обработке ее запроса участвуют таблицы маршрутизации, физические компоненты сетей и сетевые шлюзы, поэтому для достижения успешного результата сеть должна быть в более или менее рабочем состоянии. Если команда не работает, можно быть совершенно уверенным в том, что более сложные средства тем более не функционируют. Однако это правило неприменимо в сетях, где брандмауэры блокируют эхо-запросы ICMP. Убедитесь в том, что брандмауэр не препятствует работе команды ping, прежде чем подозревать, что зондируемый компьютер игнорирует эту команду. В конце концов, отключите на короткое время брандмауэр для проверки работоспособности сети.

Читайте также:  Mac os sierra нет pptp

Если не задан аргумент «число пакетов», команда ping работает в бесконечном цикле. Чтобы прервать работу команды, нужно нажать специальную клавиатурную комбинацию .

Например, пропингуем neoserver.ru (это имя хоста):

Информация о компьютере neoserver.ru включает его IP-адрес, порядковый номер ответного ICMP-пакета и полное время прохождения пакета. Полученные результаты свидетельствуют о том, что компьютер neoserer.ru работает и подключен к сети.

Min — минимальное время ответа хоста, кторому был отправлен запрос.

Avg среднее время ответа хоста, кторому был отправлен запрос

Max максимальное время ответа хоста, кторому был отправлен запрос.

Ещё вы увидите TTL — определяет максимальное количество хопов (то есть прыжок, участок между маршрутизаторами), которые пакет может пройти. Наличие этого параметра не позволяет пакету бесконечно ходить по сети.

В ОС Linux, как уже было сказано выше, команда ping без дополнительных параметров будет пинговать заданный хост бесконечно. Чтобы отправить, например, 10 запросов, необходимо добавить ключ :

В итоге, мы видим, что было отпралено 10 запросов и выведен результат.

Другие примеры задействования разын ключей:

Не резолвить имена адресов, выводить только ip-адреса

Завершение работы ping по заданному времени (тут 5 секунд)

Установить размер отправляемых пакетов в 1000 байт

Увеличить интервал времени пинга на 3 секунды

Утилита traceroute

Каждый пакет проходит на своем пути определенное количество узлов, пока достигнет своей цели. И, как мы уже знаем, каждый пакет имеет свое время жизни. Это количество узлов, которые может пройти пакет перед тем, как он будет уничтожен. Этот параметр записывается в заголовке TTL, каждый маршрутизатор, через который будет проходить пакет уменьшает его на единицу. При TTL=0 пакет уничтожается, а отправителю отсылается сообщение Time Exceeded.

Команда traceroute linux использует UDP пакеты. Она отправляет пакет с TTL=1 и смотрит адрес ответившего узла, дальше TTL=2, TTL=3 и так пока не достигнет цели. Каждый раз отправляется по три пакета и для каждого из них измеряется время прохождения. Пакет отправляется на случайный порт, который, скорее всего, не занят. Когда утилита traceroute получает сообщение от целевого узла о том, что порт недоступен трассировка считается завершенной.

Синтаксис утилиты не сложный:

Адресом узла может служить как IP адрес, так и доменное имя. Основные опции:

Для примера, выпоним трасировку к ресурсу yandex.ru:

В итоге, пакет прошел через 6 узлов перед тем, как дойти до указанного хоста. На каждый узел отправлялось по три пакета и для каждого из них было засечено время прохождения. И если на одном из узлов возникнет проблема, теперь вы будете знать на каком.

Иногда, вместо одного узла вы можете видеть звездочки. Это значит, что шлюзы либо не высылают нам ICMP с сообщением «time exceeded», либо у их сообщений слишком маленький TTL и оно нас не достигает. В точности нельзя сказать, что происходит на самом деле, но ясно, что по какой-то причине хост не захотел нам отвечать:

Бывает, что трассировка с помощью UDP не работает, это может произойти потому, что фаервол блокирует все лишние пакеты. Можно воспользоваться ICMP с помощью опции -I:

Рассмотреных выше простых примеров, вполне достаточно для первичной диагностики сети как для обычныз пользователей, так и для начинающих администраторов.

Утилита MTR

MTR – это альтернатива программе traceroute. Объединяя функции ping и traceroute, mtr позволяет постоянно опрашивать удаленный сервер и отслеживать изменения задержки и производительности с течением времени.

Синтаксис утилиты также несложный:

Вывод похож на traceroute, но mtr имеет существенное преимущество – ее вывод постоянно обновляется. Это позволяет собирать средние показатели, а также отслеживать тенденции и изменения производительности сети. Как и с утилитой ping, mtr будет работать бесконечно. Чтобы прервать работу команды, нужно нажать специальную клавиатурную комбинацию .

Источник

Еще несколько слов о Path MTU Discovery Black Hole

Еще несколько слов о Path MTU Discovery Black Hole

Вместо вступления

Однажды для каждого настоящего системного администратора (или исполняющего обязанности такового) наступает момент истины. Ему выпадает судьба настроить маршрутизатор на компьютере с установленной ОС GNU/Linux. Те, кто это уже прошел, знают, что ничего сложного в этом нет и можно уложиться в пару команд. И вот наш админ находит эти команды, вбивает их в консоль и гордо идет к пользователям сказать, что уже все работает. Но не тут-то было – пользователи говорят что их любимые сайты не открываются. После траты некоторой части своей жизни на выяснение подробностей обнаруживается, что большая часть сайтов ведет себя следующим образом:
1. При открытии страницы загружается заголовок и больше ничего;
2. В таком состоянии страница висит неопределенно долгое время;
3. Строка статуса браузера все это время показывает что загружает страницу;
4. Пинги и трассировка до данного сайта проходят нормально;
5. Соединение по telnet на 80 порт тоже проходит нормально.
Обескураженный админ звонит в техподдержку провайдера, но там от него быстро избавляются, советуя попробовать настроить маршрутизатор на OC Windows, а если уж и там не работает тогда… купить аппаратный маршрутизатор.
Я думаю, эта ситуация знакома многим. Некоторые в нее попадали сами, у кого-то с ней сталкивались знакомые, а кто-то встречал таких админов на форумах и прочих конференциях. Итак: если у Вас Такая Ситуация, то — Поздравляю! Вы столкнулись с Path MTU Discovering Black Hole. Данная статья посвящается тому, отчего это бывает, и как решить эту проблему.

Термины, необходимые для понимания статьи

MTU (Maximum Transmission Unit) – этот термин используется для определения максимального размера пакета (в байтах), который может быть передан на канальном уровне сетевой модели OSI. Для Ethernet это 1500 байт. Если приходит пакет большего размера (например по Token Ring), то данные пересобираются в пакеты размером не более MTU ( т е не более 1500 байт). Операция пересборки пакетов под другой MTU называется фрагментацией (fragmentation) и является затратной для маршрутизатора.
PMTU (Path MTU) — данный параметр обозначает наименьший MTU среди MTU каналов данных, находящихся между источником и приемником.
PMTU discovery – технология определения PMTU разработанная для уменьшения нагрузки на маршрутизаторы. Описана в RFC 1191 в 1988 году. Суть технологии заключается в том, что при соединении двух хостов устанавливается параметр DF (don’t fragment, не фрагментировать), который запрещает фрагментацию пакетов. Это приводит к тому, что узел, значение MTU которого меньше размера пакета, отклоняет передачу пакета и отправляет сообщение ICMP типа Destination is unreachable (Хост недоступен). К сообщению об ошибке прилагается значение MTU узла. Хост-отправитель уменьшает размер пакета и отсылает его заново. Такая операция происходит до тех пор, пока пакет не будет достаточно мал, чтобы дойти до хоста-получателя без фрагментации.
МSS(Maximum Segment Size) — максимальный размер сегмента, т.е. самая большая порция данных, которую TCP пошлет на удаленный другой конец соединения. Рассчитывается по следующей формуле:
MTU_интерфейса – Размер_IP_заголовка(20 байт) – Размер_TCP_заголовка(20 байт). Итого обычно это 1460 байт. Когда соединение устанавливается, каждая сторона может объявить свой MSS. Выбирается наименьшее значение. Подробнее можно посмотреть здесь.
Флаг DF(Don’t fragment) – Бит в поле флагов заголовка IP пакета, который будучи установленным в единицу сообщает о том, что данный пакет запрещено фрагментировать. Если пакет с таким флагом больше, чем MTU следующей пересылки, то этот пакет будет отброшен, а отправителю посылается ICMP ошибка «фрагментация необходима, однако установлен бит не фрагментировать» (fragmentation needed but don’t fragment bit set).

Тестовый полигон

С данной проблемой лучше всего знакомится на практике (но не в цейтноте, когда начальство орет над ухом). Для этого я создал тестовую сеть, изображенную на рис.1


Рис. 1. Тестовая сеть.

Это упрощенный вариант глобальной сети. Роли:
1. Компьютер с именем deb-serv-03 представляет собой наш маршрутизатор на Linux. Внимание – на его интерфейсе eth2 размер MTU уменьшен до 1400 байт;
2. deb-serv-05 – клиент в локальной сети;
3. deb-home – маршрутизатор, расположенный у провайдера;
4. deb-serv – Веб-сервер в Интернете с которым мы хотим обмениваться данными. Получаем с www.site.local, расположенном на нем страничку размером в 5,9Кб.
Конечно, в реальности цепочка гораздо больше, но для показательного примера этого хватит. Все компьютеры данной сети работают под управлением Debian GNU/Linux 5.0 Lenny. В разных точках сети я контролирую ситуацию с помощью программы tcpdump.

Читайте также:  Polyvision по для windows
Нормальное определение PMTU

Для начала посмотрим, что происходит в сети при открытии страницы. Изучаем, как пойдут пакеты с веб-сервера. Смотрим на вывод TCPDUMP#1 (на eth0 deb-serv):

1 IP 172.16.5.3.48547 > 192.168.0.1.80: Flags [S], seq 2947128725, win 5840, options [mss 1460. ], length 0
2 IP 192.168.0.1.80 > 172.16.5.3.48547: Flags [S.], seq 757312786, ack 2947128726, win 5792, options [mss 1460. ], length 0
3 IP 172.16.5.3.48547 > 192.168.0.1.80: Flags [.], ack 1, win 1460, options [. ], length 0
4 IP 172.16.5.3.48547 > 192.168.0.1.80: Flags [P.], seq 1:118, ack 1, win 1460, options [. ], length 117
5 IP 192.168.0.1.80 > 172.16.5.3.48547: Flags [.], ack 118, win 181, options [. ], length 0
6 IP 192.168.0.1.80 > 172.16.5.3.48547: Flags [.], seq 1:2897, ack 118, win 181, options [. ], length 2896
7 IP 172.16.250.2 > 192.168.0.1: ICMP 172.16.5.3 unreachable — need to frag (mtu 1400), length 556
8 IP 192.168.0.1.80 > 172.16.5.3.48547: Flags [.], seq 1:1349, ack 118, win 181, options [. ], length 1348
9 IP 192.168.0.1.80 > 172.16.5.3.48547: Flags [.], seq 1349:2697, ack 118, win 181, options [. ], length 1348
10 IP 172.16.250.2 > 192.168.0.1: ICMP 172.16.5.3 unreachable — need to frag (mtu 1400), length 556

Я привожу только первые 10 пакетов и обрезал в стандартном выводе tcpdump все лишнее. Разбираем:
1. В строках с 1-ой по 3-ю мы видим установку tcp соединения. Стороны обмениваются пакетами SYN, SYN-ACK, ACK. Здесь стоит обратить внимание на поле опций, а именно на параметр MSS, которым обмениваются стороны. С обеих сторон это 1460 байт. Значит максимальный размер пакетов, которые стороны будут посылать друг другу, составит 1460(MSS)+20(TCP Заголовок)+20(IP Заголовок)=1500 байт.
2. В строке 4 отправка запроса на получение веб страницы от deb-serv-05. В строке 5 подтверждение получения данного пакета.
3. В строке 6 мы видим отправку ответа на запрос (т.е. отправку куска веб-страницы). Вероятно из-за особенностей pcap на данном интерфейсе tcpdump видит один пакет размером в 2948 байт, в то время как в сеть уйдут 2 пакета размером 1500 и 1452 байта соответственно. Если посмотреть более подробный вывод tcpdump, то увидим, что на данном пакете(точнее пакетах) стоит флаг DF:
IP (tos 0x0, ttl 64, id 5177, offset 0, flags [DF], proto TCP (6), length 2948)
192.168.0.1.80 > 172.16.5.3.48547: Flags [.], seq 1:2897, ack 118, win 181, options [nop,nop,TS val 86620459 ecr 4922429], length 2896
4. Когда эти пакеты с данными доходят до deb-serv-03 они отбрасываются, так как не могут пройти по соединению с MTU 1400 и не могут быть фрагментированы(флаг DF), а в ответ генерируется сообщение ICMP тип 3 код 4: ICMP 172.16.5.3 unreachable — need to frag (mtu 1400), которое мы видим в строке 7 ( в строке 10 приходит сообщение для 2-го пакета). В этом сообщении передается нужный MTU.
5. В строках 8 и 9 мы наблюдаем как deb-serv, получив MTU=1400, отправляет тот же самый кусок веб страницы в пакетах размером 1400 байт. Данные пакеты доходят до deb-serv-05, где генерируется подтверждение, и так повторяется до тех пор, пока вся страница не будет передана. Размер всех последующих пакетов будет не больше 1400 байт.
На этом примере демонстрируется процедура определения Транспортного MTU (PMTU), описанная в RCF1911. Я представил ее в упрощенном виде на рис 2.


Рис 2. Процедура определения PMTU.

Встреча с Path MTU Discovery Black Hole

А теперь представим, что к провайдеру пришел новый специалист и решил (например в целях защиты от icmp флуда) запретить пересылку icmp пакетов через deb-home, который теперь в его ведении. Смотрим что получается:
Вывод TCPDUMP#1 (на eth0 deb-serv):

1 IP 172.16.5.3.57925 > 192.168.0.1.80: Flags [S], seq 1723325723, win 5840, options [mss 1460. ], length 0
2 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [S.], seq 2482933888, ack 1723325724, win 5792, options [mss 1460. ], length 0
3 IP 172.16.5.3.57925 > 192.168.0.1.80: Flags [.], ack 1, win 1460, options [. ], length 0
4 IP 172.16.5.3.57925 > 192.168.0.1.80: Flags [P.], seq 1:118, ack 1, win 1460, options [. ], length 117
5 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], ack 118, win 181, options [. ], length 0
6 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], seq 1:2897, ack 118, win 181, options [. ], length 2896
7 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], seq 1:1449, ack 118, win 181, options [. ], length 1448
8 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], seq 1:1449, ack 118, win 181, options [. ], length 1448
9 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], seq 1:1449, ack 118, win 181, options [. ], length 1448
10 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], seq 1:1449, ack 118, win 181, options [. ], length 1448

Вывод TCPDUMP#2 (на eth0 deb-serv-03):

1 IP 172.16.5.3.57925 > 192.168.0.1.80: Flags [S], seq 1723325723, win 5840, options [mss 1460. ], length 0
2 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [S.], seq 2482933888, ack 1723325724, win 5792, options [mss 1460. ], length 0
3 IP 172.16.5.3.57925 > 192.168.0.1.80: Flags [.], ack 1, win 1460, options [. ], length 0
4 IP 172.16.5.3.57925 > 192.168.0.1.80: Flags [P.], seq 1:118, ack 1, win 1460, options [. ], length 117
5 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], ack 118, win 181, options [. ], length 0
6 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], seq 1:1449, ack 118, win 181, options [. ], length 1448
7 IP 172.16.250.2 > 192.168.0.1: ICMP 172.16.5.3 unreachable — need to frag (mtu 1400), length 556
8 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], seq 1449:2897, ack 118, win 181, options [. ], length 1448
9 IP 172.16.250.2 > 192.168.0.1: ICMP 172.16.5.3 unreachable — need to frag (mtu 1400), length 556
10 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], seq 1:1449, ack 118, win 181, options [. ], length 1448
11 IP 172.16.250.2 > 192.168.0.1: ICMP 172.16.5.3 unreachable — need to frag (mtu 1400), length 556
12 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], seq 1:1449, ack 118, win 181, options [. ], length 1448
13 IP 172.16.250.2 > 192.168.0.1: ICMP 172.16.5.3 unreachable — need to frag (mtu 1400), length 556
14 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], seq 1:1449, ack 118, win 181, options [. ], length 1448
15 IP 172.16.250.2 > 192.168.0.1: ICMP 172.16.5.3 unreachable — need to frag (mtu 1400), length 556
16 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], seq 1:1449, ack 118, win 181, options [. ], length 1448
17 IP 172.16.250.2 > 192.168.0.1: ICMP 172.16.5.3 unreachable — need to frag (mtu 1400), length 556
18 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], seq 1:1449, ack 118, win 181, options [. ], length 1448
19 IP 172.16.250.2 > 192.168.0.1: ICMP 172.16.5.3 unreachable — need to frag (mtu 1400), length 556
20 IP 192.168.0.1.80 > 172.16.5.3.57925: Flags [.], seq 1:1449, ack 118, win 181, options [. ], length 1448

Как видите, ситуация вполне ожидаемая. Первые 6 строк в каждом выводе точно такие же, как и при нормальной передаче (см. описание в предыдущем примере). Но вот дальше начинаются расхождения. ICMP 3:4 точно так же генерируется на deb-serv-03 (строки 7, 9 11.13, 15, 17, 19 в TCPDUMP#2), но deb-serv его не получает и продолжает слать пакеты размером в 1500 байт(строки с 6 по 12 в TCPDUMP#1 и 6, 8, 10, 12, 14, 16, 18 и 20 в TCPDUMP#2). С каждым разом время между повторной посылкой все увеличивается (в данных примерах я отбросил временые метки, но на самом деле так работает механизм ретрансмита TCP). Никаких данных размером большим, чем PMTU, в таком случае не передать. Но увы, TCP этого не знает и продолжает слать пакеты с MSS, выбранным в момент установки соединения. Именно эта ситуация и называется Path MTU Discovery Black Hole (Черная дыра в определении транспортного MTU). Я постарался представить ее в упрощенном виде на рис. 3.


Рис. 3. Черная дыра в определении PMTU.

Эта проблема совсем не нова. Она описана в RFC 2923 в 2000 году. Но тем не менее, продолжает встречаться с завидным упорством у многих провайдеров. А ведь именно провайдер виноват в данной ситуации: не нужно блокировать ICMP тип 3 код 4. Причем слушаться «голоса разума» ( т. е. клиентов, понимающих в чем проблема) они обычно не хотят.

Решение проблемы с PMTU

Не будем звонить в техподдержку, а попробуем решить проблему, исходя из собственных средств.
Разработчики Linux, тоже знающие о ней, предусмотрели специальную опцию в iptables. Цитата из man iptables:

TCPMSS
This target allows to alter the MSS value of TCP SYN packets, to control the maximum size for that connection (usually limiting it to your outgoing interface’s MTU minus 40 for IPv4 or 60 for IPv6, respectively). Of course, it can only be used in conjunction with -p tcp. It is only valid in the mangle table. This target is used to overcome criminally braindead ISPs or servers which block «ICMP Fragmentation Needed» or «ICMPv6 Packet Too Big» packets. The symptoms of this problem are that everything works fine from your Linux firewall/router, but machines behind it can never exchange large packets:
1) Web browsers connect, then hang with no data received.
2) Small mail works fine, but large emails hang.
3) ssh works fine, but scp hangs after initial handshaking.
Workaround: activate this option and add a rule to your firewall configuration like:
iptables -t mangle -A FORWARD -p tcp —tcp-flags SYN,RST SYN \
-j TCPMSS —clamp-mss-to-pmtu

Читайте также:  Как перезапустить explorer exe windows 10

—set-mss value
Explicitly set MSS option to specified value.

—clamp-mss-to-pmtu
Automatically clamp MSS value to (path_MTU — 40 for IPv4; -60 for IPv6).

These options are mutually exclusive.

Мой вольный перевод для тех, у кого туго с английским:

TCPMSS
Это действие позволяет изменять значение MSS в TCP SYN пакетах, для контроля максимального размера пакетов в этом соединении (Обычно ограничивая его MTU исходящего интерфейса минус 40 байт для IPv4 или минус 60 для IPv6). Конечно, это действие может использоваться только в сочетании с -p tcp. Разрешено это только в таблице mangle. Это действие используется для преодоления преступной некомпетентности провайдеров и серверов, блокирующих «ICMP Fragmentation Needed» или «ICMPv6 Packet Too Big» пакеты. Симптомы этой проблемы – все прекрасно работает на вашем сетевом экране или роутере, но машины за ним никогда не смогут обмениваться большими пакетами:
1) Веб браузеры связываются, но просто висят без пересылки данных.
2) маленькие электронные письма приходят нормально, но большие висят.
3) ssh работает отлично, но scp висит после начальных рукопожатий(прим пер: процесс установки TCP соединения также называют «тройным рукопожатием»).
Решение: активировать эту опцию и добавить правило, подобное нижеприведенному, в конфигурацию своего сетевого экрана:
iptables -t mangle -A FORWARD -p tcp —tcp-flags SYN,RST SYN \
-j TCPMSS —clamp-mss-to-pmtu

—set-mss значение
Явная установка в опции MSS специфического значения.

—clamp-mss-to-pmtu
Автоматическая установка значения MSS в (path_MTU — 40 для IPv4; -60 для IPv6).
Эти опции являются взаимоисключающими.
Как видите, много всего написали, даже описали примерные симпотомы проблемы. А такое поведение провайдеров назвали «преступной некомпетентностью(criminally braindead)», в чем я с ними полностью согласен. Давайте исследуем, как же будет работать эта опция в нашем примере. Добавляем на deb-serv-03 рекомендованное правило:
iptables -t mangle -A FORWARD -p tcp —tcp-flags SYN,RST SYN -j TCPMSS –set-mss 1360
И смотрим что получилось:
Вывод TCPDUMP#1 (на eth0 deb-serv):

1 IP 172.16.5.3.33792 > 192.168.0.1.80: flags [s], seq 1484543117, win 5840, options [mss 1360. ], length 0
2 IP 192.168.0.1.80 > 172.16.5.3.33792: flags [s.], seq 2230206317, ack 1484543118, win 5792, options [mss 1460. ], length 0
3 IP 172.16.5.3.33792 > 192.168.0.1.80: flags [.], ack 1, win 1460, options [. ], length 0
4 IP 172.16.5.3.33792 > 192.168.0.1.80: flags [p.], seq 1:118, ack 1, win 1460, options [. ], length 117
5 IP 192.168.0.1.80 > 172.16.5.3.33792: flags [.], ack 118, win 181, options [. ], length 0
6 IP 192.168.0.1.80 > 172.16.5.3.33792: flags [.], seq 1:2697, ack 118, win 181, options [. ], length 2696
7 IP 172.16.5.3.33792 > 192.168.0.1.80: flags [.], ack 1349, win 2184, options [. ], length 0
8 IP 192.168.0.1.80 > 172.16.5.3.33792: flags [.], seq 2697:5393, ack 118, win 181, options [. ], length 2696
9 IP 192.168.0.1.80 > 172.16.5.3.33792: flags [fp.], seq 5393:6380, ack 118, win 181, options [. ], length 987
10 IP 172.16.5.3.33792 > 192.168.0.1.80: flags [.], ack 2697, win 2908, options [. ], length 0

Вывод TCPDUMP#3 (на eth0 deb-serv-05):

1 IP 172.16.5.3.33792 > 192.168.0.1.80: Flags [S], seq 1484543117, win 5840, options [mss 1460. ], length 0
2 IP 192.168.0.1.80 > 172.16.5.3.33792: Flags [S.], seq 2230206317, ack 1484543118, win 5792, options [mss 1360. ], length 0
3 IP 172.16.5.3.33792 > 192.168.0.1.80: Flags [.], ack 1, win 1460, options [. ], length 0
4 IP 172.16.5.3.33792 > 192.168.0.1.80: Flags [P.], seq 1:118, ack 1, win 1460, options [. ], length 117
5 IP 192.168.0.1.80 > 172.16.5.3.33792: Flags [.], ack 118, win 181, options [. ], length 0
6 IP 192.168.0.1.80 > 172.16.5.3.33792: Flags [.], seq 1:1349, ack 118, win 181, options [. ], length 1348
7 IP 192.168.0.1.80 > 172.16.5.3.33792: Flags [.], seq 1349:2697, ack 118, win 181, options [. ], length 1348
8 IP 172.16.5.3.33792 > 192.168.0.1.80: Flags [.], ack 1349, win 2184, options [. ], length 0
9 IP 172.16.5.3.33792 > 192.168.0.1.80: Flags [.], ack 2697, win 2908, options [. ], length 0
10 IP 192.168.0.1.80 > 172.16.5.3.33792: Flags [.], seq 2697:4045, ack 118, win 181, options [. ], length 1348

Разбираем:
1. В строках 1-3 мы уже привычно наблюдаем установку TCP соединения. Но обратите внимание на значения MSS. В TCPDUMP#1 от deb-serv-05 приходит значение 1360, в то время как в TCDUMP#3 видно, что уходит пакет с MSS=1460. Именно так и работает правило с –set-mss 1360. Оно редактирует значение MSS у пролетающих пакетов. Для SYN пакета, пришедшего в ответ, это значение тоже отредактировано.
2. В строках 4 и 5 обоих выводов мы опять наблюдаем отправку GET запроса и подтверждение получения.
3. В строке 6 для TCPDUMP#1 и строках 6 и7 для TCPDUMP#3 видим отправку пакетов с данными, но теперь размер каждого из пакетов не превышает 1400 байт. Опять происходит странный глюк с TCPDUMP#1, где виден один большой пакет, в то время как в TCPDUMP#3 мы наблюдаем приход 2-х пакетов.
4. Дальнейший обмен пакетами идет в соответствии с правилами протокола TCP. Но ни разу размер пакета на превышал 1400 байт.

В упрощенном виде поведение MSS представлено на рис. 4. Я не стал показывать обмен данными, так как он аналогичен обычному поведению.

Рис. 4. Изменение MSS на лету.

Хотя в man iptables описаны две опции, но я пока примененил только одну. Нужная опция зависит от конкретной ситуации. Все ситуации можно разделить на 2 типа:

1. На вашем маршрутизаторе сайты открываются нормально, у клиентов в локальной сети наблюдаются проблемы.
В этом случае наименьший MTU на всем пути находится именно на вашем сервере. Обычно это некие протоколы инкапсуляции, типа PPPoE, PPtP и тд. Для данной ситуации лучше всего подойдет опция –clamp-mss-to-pmtu, которая автоматически установит минимальный MSS на все транзитные пакеты.

2. На вашем маршрутизаторе и у клиентов в локальной сети сайты не открываются.
В таком случае наименьший MTU находится где-то у провайдера и вычислить его стандартными средствами сложновато. Специально для этого я написал небольшой скрипт на python(не особо заботясь о PEP8 и невозможности выстрелить в ногу), который поможет определить необходимый размер MSS для данной ситуации:

Запускать скрипт нужно с правами суперпользователя. Алгоритм его работы таков:
1. Пытаемся получить некоторое количество данных с сайта с нормальным значением MSS.
2. Если это не получается, то понижаем MSS на iptables цепочке OUTPUT до MTU — 40 – LIM.
3. Если и после этого мы не можем получить данные, то выдаем ошибку о том, что LIM имеет слишком маленькое значение.
4. Последовательно наращивая MSS, ищем тот момент, когда данные перестанут поступать. После этого выводим последнее рабочее значение MSS.
5. Если мы дошли до MSS=MTU-40, то выводим ошибку о том, что не можем определить MSS. Данная ситуация является ошибочной, т. к. в пункте 1 проводим аналогичную проверку, и, если результаты не совпадают, это повод задуматься.

После получения нужного MSS необходимо вписать его в соответствующее правило. Можно обойтись и без скрипта, на глаз понизив значение MSS, но лучше выяснить его точно – меньше накладые расходы на пересылку пакетов.

Часто на форумах можно встретить советы понизить MTU на том или ином интерфейсе. Нужно понимать, что это не панацея, и результат зависит от того, на каком интерфейсе понижать. Если понизим на одном из интерфейсов участников TCP соединения, то это принесет эффект, так как заявленная MSS будет соответствовать минимальному размеру пакета. Но если это будут не конечные точки, а один из транзитных маршрутизаторов, то без включения опции —clamp-mss-to-pmtu никакого эффекта не будет.

Надеюсь данная статья поможет Вам решить подобную проблему как у себя, так и у ваших друзей и знакомых. Еще раз обращаюсь к специалистам провайдеров – БЕЗ КРАЙНЕЙ НЕОБХОДИМОСТИ НЕ БЛОКИРУЙТЕ ICMP ТИП 3 КОД 4 – этим вы создаете проблемы вашим колегам.

Источник

Оцените статью