Как эффективно отладить проблему HTTP-запроса на моем веб-сервере?
1182
Horseman
У меня странная проблема с моим веб-сервером в локальной сети. HTTP-запросы вращаются вечно, но не дают значимого кода ошибки.
Эта проблема возникает на моем маршрутизаторе ASUS и маршрутизаторе Cisco, но, как это ни парадоксально, на моем старом маршрутизаторе DLink это не происходит. Некоторый анализ различий ниже.
[Обновление 19 февраля, 22:30] Я попытался переключиться с Apache на сервер Nginx (основываясь на комментариях Кевина), и они показали идентичный результат. Похоже, что проблемы с пакетами TCP не зависят от сервера (см. Tcpdumps ниже). Я также экспериментировал с размером TCP-datapush и обнаружил, что вероятность сбоя уменьшается с размером запроса. Когда меньше чем ~ 800 байт, ему удается загрузить примерно половину времени после зацикливания 5-10 до получения этого редкого ACK. При ~ 2000 байтах это редко, но иногда работает. На ~ 6000 байтов, никак. Маршрутизатор DLink работает мгновенно на любом из этих размеров файлов. Я проверил, нет ли каких-либо мешающих пакетов на интерфейсе обратной связи, ничего там. Я переключил кабели / порты (но не сетевые карты, только один).
Я попытался использовать telnet для выполнения ручного HTTP-запроса для простой страницы:
telnet 192.168.0.101 80 GET /index.html HTTP/1.0
Та же самая проблема появляется там, висящая в течение нескольких секунд.
Дамп tcpdump, похоже, указывает на отсутствующий пакет «ACK 2921», следующий за Push-пакетом. Затем сервер повторяет пакет Push, по-прежнему без подтверждения. Затем он выполняет серию последовательных ACK 1: 1461 перед завершающим F-пакетом, похоже, сдаваясь.
Я не эксперт по пакетам tcp, но это от анализа сбойного случая (маршрутизатор ASUS) по сравнению с успешным случаем (маршрутизатор Dlink). На DLink есть чистый пакет ACK 2921. До этого оба показывают одинаковый вывод.
Одно очевидное отличие состоит в том, что с DLink сервер видит клиента по его IP (192.168.0.104), тогда как на ASUS сервер видит клиента по его имени хоста (Gin) - но экспериментирует с правилами третьего маршрутизатора (Cisco) это является частью проблемы, поскольку он также видит клиента по IP, но в остальном ведет себя так же, как ASUS.
simon@fire:~$ sudo tcpdump -i eth0 port 80 or port 443 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 19:43:37.815448 IP Gin.60309 > fire.http: Flags [S], seq 4284943091, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0 19:43:37.815490 IP fire.http > Gin.60309: Flags [S.], seq 1854464822, ack 4284943092, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0 19:43:37.815684 IP Gin.60309 > fire.http: Flags [.], ack 1, win 16425, length 0 19:43:37.816701 IP Gin.60309 > fire.http: Flags [P.], seq 1:344, ack 1, win 16425, length 343: HTTP: GET / HTTP/1.1 19:43:37.816729 IP fire.http > Gin.60309: Flags [.], ack 344, win 237, length 0 19:43:37.818341 IP fire.http > Gin.60309: Flags [.], seq 1:2921, ack 344, win 237, length 2920: HTTP: HTTP/1.1 200 OK 19:43:37.818357 IP fire.http > Gin.60309: Flags [P.], seq 2921:4155, ack 344, win 237, length 1234: HTTP -- There seems to be a missing [.] ack 2921 packet here!? Then the server tries again -- 19:43:37.827311 IP fire.http > Gin.60309: Flags [P.], seq 2921:4155, ack 344, win 237, length 1234: HTTP 19:43:38.051329 IP fire.http > Gin.60309: Flags [.], seq 1:1461, ack 344, win 237, length 1460: HTTP: HTTP/1.1 200 OK 19:43:38.499322 IP fire.http > Gin.60309: Flags [.], seq 1:1461, ack 344, win 237, length 1460: HTTP: HTTP/1.1 200 OK 19:43:39.395318 IP fire.http > Gin.60309: Flags [.], seq 1:1461, ack 344, win 237, length 1460: HTTP: HTTP/1.1 200 OK 19:43:41.191327 IP fire.http > Gin.60309: Flags [.], seq 1:1461, ack 344, win 237, length 1460: HTTP: HTTP/1.1 200 OK 19:43:42.823524 IP fire.http > Gin.60309: Flags [F.], seq 4155, ack 344, win 237, length 0 19:43:42.823736 IP Gin.60309 > fire.http: Flags [.], ack 1, win 16425, length 0 19:43:44.783318 IP fire.http > Gin.60309: Flags [.], seq 1:1461, ack 344, win 237, length 1460: HTTP: HTTP/1.1 200 OK 19:43:51.967338 IP fire.http > Gin.60309: Flags [.], seq 1:1461, ack 344, win 237, length 1460: HTTP: HTTP/1.1 200 OK 19:43:52.825832 IP Gin.60309 > fire.http: Flags [.], seq 343:344, ack 1, win 16425, length 1: HTTP 19:43:52.825875 IP fire.http > Gin.60309: Flags [.], ack 344, win 237, options [nop,nop,sack 1 ], length 0 19:44:02.826426 IP Gin.60309 > fire.http: Flags [.], seq 343:344, ack 1, win 16425, length 1: HTTP 19:44:02.826464 IP fire.http > Gin.60309: Flags [.], ack 344, win 237, options [nop,nop,sack 1 ], length 0 19:44:06.335330 IP fire.http > Gin.60309: Flags [.], seq 1:1461, ack 344, win 237, length 1460: HTTP: HTTP/1.1 200 OK 19:44:12.827029 IP Gin.60309 > fire.http: Flags [.], seq 343:344, ack 1, win 16425, length 1: HTTP 19:44:12.827067 IP fire.http > Gin.60309: Flags [.], ack 344, win 237, options [nop,nop,sack 1 ], length 0 19:44:22.827563 IP Gin.60309 > fire.http: Flags [.], seq 343:344, ack 1, win 16425, length 1: HTTP 19:44:22.827592 IP fire.http > Gin.60309: Flags [.], ack 344, win 237, options [nop,nop,sack 1 ], length 0 19:44:32.828133 IP Gin.60309 > fire.http: Flags [.], seq 343:344, ack 1, win 16425, length 1: HTTP 19:44:32.828157 IP fire.http > Gin.60309: Flags [.], ack 344, win 237, options [nop,nop,sack 1 ], length 0 19:44:35.039322 IP fire.http > Gin.60309: Flags [.], seq 1:1461, ack 344, win 237, length 1460: HTTP: HTTP/1.1 200 OK 19:44:42.828692 IP Gin.60309 > fire.http: Flags [.], seq 343:344, ack 1, win 16425, length 1: HTTP 19:44:42.828734 IP fire.http > Gin.60309: Flags [.], ack 344, win 237, options [nop,nop,sack 1 ], length 0 19:45:08.571555 IP Gin.60309 > fire.http: Flags [F.], seq 344, ack 1, win 16425, length 0 19:45:08.571581 IP fire.http > Gin.60309: Flags [.], ack 345, win 237, length 0 (Pressed CTRL C after 30 seconds) ^C 32 packets captured 32 packets received by filter 0 packets dropped by kernel
Tcpdump при использовании роутера DLink (работает нормально) ниже:
simon@fire:/sbin$ sudo tcpdump -B 4096 -i eth0 port 80 or port 443 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 21:48:20.209920 IP 192.168.0.104.53696 > fire.http: Flags [S], seq 1043812686, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0 21:48:20.209954 IP fire.http > 192.168.0.104.53696: Flags [S.], seq 639467520, ack 1043812687, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0 21:48:20.210290 IP 192.168.0.104.53696 > fire.http: Flags [.], ack 1, win 16425, length 0 21:48:20.211575 IP 192.168.0.104.53696 > fire.http: Flags [P.], seq 1:344, ack 1, win 16425, length 343: HTTP: GET / HTTP/1.1 21:48:20.211603 IP fire.http > 192.168.0.104.53696: Flags [.], ack 344, win 237, length 0 21:48:20.213190 IP fire.http > 192.168.0.104.53696: Flags [.], seq 1:2921, ack 344, win 237, length 2920: HTTP: HTTP/1.1 200 OK 21:48:20.213199 IP fire.http > 192.168.0.104.53696: Flags [P.], seq 2921:4155, ack 344, win 237, length 1234: HTTP 21:48:20.213959 IP 192.168.0.104.53696 > fire.http: Flags [.], ack 2921, win 16425, length 0 21:48:20.415317 IP fire.http > 192.168.0.104.53696: Flags [P.], seq 2921:4155, ack 344, win 237, length 1234: HTTP 21:48:20.416066 IP 192.168.0.104.53696 > fire.http: Flags [.], ack 4155, win 16116, options [nop,nop,sack 1 ], length 0 21:48:25.215387 IP fire.http > 192.168.0.104.53696: Flags [F.], seq 4155, ack 344, win 237, length 0 21:48:25.215864 IP 192.168.0.104.53696 > fire.http: Flags [.], ack 4156, win 16116, length 0 21:48:25.216086 IP 192.168.0.104.53696 > fire.http: Flags [F.], seq 344, ack 4156, win 16116, length 0 21:48:25.216093 IP fire.http > 192.168.0.104.53696: Flags [.], ack 345, win 237, length 0 ^C 14 packets captured 14 packets received by filter 0 packets dropped by kernel
Я также проверил брандмауэр, не обнаружил пакетов, соответствующих правилам «Запретить», а также выполнил рекомендованную команду iptables, но это не помогло: / sbin / iptables -I INPUT -p tcp --dport 80 -j ПРИНЯТЬ
Подобная проблема возникает, если я пытаюсь получить доступ к Интернету с сервера через порт 80 (очень медленный, крутится или иногда может загрузить простую страницу через очень долгое время).
Это сервер LAMP (Ubuntu 16.4).
Заранее спасибо!
`телнет` в 21 веке ??? Вы смелы ... Если этот сервер сталкивается с диким интернетом, то я настоятельно рекомендую вам перейти на SSH. О вашей проблеме запустите `sudo netstat -lntp` и добавьте ее результат к вашему вопросу.
Alex 7 лет назад
0
Спасибо, Алекс. Я добавил вывод netstat -lntp в вопрос. Есть что-нибудь интересное? :)
Horseman 7 лет назад
0
@Alex - `telnet` здесь используется не для выдачи команд, а просто для выдачи необработанного HTTP-запроса. Хотя `nc` немного лучше для этого, это не риск для безопасности. Угроза безопасности заключается в запуске telnet * server *, а не в использовании команды telnet * * для ручной отправки данных через сокет.
LawrenceC 7 лет назад
0
@LawrenceC Согласитесь, когда я вижу, что люди все еще используют серверы telnet в наши дни, это сказывается на мне, как на красной драке в бычьих боях, но согласно выводу `netstat`, сервер OP прослушивает входящие соединения через порт 23, так что это все еще так. , В любом случае, я ценю ваш комментарий;) перед выводом `netstat` это звучит как не очень хороший комментарий с моей стороны!
Alex 7 лет назад
0
ага, чёрт, да, теперь, когда я внимательно посмотрел, вы правы.
LawrenceC 7 лет назад
0
2 ответа на вопрос
1
Kevin
Вы пробовали запустить tcpdump на сервере?
sudo tcpdump -i eth0 port 80 or port 443
Если вы не видите пакеты, вам может потребоваться дважды проверить брандмауэр.
Вы также можете отключить Apache и запустить временный веб-сервер Netcat на порт 80 с
Вы можете использовать tcpdump для записи в файл, а затем передать и открыть его на клиентском компьютере с помощью wireshark, чтобы увидеть, какая информация передается в пакетах.
sudo tcpdump -i eth0 port 80 or port 443 -w httpdebug.pcap
Затем скопируйте этот файл на компьютер с wireshark. Если вам нужно установить wireshark на машине с Windows, вы можете пропустить установку winpcap.
Некоторые другие шаги, которые вы можете попробовать:
При использовании apache файл с "Hello World!" или что-то очень короткое в этом.
Использование веб-сервера netcat для размещения вашего index.html
Если последнее работает, то может быть либо много контента, блокирующего рендеринг, либо некоторая неверная конфигурация в apache. Я бы попробовал очистить и переустановить apache, а не искать проблему с конфигурацией.
+1 для проверки брандмауэра: попробуйте запустить "/ sbin / iptables -I INPUT -p tcp --dport 80 -j ПРИНЯТЬ на сервере, чтобы разрешить ему принимать трафик через порт 80 до перезагрузки / перезапуска брандмауэра.
davidgo 7 лет назад
0
Большое спасибо Кевину и Дэвидго - я добавил в описание информацию tcpdump и netcat. Также попробовал iptables (без помощи). netcat работает на порте 80. TCPdump, кажется, показывает, что он повторяет один и тот же запрос снова и снова ... но фактически нет пропущенных пакетов ?!
Horseman 7 лет назад
0
Это не обязательно хороший ответ (исправление вашей проблемы), но вы рассматривали возможность запуска nginx перед или заменой apache. Я использую nginx и обнаружил, что его гораздо проще настроить и использовать. Он также (предположительно) гораздо эффективнее в обслуживании статического контента.
Kevin 7 лет назад
0
Кевин, я не слышал о nginx, я посмотрю его, но надеюсь, что смогу решить эту проблему и с помощью apache.
Horseman 7 лет назад
0
Для tcpdump, кажется, отсутствует ACK 2921, который соответствует push-пакету ... и, что интересно, на другом маршрутизаторе, где сервер видит клиента только по его IP и записывает его имя хоста "Gin", все работает, и я Я обновлю описание с некоторой дополнительной информацией по этому вопросу. 19: 43: 37.818357 IP fire.http> Gin.60309: Flags [P.], seq 2921: 4155, ack 344, win 237, длина 1234: HTTP - здесь отсутствует ACK для 2921, и он никогда не приходит. - 19: 43: 37.827311 IP fire.http> Gin.60309: Флаги [P.], след. 2921: 4155, подтверждение 344, выигрыш 237, длина 1234: HTTP
Horseman 7 лет назад
0
@kevin Интересное новое назначение данных, я попытался удалить Apache и перейти на Nginx. Установка была очень простой (довольно приятной), но это приводит к идентичному результату. Так что, возможно, проблема в том, что слой выше веб-сервера, что-то с TCP ... но все же маршрутизатор dlink почему-то работает как по волшебству.
Horseman 7 лет назад
0
@ Horseman Я думаю, это как-то связано с маршрутизацией / коммутацией в вашей сети. Не совсем уверен, как вы могли бы отладить / исправить это все же.
Kevin 7 лет назад
0
0
Alex
Согласно sudo netstat -lntpвыводу, ваши apacheнастройки не прослушивают IPv4.
Вам необходимо добавить в конфигурацию вашего apache:
#NameVirtualHost *:80 Listen 0.0.0.0:80
Если вы используете протокол SSL на своем сайте, добавьте также:
Эти настройки применяются к версиям Apache 2.4 +. Если вы используете версии 2.2, то добавьте также
NameVirtualHost *:80 NameVirtualHost *:443
в (apache|httpd|ports)\.conf
Я обновил его, как вы упомянули, но это не помогло. Что касается исследования, то похоже, что IPv4 и v6 работают в предыдущих настройках, но netstat просто представляет его как tcp6, некоторая информация об этом здесь [link] (http://unix.stackexchange.com/questions/106502/apache2-does -на-выбег-ipv4-ТСР-порт)
Horseman 7 лет назад
0
@ Horseman "похоже, что и IPv4, и v6 работают в предыдущих настройках, но netstat просто представляет его как tcp6" - Нет, так не должно быть. Если вы использовали `Listen 0.0.0.0: 80`, это эффективно отключает слушателя на TCP6. Вы переустанавливали свой сервер Apache (`sudo service apache2 restart`) после того, как добавили изменения, о которых я упоминал?
Alex 7 лет назад
0
да, перезапустил сервер. Проблема, похоже, не связана с ipv4 / v6. (с тех пор попробовал сервер nginx с включенным ipv4 / v6)
Horseman 7 лет назад
0
@ Horseman Можете ли вы получить какой-либо вывод из этой команды: `wget -O - http: // 127.0.0.1`? Не могли бы вы также добавить вывод `ifconfig` и` iptables -L -n`
Alex 7 лет назад
0
Я добавил вывод ifconfig и iptables выше. Использование wget -O - http://127.0.0.1, кажется, работает хорошо, сразу показывает полную HTML-страницу. Спасибо, что продолжаете давать предложения, ты мой спасательный круг: о)
Horseman 7 лет назад
0