У меня очень странная проблема с некоторыми пакетами, которые не приходят на целевой хост. Это происходит, когда мы передаем POST, размер которого несколько превышает MTU. Мы можем воспроизвести это с помощью этого скрипта:
#!/usr/bin/python
import urllib2
magic_length = 2297
logurl = 'http://www.example.nl/'
data = (magic_length - len(logurl)) * 'X'
headers = {'content-type': 'application/x-www-form-urlencoded', 'User-Agent': 'Fake'}
request = urllib2.Request(logurl, data, headers)
handler = urllib2.build_opener(urllib2.HTTPHandler())
answer = handler.open(request, timeout=5)
Отправляющая сторона не получает ACK и выполняет повторные передачи. Принимающая сторона никогда этого не видит.
Это зависит от того, где вы запускаете скрипт и куда вы отправляете POST. Мое домашнее соединение не работает (и, кстати, у меня были проблемы с тем, что сообщения AJAX POST не проходили уже несколько месяцев; у меня новый модем).
Если я уменьшу MTU отправляющей машины на 100, он снова заработает. Но если я уменьшу magic_length
на 100 он снова терпит неудачу. Первая теория заключалась в том, что уровень моего ADSL (например, PPPoA) добавляет заголовки и вызывает ошибочное разделение пакетов, но тогда, похоже, это не так.
Возможно, что-то пойдет не так с обнаружением MTU. Возможно, кто-то заблокирует все ICMP? Это первая часть трассировки в Google из моего дома:
traceroute to google.com (74.125.133.102), 30 hops max, 60 byte packets
1 dsldevice.lan (192.168.2.254) 0.453 ms 0.547 ms 0.636 ms
2 195.190.243.7 (195.190.243.7) 29.836 ms 29.947 ms 29.986 ms
3 nl-zl-dc2-git-cr02.kpn.net (213.75.64.237) 37.004 ms 37.153 ms 37.204 ms
4 nl-rt-dc2-ice-ir02.kpn.net (213.75.64.236) 37.261 ms 37.300 ms 37.339 ms
5 72.14.198.161 (72.14.198.161) 38.351 ms 38.395 ms 38.405 ms
6 209.85.254.92 (209.85.254.92) 37.976 ms 38.103 ms 37.972 ms
7 209.85.253.247 (209.85.253.247) 38.612 ms 72.14.238.153 (72.14.238.153) 33.709 ms 209.85.253.249 (209.85.253.249) 36.890 ms
8 209.85.240.158 (209.85.240.158) 41.052 ms 41.104 ms 209.85.244.102 (209.85.244.102) 41.164 ms
9 209.85.249.12 (209.85.249.12) 38.392 ms 209.85.249.14 (209.85.249.14) 38.247 ms 38.851 ms^C
Если я пингую 213.75.64.237, я получаю (я никогда не видел, чтобы «пакет фильтровался» как ответ на STDOUT ...):
PING 213.75.64.237 (213.75.64.237) 56(84) bytes of data.
From 213.75.64.237 icmp_seq=1 Packet filtered
Остальное могу пинговать.
Этот ответ похоже. Однако мой скрипт не устанавливает флаг DF (не фрагментировать) (edit: исправление, tcpdmp показывает, что флаг установлен в запросе POST), и я не вижу, чтобы запросы ICMP возвращались мне, когда я запускаю скрипт на хосте, который делает работай. Кроме того, пакеты уже разделены отправителем, и отправить второй пакет не удается.
Как мне продолжить? Интернет-провайдеры NOC и так достаточно труднодоступны, поэтому мне нужно иметь доказательства того, что происходит. Они не помогут мне разобраться ...
Изменить: чтобы подтвердить или опровергнуть гипотезы ICMP типа 4 (требуется фрагментация), я сделал следующее:
$ ping -c 1 -M do -s 1472 host
PING host (1.2.3.4) 1472(1500) bytes of data.
1480 bytes from host (1.2.3.4): icmp_req=1 ttl=50 time=33.8 ms
Это работает, но я немного запутался. Означает ли "(1500)" общий размер фрагмента? Я предполагаю это, потому что 1480 байт + 20 байт IP-заголовок составляет 1500 байт.
Если я увеличу размер пинга на единицу:
$ ping -c 1 -M do -s 1473 host
PING host (1.2.3.4) 1473(1501) bytes of data.
From pannekoek.lan (192.168.2.5) icmp_seq=1 Frag needed and DF set (mtu = 1500)
Таким образом, это будет означать, что путь между двумя хостами разрешает пакеты размером 1500 байт и проблем с фрагментацией не возникает. Кажется, я вернулся на круги своя.
Снова отредактируйте: я нашел кое-что значимое. Проблема просто в том, что пакеты определенного размера не приходят. Это происходит между моим модемом и первым шлюзом провайдера:
$ for i in `seq 1025 1030`; do ping -c 1 -M do -s $i 195.190.243.7; done
PING 195.190.243.7 (195.190.243.7) 1025(1053) bytes of data.
1033 bytes from 195.190.243.7: icmp_req=1 ttl=254 time=31.2 ms <- works
--- 195.190.243.7 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 31.273/31.273/31.273/0.000 ms
==========================
PING 195.190.243.7 (195.190.243.7) 1026(1054) bytes of data.
--- 195.190.243.7 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms <- packet loss
==========================
PING 195.190.243.7 (195.190.243.7) 1027(1055) bytes of data.
--- 195.190.243.7 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms <- packet loss
==========================
PING 195.190.243.7 (195.190.243.7) 1028(1056) bytes of data.
--- 195.190.243.7 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms <- packet loss
==========================
PING 195.190.243.7 (195.190.243.7) 1029(1057) bytes of data.
--- 195.190.243.7 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms <- packet loss
==========================
PING 195.190.243.7 (195.190.243.7) 1030(1058) bytes of data.
1038 bytes from 195.190.243.7: icmp_req=1 ttl=254 time=31.1 ms <- works
--- 195.190.243.7 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 31.177/31.177/31.177/0.000 ms
Думаю, мне нужно убедить их, что это их проблема.
Где-то на линии от точки A до точки B маршрутизатор был настроен с меньшим значением MTU, и именно это ломает работу. Вы пробовали выполнить трассировку, чтобы увидеть, где именно теряются ICMP-пакеты?