Я получаю значительное количество записей BADREQ в моем журнале HAProxy (10+ в минуту).
Пример:
1 октября 19:46:00 LB haproxy [19022]: 69.171.251.8:57356 [01 / Oct / 2018: 19: 46: 00.903] имя сайта имя сайта / -1 / -1 / -1 / -1 / 5 400 187 - - ПРНН 19/19/0/0/5 0/0 ""
Кажется, что почти все они исходят от краулера Facebook.
Похоже, что поисковый робот по большей части нормально очищает контент. Однако небольшое количество этих запросов приводит к ошибкам BADREQ.
Как было предложено в другом месте, я использовал socat, чтобы увидеть последнюю ошибку, выполнив следующую команду:
sudo echo "show errors" | sudo socat unix-connect:/var/run/haproxy.stat stdio
Это дало мне следующий результат:
invalid request
backend mysite (#2), server <NONE> (#-1), event #127
src 69.171.251.1:61042, session #9717, session flags 0x00000080
HTTP msg state 26, msg flags 0x00000000, tx flags 0x00000000
HTTP chunk len 0 bytes, HTTP body len 0 bytes
buffer flags 0x00808002, out 0 bytes, total 517 bytes
pending 517 bytes, wrapping at 32776, error at position 0:
00000 \x16\x03\x01\x02\x00\x01\x00\x01\xFC\x03\x03 B\x9B\xF8\xAE\xFB=\xD7dN
00021+ \x8D\xAD\xCCP\x99\x9C\xEEow#w\n
00033 \xB5\x99\x16g@\x1F{\x9A5H\x00\x00\xAA\xC00\xC0,\xC0(\xC0$\xC0\x14\xC0
00057+ \n
00058 \x00\xA5\x00\xA3\x00\xA1\x00\x9F\x00k\x00j\x00i\x00h\x009\x008\x007
00080+ \x006\xCC\xA9\xCC\xA8\xCC\x14\xCC\x13\xCC\xAA\xCC\x15\x00\x88\x00\x87
00098+ \x00\x86\x00\x85\xC02\xC0.\xC0*\xC0&\xC0\x0F\xC0\x05\x00\x9D\x00=\x005
00120+ \x00\x84\xC0/\xC0+\xC0'\xC0#\xC0\x13\xC0\t\x00\xA4\x00\xA2\x00\xA0\x00
00141+ \x9E\x00g\x00@\x00?\x00>\x003\x002\x001\x000\x00\x9A\x00\x99\x00\x98
00164+ \x00\x97\x00E\x00D\x00C\x00B\xC01\xC0-\xC0)\xC0%\xC0\x0E\xC0\x04\x00
00187+ \x9C\x00<\x00/\x00\x96\x00A\xC0\x12\xC0\x08\x00\x16\x00\x13\x00\x10
00206+ \x00\r\xC0\r\xC0\x03\x00\n
00214 \x00\xFF\x01\x00\x01)\x00\x00\x00\x14\x00\x12\x00\x00\x0Ffb.mysite.c
00242+ om\x00\x0B\x00\x04\x03\x00\x01\x02\x00\n
00254 \x00\x1C\x00\x1A\x00\x17\x00\x19\x00\x1C\x00\e\x00\x18\x00\x1A\x00\x16
00272+ \x00\x0E\x00\r\x00\x0B\x00\x0C\x00\t\x00\n
00284 \x00\r\x00 \x00\x1E\x06\x01\x06\x02\x06\x03\x05\x01\x05\x02\x05\x03
00302+ \x04\x01\x04\x02\x04\x03\x03\x01\x03\x02\x03\x03\x02\x01\x02\x02\x02
00319+ \x033t\x00\x00\x00\x10\x00\x0B\x00\t\x08http/1.1\x00\x15\x00\xAE\x00
00344+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
00361+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
00378+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
00395+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
00412+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
00429+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
00446+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
00463+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
00480+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
00497+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
00514+ \x00\x00\x00
Честно говоря, я понятия не имею, как разобраться в сказанном выше!
Обновление: мне удалось захватить трафик на порт 80 с помощью tcpdump. Я загрузил файл захвата и открыл его с помощью WinShark.
Я поймал несколько запросов с IP-адреса Facebook 31.13.127.5:
10622 15.837038 31.13.127.5 MYSERVERIP TCP 66 47658 → 80 [ACK] Seq=1 Ack=1 Win=61440 Len=0 TSval=1921577847 TSecr=59275252
10701 15.848790 31.13.127.5 MYSERVERIP TCP 583 47658 → 80 [PSH, ACK] Seq=1 Ack=1 Win=61440 Len=517 TSval=1921577859 TSecr=59275252
10702 15.848846 MYSERVERIP 31.13.127.5 HTTP 253 HTTP/1.0 400 Bad request (text/html)
10914 15.927603 31.13.127.5 MYSERVERIP TCP 66 47658 → 80 [FIN, ACK] Seq=518 Ack=189 Win=63488 Len=0 TSval=1921577937 TSecr=59275274
10915 15.927611 MYSERVERIP 31.13.127.5 TCP 66 80 → 47658 [ACK] Seq=189 Ack=519 Win=30080 Len=0 TSval=59275294 TSecr=1921577937
12044 17.419319 31.13.127.5 MYSERVERIP TCP 74 53712 → 80 [SYN] Seq=0 Win=61320 Len=0 MSS=1460 SACK_PERM=1 TSval=1921579431 TSecr=0 WS=2048
12045 17.419337 MYSERVERIP 31.13.127.5 TCP 74 80 → 53712 [SYN, ACK] Seq=0 Ack=1 Win=28960 Len=0 MSS=1460 SACK_PERM=1 TSval=59275667 TSecr=1921579431 WS=128
12125 17.493182 31.13.127.5 MYSERVERIP TCP 66 53712 → 80 [ACK] Seq=1 Ack=1 Win=61440 Len=0 TSval=1921579505 TSecr=59275667
12126 17.501269 31.13.127.5 MYSERVERIP TCP 583 53712 → 80 [PSH, ACK] Seq=1 Ack=1 Win=61440 Len=517 TSval=1921579513 TSecr=59275667
12127 17.501387 MYSERVERIP 31.13.127.5 HTTP 253 HTTP/1.0 400 Bad request (text/html)
12179 17.576974 31.13.127.5 MYSERVERIP TCP 66 53712 → 80 [FIN, ACK] Seq=518 Ack=189 Win=63488 Len=0 TSval=1921579589 TSecr=59275687
В этом журнале вы видите приветственное сообщение клиента TLS.
Это начальное сообщение, отправленное клиентом для инициирования согласования, следовательно, в этом сообщении нет ничего зашифрованного. Вы заметите, что в этом сообщении есть два поля, содержащих текст. Это поля следующего протокола: SNI (указание имени сервера) и ALPN (согласование протокола прикладного уровня). Остальная часть сообщения представляет собой двоичные данные, поэтому их не так легко читать.
На этой ранней стадии TLS протокол прикладного уровня еще не согласован, и ключи сеанса не установлены. Клиент даже не получил сертификат, который он мог бы проверить. Это означает, что клиент еще не может отправить какой-либо HTTP-запрос, а при отсутствии HTTP-запроса нет ничего, на что можно было бы отправить код состояния в ответ.
Запись в журнале определенно звучит так, будто HAProxy думает, что отвечает на HTTP-запрос, даже если он не был отправлен.
Исходя из этого, похоже, что здесь происходит то, что сервер говорит HTTP, а клиент говорит HTTPS. Таким образом, сообщение приветствия клиента TLS неправильно интерпретируется как HTTP-запрос и отклоняется как недействительное.
Вам было бы полезно захватывать трафик, чтобы его можно было проверить, чтобы узнать, что на самом деле отправляется по сети. Если я прав относительно сказанного выше, вы должны увидеть сообщение TLS Client Hello, которое можно декодировать с помощью Wireshark (или аналогичного), и незашифрованный HTTP-ответ с кодом ошибки 400.
Что также будет интересно в этом захвате пакета, так это номер порта.
Вы можете увидеть, что могло произойти, если пользователь ввел URL-адрес с протоколом и номером порта, например https://example.com:80/
и facebook пытается получить этот URL несколько раз (поскольку он продолжает терпеть неудачу).
Я сам попытался поместить такой искаженный URL в facebook, и конечно же facebook отправил сообщение Client Hello на порт 80. Мой (Apache) веб-сервер ответил кодом состояния 400, как и ожидалось.
Захват вашего пакета подтверждает, что трафик в вашем случае также происходит через порт 80. Предположительно, кто-то дал facebook URL-адрес https, указывающий на ваш сайт и заменив вместо этого правильный номер порта на 80.
Ваш сервер правильно отвечает кодом 400, и facebook понимает, что получение URL-адреса не удалось. Исправлять нечего. Ваш сервер работает как задумано, и единственной проблемой была ошибка пользователя при вводе URL-адреса в facebook.
Можно узнать немного больше о неверном URL-адресе, если ваш сервер автоматически определит протокол, чтобы поддерживать как HTTP, так и HTTPS на одном и том же порту. Однако я бы не рекомендовал такие хаки, и я не знаю, поддерживает ли это какое-либо программное обеспечение веб-сервера.