Почему наш брандмауэр (Ubuntu 8.04) отклоняет окончательный пакет (FIN, ACK, PSH) с RST

В течение долгого времени у нас были проблемы с нашим брандмауэром, который иногда заставляет 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 в отношении обхода пакета.

2 ответа

Решение

Аналогичная ситуация описана по адресу http://www.spinics.net/lists/netfilter/msg51408.html: некоторые пакеты, которые должны были быть обработаны NAT, каким-то образом помечены как INVALID, а не ESTABLISHED, и перешли в цепочку INPUT. Вы должны добавить некоторые правила с -m state --state INVALID чтобы проверить это, и ответ на http://www.spinics.net/lists/netfilter/msg51409.html предполагает, что такой пакет INVALID всегда должен быть DROPped, потому что 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).

Я видел такое поведение на других типах брандмауэров, и поведение было настолько идентичным, что я решил выбросить его там.

Проблема, с которой я столкнулся, заключалась в том, что брандмауэр находился в том же месте, что и временные порты на коробке. Это привело бы к такому поведению, если бы они столкнулись, потому что ядро ​​теперь предполагало, что соединение предназначено для локальной машины. Для этого есть пара вещей, которые вы можете проверить. Во-первых, вы указываете конфигурацию исходящего порта в iptables (используя --to-ports)? Или вы изменили диапазон временных портов на машине:

$ cat /proc/sys/net/ipv4/ip_local_port_range

Для диагностики вы можете настроить захват и посмотреть, видите ли вы какие-либо другие запросы с использованием того же внешнего fw ip, combo port за 3*MSL времени до RST(я думаю, ~180 с).

Хотя я не уверен, что ответ таков, если бы я был в такой ситуации, я бы сначала исключил это, а затем взглянул бы на пару других вещей.

Это легко воспроизвести? Можно ли записать больше диагностики из коробки брандмауэра и увидеть возникшую проблему? Я хотел бы попытаться захватить:

$ netstat -anp
$ cat /proc/net/ip_conntrack

каждую секунду или около того, пытаясь воспроизвести и посмотреть, есть ли что-то локально привязанное к порту и как выглядела маскарадная таблица во время проблемы.

Если вы выполняете брандмауэр для исходящих RST-сообщений, вызывает ли возможный ACK от внутреннего клиента успешное соединение?

Последнее, вы видите все журналы? Вы уже проверили dmesg? Вы настроили *.* В окне брандмауэра в конфигурации системного журнала для файла, чтобы убедиться?

Дайте мне знать, что вы найдете! Я действительно ценю объем информации, предоставленной вами в вопросе, спасибо.

Другие вопросы по тегам