О PPPoE, MTU и проблеме Path MTU Discovery Black Hole (pppoe mtu)


Предыстория

   Приехав  как-то  домой,  я вдруг обнаружил что некоторые сайты с моего
   ноутбука перестали зугружаться. Причем, на следующий день, ноутбук был
   проверен   на   работе   --   интернет  работал  и  сайты  открывались
   замечательно,  все  было  доступно.  Дома же -- только www.yandex.ru и
   www.google.com.  Да  и  то,  начиная с некоторого момента, зугружаться
   стал  только  гугл.  Причем,  веб-сайты  отлично  пинговались,  до них
   доходил  трейс  и  даже устанавливалось соединение с помощью telnet на
   80-й порт...

   Теперь  немного  о том, как я соединен с инетом. У меня дома небольшая
   локальная  сеть,  к  которой  подключены  по  wifi ноут и стационарная
   машина  на  которой  работает  отец.  Шлюзом  выступает  linux сервер,
   который  соединен  с  провайдером  по  PPPoE. По сути, такой же способ
   доступа  в интернет, через PPPoE, предлагают все dsl провайдеры (Стрим
   и   пр.).   Сначала   я  был  весьма  наивен.  И  погрешил  на  винду,
   переустановив ее с диска-реаниматора...

   Не  помогло.  Загрузился  на ноуте под линукс - те же яйца, вид сбоку.
   При  этом,  что  интересно,  на самом шлюзе все сайты замечательнейшим
   образом открывались...


Сама история

   Надо  сказать,  что  первая же мысль после этого была - посмотреть что
   там с MTU. Что я и сделал, введя ifconfig на шлюзе:




in4net ~ # ifconfig
eth0      Link encap:Ethernet  HWaddr 00:02:B3:2E:1F:86
          inet addr:82.199.102.68  Bcast:82.255.255.255  Mask:255.0.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:10031 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8405 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:5729567 (5.4 Mb)  TX bytes:1117640 (1.0 Mb)
          Interrupt:11

eth1   Link encap:Ethernet  HWaddr 00:50:70:F3:05:B5
          inet addr:192.168.0.99  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:20929 errors:0 dropped:0 overruns:0 frame:0
          TX packets:21275 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1950816 (1.8 Mb)  TX bytes:7060556 (6.7 Mb)
          Interrupt:12
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:3297 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3297 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:903591 (882.4 Kb)  TX bytes:903591 (882.4 Kb)

ppp0  Link encap:Point-to-Point Protocol
          inet addr:82.199.102.68  P-t-P:10.10.10.10  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1492  Metric:1
          RX packets:8757 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7813 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3
          RX bytes:5392618 (5.1 Mb)  TX bytes:921409 (899.8 Kb)




   Как  видим,  ppp0 соединение имеет MTU 1492. Что по сути это означает?
   Проще говоря, ваше соединение с интернет имеет окно в 1492 байт (MTU -
   Maximim Transmission Unit) - это наибольший пакет, который ваша машина
   может  передать  по  данному соединению. В тоже время, почти все веб и
   ftp серверы соединены с интернет с MTU 1500.

   Если  где-нибудь  на  пути пакета от одного хоста к другому выяснится,
   что  он  не  умещается  в  MTU  следующего  участка,  то  роутер будет
   фрагментировать  данный  пакет.  Так  произошло бы, если бы роутеры не
   использовали технологию Path MTU Discovery :-) .

   Поскольку   фрагментация  пакетов  сильно  снижает  производительность
   роутеров, то в 1988 году была предложена технология Path MTU Discoverу
   (PMTUD).  Она  описана  в RFC 1191. Суть технологии состоит в том, что
   когда  два  хоста соединяются друг с другом, то устанавливается DF бит
   "Dont  Fragmen"),  который запрещает фрагментацию пакетов на роутерах.
   Это  заставляет  роутер,  который собирается перенаправить пакет через
   соединение   с   MTU  меньше  размера  пакета,  отбрасывать  пакеты  и
   отправлять хосту-отправителю сообщение типа ICMP 3:4. Данное сообщение
   типа "Destination is unreachable" означает "Хост недоступен, поскольку
   пакет  слишком  большой  и  роутер  не  будет  его фрагментировать". В
   добавлении  к  данному  сообщению,  при  применении PMTUD, прилагается
   размер   MTU   нижестоящего   за   роутером  участка.  Таким  образом,
   хост-отправитель,  после  получения  ICMP  3:4 с информацией от PMTUD,
   уменьшает  размер  отправляемого  пакета  и пересылает его заново. Как
   итог -- пакеты доходят до хоста-получателя без фрагментации.

   Все  операционные  системы  с 1988 года поддерживают технологию PMTUD.
   Однако,  проблема  может  быть  в  том, что либо вышестоящий над вашим
   соединением роутер, либо некий роутер между вами и удаленным сервером,
   либо  сам  удаленный  веб-сервер могут БЛОКИРОВАТЬ некоторые типы ICMP
   пакетов,  включая  ICMP  3:4.  В  этом  месте  хочется передать привет
   параноидальным  администраторам  -- НЕ ДЕЛАЙТЕ ТАК, НЕ БЛОКИРУЙТЕ ICMP
   трафик! Как итог - соединение между хостами устанавливается, но пакеты
   от  одного  хоста  к  другому  не доставляются, отбрасяваясь где-то по
   пути... Похоже на наши симптомы?

   Собственно  проблема  не  нова,  ее  начали обсуждать еще в 1998 году.
   Называется она Path MTU Discovery Black Hole, и описана в RFC 2923.

   По сути, потенциально этой проблеме подвержено любой PPPoE соединение,
   поскольку  его  MTU меньше типового MTU в 1500 байт и, для прохождение
   через  PPPoE,  TCP/IP  пакет  необходимо  либо  фрагментировать,  либо
   использовать PMTUD.

   В  тоже  время,  если  у  вас обыкновенная машина с DSL модемом, вы не
   столкнетесь   с  этой  проблемой,  поскольку  на  этапе  инициализации
   соединения  с удаленными серверами размер пакета будет вычислен исходя
   из размера MTU PPPoE соединения.

   Однако,  если у вас DSL роутер (например как у меня, на базе линукса),
   то вы в зоне риска, поскольку ваша машина, при установлении соединения
   с  удаленными серверами, по умолчанию оперирует размером пакета исходя
   из  MTU  локальной  сети,  которое  установлено  в 1500. В тоже время,
   пакеты  от  удаленных  серверов  к  вам  проходят через канал роутера,
   который имеет MTU PPPoE соединения, т.е. 1492...


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

   Самый  простой  и  логичный  способ  - снятие фильтрации ICMP 3:4, как
   правило,  находится  вне  вашей  компетенции.  Поэтому решить проблему
   можно следующим способом: автоматически уменьшать размер передаваемого
   пакета  на  вашем шлюзе, либо с помошью pppd, либо с помощью iptables.
   
   При установке TCP-соединения сервер и клиент сообщают друг другу так 
   называемый максимальный размер сегмента (MSS), который каждый из них 
   сможет принять (по умолчанию на 40 байт меньше mtu интерфейса -- размер 
   заголовков ip+tcp). И далее каждый из них в рамках этого tcp-соединения 
   посылает пакеты размером не более чем min(mss+[размер заголовков], pmtu). 
   Мы меняем MSS, заставляя обе стороны посылать друг другу tcp-пакеты 
   только таких размеров, которые заведомо пролезут в наш интерфейс 
   без фрагментации.

   Для iptables есть и модуль снятия бита DF, в случае с ним шлюз бы 
   фрагментировал пакеты... В случае с корректировкой MSS 
   фрагментация просто не требуется, что является более изящным решением.
   
   Сделать это можно следующим образом.

   Используя pppd: добавить в /etc/ppp/pppoe.conf

        CLAMPMSS=1412


   Используя iptables: добавить правило

        iptables -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu  


   Идентификация  проблемы  и поиск решения у меня занял около 6 часов, в
   ходе  которых  я  анализировал  пакеты  с  помощью  tcpdump и netstat,
   выискивал  закономерность  между  открывающимися  \  не открывавшимися
   сайтами,  конфигурировал  ядро сервера, перестанавливал операционку на
   ноуте  и  задумывался  уже  над  тем  чтобы плюнуть и поставить просто
   прокси-сервер...  Проблема  усугублялась  еще и тем, что интернет мне,
   фактически,  был  недоступен....  Хотя  решение,  на самом деле, очень
   простое.


Полезные ссылки по этой теме

 http://www.phildev.net/mss/lisa.html
 
 http://tldp.org/HOWTO/IP-Masquerade-HOWTO/mtu-issues.html

Источник статьи