Случайные TCP RST на определенных сайтах, что происходит?
Краткая версия: одна машина Windows Server 2012 в моей сети получает постоянные, но прерывистые TCP RST при подключении к определенным веб-сайтам. Не знаю, откуда они. Проверьте журнал Wireshark для моего анализа и вопросов.
Длинная версия:
Мы запустили кэширующий веб-прокси на одном из наших серверов для обслуживания нашего небольшого офиса. Сотрудник сообщил, что при подключении к определенным сайтам появляется много ошибок "Сброс подключения" или "Невозможно отобразить страницу", но это обновление обычно исправляет это.
Я проверил поведение браузера, а затем более непосредственно, попробовав браузер без прокси на самом сервере. Но pings & traceroutes к проблемным сайтам не показывают никаких проблем, проблемы, казалось, были ограничены соединениями tcp.
Затем я создал скрипт для тестирования уязвимых сайтов, отправляя им HTTP-запросы HEAD напрямую через cURL и проверяя, как часто они успешны. Типичный тест выглядит следующим образом: (это не прокси-сервер, работающий непосредственно на плохом сервере)
C:\sdk\Apache24\htdocs>php rhTest.php
Sending HTTP HEAD requests to "http://www.washingtonpost.com/":
20:21:42: Length: 0 Response Code: NULL (0%)
20:22:02: Length: 0 Response Code: NULL (0%)
20:22:22: Length: 0 Response Code: NULL (0%)
20:22:42: Length: 0 Response Code: NULL (0%)
20:23:02: Length: 3173 Response Code: HTTP/1.1 302 Moved Temporarily (20%)
20:23:22: Length: 3174 Response Code: HTTP/1.1 302 Moved Temporarily (33.33%)
20:23:43: Length: 0 Response Code: NULL (28.57%)
20:24:03: Length: 3171 Response Code: HTTP/1.1 302 Moved Temporarily (37.5%)
20:24:23: Length: 3173 Response Code: HTTP/1.1 302 Moved Temporarily (44.44%)
20:24:43: Length: 3172 Response Code: HTTP/1.1 302 Moved Temporarily (50%)
20:25:03: Length: 0 Response Code: NULL (45.45%)
В долгосрочной перспективе только около 60% запросов выполняются успешно, остальные ничего не возвращают, с кодом ошибки curl: "cURL error (56): сбой при получении данных от однорангового узла" тест (ни один сайт никогда не становился "лучше"), и он достаточно постоянный, я уже неделю устраняю неполадки, и коллеги сообщают, что проблема, по-видимому, была там уже несколько месяцев.
Я протестировал скрипт запроса HEAD на других машинах в нашей сети: никаких проблем, все соединения проходят через все сайты в моем списке тестов. Затем я установил прокси на своем персональном компьютере, и когда я выполняю запросы HEAD с проблемного сервера, он проходит через все соединения. Так что, какая бы ни была проблема, она очень специфична для этого сервера.
Затем я попытался определить, какие сайты демонстрируют поведение при сбросе соединения:
- Ни один из наших сайтов в интрасети (192.168.xx) не сбрасывает соединения.
- Нет сайта ipv6, который я проверял, сбрасывает соединения. (Мы двойные стеки)
- Только небольшое меньшинство интернет-сайтов ipv4 сбрасывают соединения.
- Каждый сайт, который использует cloudflare в качестве CDN (который я тестировал), сбрасывает соединения. (но проблема, кажется, не является исключительной для сайтов cloudflare)
Этот угол не превратился во что-то действительно полезное, поэтому в следующий раз я установил wireshark, чтобы посмотреть, что происходит при сбое запроса. Неудачные запросы HEAD выглядят следующим образом: (увеличенный скриншот здесь: https://imgur.com/TNfRUtX)
127 48.709776000 192.168.1.142 192.33.31.56 TCP 66 52667 > http [SYN, ECN, CWR] Seq=0 Win=8192 Len=0 MSS=8960 WS=256 SACK_PERM=1
128 48.728207000 192.33.31.56 192.168.1.142 TCP 66 http > 52667 [SYN, ACK, ECN] Seq=0 Ack=1 Win=42340 Len=0 MSS=1460 SACK_PERM=1 WS=128
129 48.728255000 192.168.1.142 192.33.31.56 TCP 54 52667 > http [ACK] Seq=1 Ack=1 Win=65536 Len=0
130 48.739371000 192.168.1.142 192.33.31.56 HTTP 234 HEAD / HTTP/1.1
131 48.740917000 192.33.31.56 192.168.1.142 TCP 60 http > 52667 [RST] Seq=1 Win=0 Len=0
132 48.757766000 192.33.31.56 192.168.1.142 TCP 60 http > 52667 [ACK] Seq=1 Ack=181 Win=42240 Len=0
133 48.770314000 192.33.31.56 192.168.1.142 TCP 951 [TCP segment of a reassembled PDU]
134 48.807831000 192.33.31.56 192.168.1.142 TCP 951 [TCP Retransmission] http > 52667 [PSH, ACK] Seq=1 Ack=181 Win=42240 Len=897
135 48.859592000 192.33.31.56 192.168.1.142 TCP 951 [TCP Retransmission] http > 52667 [PSH, ACK] Seq=1 Ack=181 Win=42240 Len=897
138 49.400675000 192.33.31.56 192.168.1.142 TCP 951 [TCP Retransmission] http > 52667 [PSH, ACK] Seq=1 Ack=181 Win=42240 Len=897
139 50.121655000 192.33.31.56 192.168.1.142 TCP 951 [TCP Retransmission] http > 52667 [PSH, ACK] Seq=1 Ack=181 Win=42240 Len=897
141 51.564009000 192.33.31.56 192.168.1.142 TCP 951 [TCP Retransmission] http > 52667 [PSH, ACK] Seq=1 Ack=181 Win=42240 Len=897
143 54.452561000 192.33.31.56 192.168.1.142 TCP 951 [TCP Retransmission] http > 52667 [PSH, ACK] Seq=1 Ack=181 Win=42240 Len=897
То, как я читаю это (поправьте меня, если я ошибаюсь, это не моя область), заключается в следующем:
- Открываем tcp соединение с веб-сервером
- веб-сервер ACK
- HTTP HEAD запрос отправлен
- Существует пакет RST, помеченный как IP-адрес веб-сервера, который разрывает соединение.
- Веб-сервер отправляет ACK
- Веб-сервер (пытается) ответить на запрос HEAD с действительными данными HTTP (951-байтовый ответ содержит правильный заголовок HTTP)
- Веб-сервер повторно передает (несколько раз в течение нескольких секунд) действительный ответ HTTP, но он не может быть успешным, так как соединение было RST
Итак, если веб-сервер отправил действительный RST, почему он продолжает пытаться выполнить запрос? И если веб-сервер не генерирует RST, что, черт возьми, сделал?
Вещи, которые я пробовал, не имели никакого эффекта:
- Отключение объединения сетевых карт
- Замена сетевого адаптера (известно, что замена сетевого адаптера работает)
- Назначение статического ip.
- Отключение ipv6.
- Отключение больших кадров.
- Подключите сервер напрямую к нашему модему за одну ночь, минуя наши коммутаторы и маршрутизатор.
- Отключение брандмауэра Windows.
- Сброс настроек TCP через netsh
- Отключение практически всех остальных сервисов на сервере. (В основном мы используем его как файловый сервер, но есть Apache и пара БД)
- Стучать головой по столу (неоднократно)
Я подозреваю, что что-то на сервере генерирует пакеты RST, но я не могу его найти. Я чувствую, как будто я знал: почему это просто этот сервер? ИЛИ почему только некоторые сайты? это очень помогло бы. Хотя мне все еще любопытно, я все больше склоняюсь к ядерному удару с орбиты и начинаю все сначала.
Идеи / Предложения?
-Спасибо
1 ответ
В захвате вашего пакета было что-то необычное: биты ECN были установлены в исходящем пакете SYN.
Явное уведомление о перегрузке - это расширение протокола IP, которое позволяет хостам быстрее реагировать на перегрузку сети. Впервые он был представлен в Интернете 15 лет назад, но при первом его развертывании были отмечены серьезные проблемы. Наиболее серьезным из них было то, что многие брандмауэры либо отбрасывали пакеты, либо возвращали RST при получении пакета SYN с установленными битами ECN.
В результате большинство операционных систем по умолчанию отключили ECN, по крайней мере, для исходящих соединений. В результате я подозреваю, что многие сайты (и производители брандмауэров!) Просто никогда не исправляли свои брандмауэры.
До выхода Windows Server 2012. Microsoft включила ECN по умолчанию, начиная с этой версии операционной системы.
К сожалению, в последнее время никто не проводил сколько-нибудь значительного тестирования ответов интернет-сайтов на ECN, поэтому трудно оценить, сохранились ли проблемы, наблюдаемые в начале 2000-х годов, но я сильно подозреваю, что они есть и что ваш трафик, по крайней мере, какое-то время проходило через такое оборудование.
После включения ECN на моем настольном компьютере и последующего запуска Wireshark прошло всего несколько секунд, прежде чем я увидел пример хоста, с которого я получил RST для пакета с установленными SYN и ECN, хотя большинство хостов, кажется, работают нормально. Может быть, я пойду сканировать Интернет сам...
Вы можете попробовать отключить ECN на своем сервере, чтобы увидеть, устранена ли проблема. Это также сделает вас неспособным использовать DCTCP, но в небольшом офисе маловероятно, что вы делаете это или у вас есть такая необходимость.
netsh int tcp set global ecncapability=disabled