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

20

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

ernelli
источник
У вас есть какие-либо операторы REJECT в вашей конфигурации iptables? Если так, посмотрите, можете ли вы использовать ведение журнала, чтобы выяснить, какое это правило.
Ладададада
Нет, нет правил отклонения, кажется, что REJECT происходит вне iptablesm, это происходит во время принятия решения о маршрутизации
ernelli
Возможно ли, что брандмауэр не поддерживает раздвижные окна? Как захват с рабочего клиента сравнивается с этим?
Joeqwerty
Когда это работает, за исключением того, что все пакеты правильно передаются клиенту и никакие RST-пакеты не возвращаются, клиент отправляет ACK перед окончательным FIN с сервера. Я изучил дамп из большого файла (300 КБ), и тогда нет проблем. Трассировка из небольшого файла также работает, окончательный пакет с FIN пересылается. Можете ли вы уточнить, что «брандмауэр не поддерживает раздвижные окна»
ernelli
Можете ли вы расширить связь между маршрутизатором и клиентом лаборатории? У вас есть / 24 сетевых масок на 60 и 126, так что не ясно, как клиенты лаборатории могут отправлять трафик? Разве их сетевая маска не а / 24? Происходит ли какой-то прокси-арп? Есть ли псевдоним eth0: 1 для 126.0 / 24?
полином

Ответы:

9

Аналогичная ситуация описана по адресу 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).

Сергей Власов
источник
4

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

Проблема, с которой я столкнулся, заключалась в том, что брандмауэр находился в том же месте, что и временные порты на коробке. Это привело бы к такому поведению, если бы они столкнулись, потому что ядро ​​теперь предполагало, что соединение предназначено для локальной машины. Для этого есть пара вещей, которые вы можете проверить. Во-первых, вы указываете конфигурацию исходящего порта в 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? Вы настроили *. * В окне брандмауэра в конфигурации системного журнала для файла, чтобы убедиться?

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

многочлен
источник
Спасибо за ваши усилия, я могу воспроизвести ошибку на 100%, все запросы через брандмауэр работают, за исключением очень немногих. Те, кто не работает, похоже, сталкиваются с проблемой точного размера / времени. Я могу добавить несколько трассировок Wireshark для больших / меньших запросов между одним и тем же клиентом / веб-сервером через брандмауэр, который все работает, но приведенная выше трассировка - это то, что застревает. Я добавил новую информацию выше, которая может пролить свет на проблему.
Эрнелли
Для / proc / sys / net / ipv4 / ip_local_port_range установлено значение [32768 61000]. netstat не показывает локально связанные порты. ip_conntrack показывает соединение как установлено, например, считает, что оно все еще открыто, так как последний FIN не был переадресован клиенту. Статус - пакеты = 10 байт = 12084. Марк [ASSURED] = 0. Метка = 0. Использование = 1
Эрнелли.