Назад | Перейти на главную страницу

Совмещение TCP, введенное сетевым узлом «человек посередине» между клиентом и сервером?

Когда трассировка wirehark выполняется на стороне клиента, она выглядит так:

---SYN--->
<-SYN-ACK-
---ACK--->
-HTTPGET->

Но когда трассировка wirehark выполняется для того же трафика на стороне сервера, это выглядит так:

---SYN--->
<-SYN-ACK-
-HTTPGET->

Где пакет HTTPGET выглядит как ACK для SYN-ACK, поскольку он имеет ту же последовательность и номер подтверждения, что и предыдущий пакет ACK.

То же самое происходит позже и наоборот:

Когда трассировка wirehark выполняется на стороне сервера, она выглядит так:

-HTTPGET->
<---ACK---
<-200-OK--

Но трассировка wirehark, взятая для того же трафика на стороне клиента, выглядит так:

-HTTPGET->
<-200-OK--

Где 200OK выглядит как ACK для HTTPGET, поскольку он имеет ту же последовательность и номер подтверждения, что и предыдущий пакет ACK.

Итак, мой вопрос, есть ли какой-либо известный сетевой элемент, который выполняет TCP-копирование как человек-посередине?

Я считаю, что это вызывает некоторые проблемы у обоих пиров, поскольку они, кажется, ждут «отсутствующего» ACK навсегда: Например:

* Дублирующий ACK для 200OK на стороне сервера, поскольку он ожидает третьего ACK в трехстороннем подтверждении связи TCP (которое было скопировано в последующий HTTPGET).

* Повторная передача HTTPGET на стороне клиента, поскольку исходный, не совмещенный ACK для него никогда не приходит.

Вот примеры трассировки: http://goo.gl/7V0pah

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

Посмотрите на опцию отметки времени, в частности посмотрите на поле значения отметки времени на пакетах от сервера к клиенту. Они исходят от сервера со значениями от 7236650 в SYN-ACK до 7246570 в последнем пакете.

Однако по получении на клиенте значение метки времени в пакете SYN-ACK было изменено на значение 1068916716. Остальные пакеты отправляются от сервера к клиенту без изменения значения метки времени.

Таким образом, с точки зрения клиентов, временная метка идет от 1068916716 до 7236708. Другими словами, она идет в обратном направлении, и это, безусловно, веская причина для клиента рассматривать пакет как неупорядоченный.

Итак, у вас есть предположение, что основная причина вашей проблемы - это искаженная временная метка в SYN-ACK.

Прежде чем прийти к такому предположению, я обнаружил много других интересных фактов из трассировки пакетов. Хотя эти другие точки данных не объясняют вашу проблему, они могут быть важными точками данных для дальнейшего исследования. Я использовал Wireshark для проверки захвата пакетов, но подойдет любой инструмент, который может декодировать все заголовки TCP.

  • Происходит какой-то NAT. Пакеты от клиента исходят с IP-адресом источника 192.168.43.87 и прибывают с IP-адресом источника 10.53.72.193. Поскольку NAT между двумя диапазонами RFC 1918 был бы необычным, я предполагаю, что происходит два уровня NAT. Я предполагаю, что 192.168.43.87 отображается на общедоступный IP-адрес рядом с клиентом, а затем на 10.53.72.193 рядом с сервером. (Учитывая количество происходящих изменений, немного удивительно, что номер клиентского порта остается неизменным.)
  • Уделяя пристальное внимание полю IPID в пакетах от клиента к серверу, я заметил следующее: они начинаются с 0x5b1f и просто увеличивая от этого значения до достижения 0x51d3 на последнем пакете. Однако на принимающей стороне первый пакет имеет другой IPID по прибытии. это 0xd5f5. Также замечаю, что пакет с ID 0x51c2 задержался и прибыл после пакета с идентификатором 0x51c4.
  • В пакете SYN, в котором было искажено поле IPID, также были переупорядочены параметры. Это не должно вызвать каких-либо проблем, но указывает на то, что промежуточный ящик полностью разделил этот SYN-пакет и создал новый, который во многих отношениях напоминал оригинал. Мы также можем видеть, что для этого конкретного пакета TTL увеличился при передаче.
  • Ни искаженный IPID, ни отброшенный пакет ACK, ни отложенная повторная передача не вызывали никаких проблем. Сервер действительно ответил на запрос, и задержанный пакет ничего не значил, потому что это была повторная передача пакета, который сервер уже получил.
  • IPID пакетов от сервера начинается с 0x0000 в пакете SYN-ACK, а затем идет от 0x2766 на втором пакете 0x2770 на последнем.
  • Только пакет с ID 0x2766 потерялся. Остальные идентификаторы поступают к клиенту по порядку.
  • Вариант масштабирования окна был изменен в полете. Сервер отправил 9, клиент получил 7.
  • Потерянный пакет - это ACK самого запроса. Потеря этого пакета объясняет, почему клиент повторно передает запрос.
  • Время, в течение которого сервер обрабатывает запрос и дает ответ, составляет более 200 мс. Задержка ACK на такой долгий срок недопустима. Можно отложить его ненадолго на тот случай, если он может быть совмещен с пакетом полезной нагрузки. Но если пакет полезной нагрузки не появляется в течение нескольких мс, предполагается, что ACK будет передан сам по себе.
  • При получении пакета с первой частью HTTP-ответа (и ACK запроса) - пакет с идентификатором 0x2767, клиент отвечает ACK порядкового номера начального SYN-ACK а не только что полученного пакета. И он игнорирует полученный ACK и продолжает повторно передавать запрос. Другими словами, клиент ведет себя так, как если бы он только что получил пакет, который не соответствует порядку. Если клиент сделал это только из-за потери ACK от сервера к клиенту, то это явно ошибка в стеке TCP на клиенте. Я подозреваю, что с этим пакетом что-то не так. Объявленный размер окна для этого пакета был увеличен при передаче от сервера к клиенту. Однако, поскольку окно далеко не полное, это вряд ли будет проблемой.
  • Обращая пристальное внимание на абсолютные порядковые номера (а не только на относительные значения, отображаемые по умолчанию в Wireshark), я заметил, что порядковые номера передаются от клиента к серверу без изменений, но изменяются при передаче от сервера к клиенту. Пока ACKed порядковые номера изменяются соответствующим образом при передаче от клиента к серверу, это не должно вызывать никаких проблем.

У задействованных промежуточных ящиков нет никакого способа вернуть все свои изменения, если они обнаружены в сообщениях об ошибках ICMP. Таким образом, я уверен, что выборочное уменьшение TTL на пакетах перед их отправкой может быть использовано для определения того, какой маршрутизатор на этом пути искажает пакеты. (За исключением случаев, когда провайдер решил отбросить все соответствующие пакеты ICMP, так что вы не сможете отлаживать проблемы, и если это так, пора было бы искать другого провайдера.)