В течение долгого времени у нас были проблемы с нашим брандмауэром, который иногда заставляет HTTP-запросы зависать частично загруженными до истечения времени ожидания TCP.
После отслеживания трафика на брандмауэре я заметил, что это происходит только при определенных условиях синхронизации, например, когда веб-сервер отправил полный ответ до того, как клиент отправил свой второй ACK на полезную нагрузку. [SYN, SYN / ACK, ACK] был обменен, REQUEST был отправлен и ACK 'и первый пакет RESPONSE был получен и ACK', затем веб-сервер отправляет остальную часть тела ответа за один кадр (8 пакетов включая последнюю FIN (PSH), и до того, как клиент получил ACK-код, Брандмауэр ОТКАЗЫВАЕТСЯ с RST по отношению к веб-серверу и держит клиента бесконечным.
Вот полная трассировка Wireshark с пакетами с обеих сторон брандмауэра. 192.168.126.161 - это частный NAT'et IP-адрес клиента. 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 правильно маршрутизируется. Это похоже на ошибку в ядре или на то, что решение о маршрутизации в каком-то смысле является состоянием.
РЕДАКТИРОВАТЬ
Одна из причин, которая может вызвать эти проблемы, заключается в следующем: трафик направляется между брандмауэром и локальной сетью, поэтому клиентская локальная сеть напрямую не подключается к брандмауэру через 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 и чтение документации Kernel ничего не показывают, что может вызвать такое поведение, следующим шагом будет чтение исходного кода ядра для модуля маршрутизации / conntrack.
ПРОБЛЕМА РЕШЕНА
Ну, по крайней мере, теперь мы точно знаем, что происходит, и имеем обходной путь, который решает проблему.
Сергей указал на очень ценное правило сопоставления INVALID -state состояние -m, которое очень помогло в отладке. Теперь я понимаю, что настройка 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 происходит сбой, так как окно приема фактически значительно превышено ранее.
Я считаю, что это может быть вызвано неправильной разгрузкой TCP в сетевой карте на веб-сервере. Когда я начал анализировать это, я сделал снимки на веб-сервере и в соответствии с трассировкой tcpdump / wireshark jumbo-кадры были записаны слоем TCP в ядре, которое затем было сегментировано на меньшие кадры с MTU = 1500 сетевой картой. Таким образом, очевидно, что это необходимо учитывать в веб-сервере, поскольку некорректно поведение TCP для отправки большего количества данных, чем у получателя в окне приема.
И Полином, и Сергей внесли ценный вклад, но Сергей указал мне точное поведение модуля conntrack / NAT в отношении обхода пакета.