Справочная информация: долгое время у нас были проблемы с нашим брандмауэром, из-за которого HTTP-запросы иногда зависали частично загруженными до истечения времени ожидания TCP.
После отслеживания трафика на брандмауэре я заметил, что это происходит только в определенных временных условиях, например, когда веб-сервер отправил весь ответ до того, как клиент отправил свой второй ACK для полезной нагрузки. [SYN, SYN / ACK, ACK] был обменен, REQUEST был отправлен и ACK'ed, и первый пакет RESPONSE был получен и ACK'ed, затем веб-сервер отправляет остальную часть тела ответа за один раз (8 пакетов включая последний FIN, PSH) и до того, как клиент подтвердит какое-либо из них, брандмауэр ОТКАЗЫВАЕТСЯ с RST в направлении веб-сервера и держит клиента в бесконечном зависании.
Вот вся трассировка wirehark с пакетами с обеих сторон межсетевого экрана. 192.168.126.161 - это частный IP-адрес клиента NAT. 172.16.1.2 - это IP-адрес веб-сервера (не показывающий реальный публичный IP-адрес), а 10.1.1.1 - это внешний IP-адрес брандмауэра (не показывающий реальный публичный IP-адрес)
2105 0.086275 192.168.126.161 172.16.1.2 TCP 37854 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSV=89375083 TSER=0
2106 0.000066 10.1.1.1 172.16.1.2 TCP 37854 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSV=89375083 TSER=0
2107 0.002643 172.16.1.2 10.1.1.1 TCP http > 37854 [SYN, ACK] Seq=0 Ack=1 Win=32768 Len=0 MSS=1460
2108 0.007705 172.16.1.2 192.168.126.161 TCP http > 37854 [SYN, ACK] Seq=0 Ack=1 Win=32768 Len=0 MSS=1460
2109 0.006301 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=1 Ack=1 Win=5840 Len=0
2110 0.000025 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=1 Ack=1 Win=5840 Len=0
2111 0.000007 192.168.126.161 172.16.1.2 HTTP GET /test/style.css HTTP/1.1
2112 0.000015 10.1.1.1 172.16.1.2 HTTP GET /test/style.css HTTP/1.1
2113 0.001536 172.16.1.2 10.1.1.1 TCP http > 37854 [ACK] Seq=1 Ack=111 Win=32658 Len=0
2114 0.000014 172.16.1.2 192.168.126.161 TCP http > 37854 [ACK] Seq=1 Ack=111 Win=32658 Len=0
2115 0.002274 172.16.1.2 10.1.1.1 HTTP HTTP/1.1 200 OK (text/css)
2116 0.000025 172.16.1.2 192.168.126.161 HTTP HTTP/1.1 200 OK (text/css)
2117 0.005689 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=1461 Win=8760 Len=0
2118 0.000024 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=1461 Win=8760 Len=0
2119 0.001536 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2120 0.000026 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2121 0.000007 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2122 0.000023 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2123 0.000313 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2124 0.000030 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2125 0.000007 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2126 0.000023 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2127 0.000009 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2128 0.000023 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2129 0.001108 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2130 0.000035 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2131 0.000008 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
2132 0.000022 172.16.1.2 192.168.126.161 HTTP Continuation or non-HTTP traffic
2133 0.000007 172.16.1.2 10.1.1.1 HTTP Continuation or non-HTTP traffic
REJECT-->
2134 0.000089 10.1.1.1 172.16.1.2 TCP 37854 > http [RST] Seq=111 Win=0 Len=0
CLIENT FIRST ACK-->
2135 0.002421 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=2921 Win=11680 Len=0
2136 0.000033 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=2921 Win=11680 Len=0
2137 0.000007 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=4381 Win=14600 Len=0
2138 0.000014 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=4381 Win=14600 Len=0
2139 0.000008 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=5841 Win=17520 Len=0
2140 0.000014 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=5841 Win=17520 Len=0
2141 0.000007 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=7301 Win=20440 Len=0
2142 0.000013 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=7301 Win=20440 Len=0
2143 0.000007 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=8761 Win=23360 Len=0
2144 0.000015 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=8761 Win=23360 Len=0
2145 0.000007 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=10221 Win=26280 Len=0
2146 0.000013 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=10221 Win=26280 Len=0
2147 0.001059 192.168.126.161 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=11681 Win=29200 Len=0
2148 0.000018 10.1.1.1 172.16.1.2 TCP 37854 > http [ACK] Seq=111 Ack=11681 Win=29200 Len=0
Я копал и регистрировал обход пакетов в соответствии с этим диаграмма и кажется, что последний входящий пакет 2133 проходит через raw-PREROUTING, conntrack, mangle-PREROUTING, но затем теряется. У меня нет правил REJECT в моих iptables, я регистрирую все правила DROP, и ни одно из них не показывает, где теряется пакет 2133.
Я бы хотел использовать цель TRACE во входящем фильтре, но, к сожалению, ubuntu 8.04 не поставляется с поддержкой цели TRACE.
Поэтому я считаю, что применяются некоторые внутренние правила неявной маршрутизации / conntrack / mangling, которые по какой-то причине сбрасывают соединение. Возможно, трафик вызывает некоторую защиту DOS, но я не знаю, где это настраивать / анализировать. Самое неприятное, что пакет отклоняется и ничего не регистрируется ...
Также запрос этого файла работает на 100% с хостов Windows, но он не работает на определенных хостах Linux, и 99,9% всех запросов проходят, но иногда время пакетов вызывает такое поведение в нашем брандмауэре.
РЕДАКТИРОВАТЬ Хорошо, теперь я добавил множество журналов в iptables, и похоже, что происходит следующее (все еще не знаю почему!)
Для пакетов, успешно проходящих через брандмауэр, выполняются следующие шаги, ссылки на таблицы / шаги из Вот
Table 3-3 step
2 raw-pre
conntrack
3 mangle-pre
4 [nat-pre]
5 routing-decision -> destination forward
6 mangle-fwd
7 filter-fwd
8 mangle-post
9 [nat-post]
Пакет 2133, который отклоняется, проходит следующие шаги:
Table 3-1 steps for the incoming FIN,ACK packet 2133
2 raw-pre
conntrack
3 mangle-pre
4 [nat-pre]
5 routing-decision -> destination local
6 mangle-input
7 filter-input
8 local process emits RST -> webserver
Table 3-2 steps for the outgoing RST packet 2134 in response to 2133
1 raw-out
2 routing decision
conntrack
3 mangle-out
reroute-check
4 [nat-out]
5 filter-out
6 mangle-post
7 nat-post
Странно то, что решение о маршрутизации для пакета 2133 на шаге 5 теперь отличается от решения о маршрутизации для других пакетов. При анализе запросов работает, например, не застревает, даже последний FIN правильно маршрутизируется. Это похоже на ошибку в ядре или на то, что решение о маршрутизации каким-то образом имеет состояние.
РЕДАКТИРОВАТЬ
Одна вещь, которая может вызвать эти проблемы, заключается в следующем: трафик маршрутизируется между межсетевым экраном и локальной LAN, поэтому клиентская LAN не связана напрямую с межсетевым экраном через L2.
+---------------------------+ +------------------+ +------------------------+
| | | Router | ( Lab network ) | |
( Internet ) -- + eth1 eth0 +-------+ +-- ( ) -+ Client 192.168.126.161 |
| 10.1.1.1 192.168.60.254 | | | ( 192.168.126.0/24 ) | |
+---------------------------+ +------------------+ +------------------------+
На этом рисунке 10.1.1.1 представляет собой внешний IP-адрес межсетевого экрана, все остальные адреса являются реальными используемыми IP-адресами.
Вот таблица маршрутизации на межсетевом экране:
Destination Gateway Genmask Flags Metric Ref Use Iface
10.1.1.0 0.0.0.0 255.255.255.240 U 0 0 0 eth1
192.168.126.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
192.168.60.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
0.0.0.0 10.1.1.15 0.0.0.0 UG 0 0 0 eth1
Обратите внимание, что 10.1.1.0 и gw по умолчанию 10.1.1.15 созданы, остальные точно такие же, как и использовались. Мне пришлось вручную добавить маршрут 192.168.126.0/24, чтобы добраться до лабораторной сети от eth0 (192.168.60.254).
Вот несколько подробных журналов прохождения пакета для последнего пакета 2133, который был отклонен из-за маршрутизации на локальный хост (например, межсетевой экран).
[16406874.374588] raw pre IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
[16406874.374625] mangle pre IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
[16406874.374667] mangle in IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
[16406874.374699] filter in IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
[16406874.374780] mangle out IN= OUT=eth1 SRC=10.1.1.1 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=0 RES=0x00 RST URGP=0
[16406874.374807] mangle post IN= OUT=eth1 SRC=10.1.1.1 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=0 RES=0x00 RST URGP=0
[16406874.378813] mangle pre IN=eth0 OUT= MAC=00:02:b3:b9:ff:b4:00:90:1a:10:0c:dd:08:00 SRC=192.168.126.161 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=63 ID=35424 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=11680 RES=0x00 ACK URGP=0
[16406874.378863] mangle fwd IN=eth0 OUT=eth1 SRC=192.168.126.161 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=62 ID=35424 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=11680 RES=0x00 ACK URGP=0
Еще раз, наш внешний IP-адрес fw был заменен на 10.1.1.1, а IP-адрес веб-сервера за пределами сети с NAT заменен на 172.16.1.2
ИЗМЕНИТЬ Главные новости!
Хорошо, последняя попытка заключалась в том, чтобы ОТБРАСЫВАТЬ пакет RST, очень интересно, я добавил правило iptables, которое отбрасывает все пакеты RST, предназначенные для веб-сервера, с которого у нас есть проблемы с запросом файлов. А потом это работал например, последний пакет 2133 FIN, ACK, PSH в приведенном выше журнале отбрасывается, но поскольку RST отброшен, у веб-сервера есть время, чтобы получить все ACK, муравей затем решает повторно передать последний пакет, пакет 2133 еще раз, и теперь он идет через брандмауэр, так как модуль контрацепции теперь видит возвращение ACK от клиента и разрешает последний пакет ACK, FIN с конечной полезной нагрузкой.
Таким образом, это определенно проблема синхронизации / окна, этот конкретный файл с синхронизацией ACK от клиента запускает что-то в conntrack, которое отклоняет последний пакет с веб-сервера.
Пока поиск в Google и чтение документации ядра не выявили ничего, что могло бы вызвать такое поведение, следующим шагом будет чтение исходного кода ядра для модуля routing / conntrack.
ЗАДАЧА РЕШЕНА
Что ж, по крайней мере, теперь мы точно знаем, что происходит, и у нас есть обходной путь, который решает проблему.
Сергей указал на очень ценное правило сопоставления -m state --state INVALID, которое очень помогло при отладке, теперь я понимаю, что настройка iptables без явного правила для INVALID-пакетов не завершена, поэтому иногда возникает странное поведение.
При включении входа в модуль conntrack для выяснения того, что вызывает недопустимый пакет, то, что происходит, довольно очевидно, и у меня были свои подозрения по этому поводу.
[16659529.322465] nf_ct_tcp: SEQ is over the upper bound (over the window of the receiver) IN= OUT= SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=40874 DF PROTO=TCP SPT=80 DPT=55498 SEQ=658735108 ACK=1194081763 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0
И снова 172.16.1.2 - это внешний веб-сервер (который ведет себя некорректно), а 10.1.1.1 - это внешний адрес межсетевого экрана.
Веб-сервер проталкивает по сети больше данных, чем клиент объявил в окне приема (conntrack имеет полное состояние и проверяет это), кажется, что когда приходит пакет FIN, conntrack выходит из строя, поскольку окно приема фактически превышено намного ранее.
Я считаю, что это могло быть вызвано неправильной разгрузкой TCP в сетевой карте на веб-сервере. Когда я начал анализировать это, я сделал снимки на веб-сервере, и в соответствии с трассировками tcpdump / wirehark jumbo-кадры были записаны на уровне TCP в ядре, которое затем сегментировалось сетевой картой на более мелкие кадры с MTU = 1500. Таким образом, очевидно, что это должно быть решено на веб-сервере, поскольку поведение TCP не является правильным - отправлять больше данных, чем получатель имеет рекламных объявлений в своем окне приема.
И Polynomial, и Сергей внесли ценный вклад, но Сергей указал мне на точное поведение модуля conntrack / NAT в отношении обхода пакетов.
Похожая ситуация описана на http://www.spinics.net/lists/netfilter/msg51408.html: некоторые пакеты, которые должны были быть обработаны NAT, каким-то образом помечались как INVALID вместо ESTABLISHED и отправлялись в цепочку INPUT. Вы должны добавить несколько правил с помощью -m state --state INVALID
чтобы проверить это, и ответ на http://www.spinics.net/lists/netfilter/msg51409.html предполагает, что такой НЕВЕРНЫЙ пакет всегда следует отбрасывать, потому что NAT не выполняется для них должным образом, поэтому адреса в них могут быть неправильными.
Если ваши проблемные пакеты действительно помечены как НЕДЕЙСТВИТЕЛЬНЫЕ, добавив iptables -I INPUT -m state --state INVALID -j DROP
Вероятно, проблема будет решена (поврежденный пакет не попадет в локальный процесс и не вызовет ответа RST, тогда TCP восстановит потерянный пакет после тайм-аута). Затем вы можете попробовать продолжить отладку проблемы, как описано в http://www.spinics.net/lists/netfilter/msg51411.html:
echo 255 >/proc/sys/net/netfilter/nf_conntrack_log_invalid
(В этом конкретном случае проблема была вызвана каким-то неисправным сетевым оборудованием на пути, вероятно, в сочетании с некоторым нарушением разгрузки контрольной суммы TCP.)
Я видел такое поведение на других типах межсетевых экранов, и поведение было настолько идентичным, что я решил выбросить его там.
Проблема, с которой я столкнулся, заключалась в том, что брандмауэр подключал NAT к тому же пространству, что и эфемерные порты на коробке. Это привело бы к такому же поведению, если бы они столкнулись, потому что теперь ядро предполагало, что соединение предназначено для локальной машины. С этой целью вы можете проверить несколько вещей. Сначала вы указываете конфигурацию исходящего порта в iptables (используя --to-ports)? Или вы изменили диапазон временных портов на машине:
$ cat /proc/sys/net/ipv4/ip_local_port_range
Чтобы диагностировать, вы можете настроить свой захват и посмотреть, видите ли вы какие-либо другие запросы, использующие тот же внешний fw ip, комбинацию портов в пределах 3 * MSL времени до RST (~ 180 с, я думаю).
Хотя я еще не уверен, что это ответ, но если бы я был в этой ситуации, я бы сначала исключил это, а затем посмотрел бы на пару других вещей.
Легко ли это воспроизвести? Можно ли получить дополнительную диагностику из окна брандмауэра и увидеть, как возникает проблема? Я бы попытался запечатлеть:
$ netstat -anp
$ cat /proc/net/ip_conntrack
каждую секунду или около того, пытаясь воспроизвести и посмотреть, есть ли что-то локально привязанное к порту, и как выглядела таблица маскарада во время проблемы.
Если вы используете брандмауэр для исходящего RST, может ли окончательный ACK от внутреннего клиента привести к успешному соединению?
И последнее: вы видите все журналы? Вы уже проверяли dmesg? Вы установили *. * В поле брандмауэра в конфигурации системного журнала в файл, чтобы убедиться?
Дайте мне знать, что вы найдете! Я очень ценю объем информации, которую вы предоставили в вопросе, спасибо.