Чому наш брандмауер (Ubuntu 8.04) відкидає остаточний пакет (FIN, ACK, PSH) з RST


20

Передумови, ми тривалий час мали проблеми з нашим брандмауером, який іноді зберігає HTTP-запити частково завантаженими, поки не вичерпається TCP.

Після відстеження трафіку на брандмауері я помітив, що він виникає лише під час певних часових умов, наприклад, коли веб-сервер надіслав всю відповідь до того, як клієнт надіслав свій другий ACK на корисний вантаж. [SYN, SYN / ACK, ACK] було обмінено, REQUEST було надіслано та ACK'ed, і перший пакет RESPONSE отримано та ACK'ed, потім веб-сервер надсилає решту тіла відповіді за один кадр (8 пакетів включаючи останній FIN, PSH) і перед тим, як клієнт ACK''отримав будь-який із них, Брандмауер ОТХВОРЮЄ RST у напрямку до веб-сервера і зберігає, щоб клієнт був нескінченним.

Тут знаходиться весь слід проводки з пакетами з обох сторін брандмауера. 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 проходить повз сировину - ПЕРЕДАЧА, контракція, мангра-ПЕРЕДАЧА, але потім втрачається. У своїх iptables у мене немає правил REJECT, я реєструю всі правила 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 надходить належним чином. Здається, що помилка в ядрі або що рішення про маршрутизацію є якимось станом.

EDIT

Одне, що може спричинити ці проблеми, полягає в наступному: трафік направляється між брандмауером та локальною локальною мережею, тому клієнтська локальна мережа безпосередньо не підключена до брандмауера через 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'ed замінено на 172.16.1.2

EDIT Актуальні новини!

Ок, остання спроба полягала в тому, щоб скинути пакет RST, дуже цікаво, я додав правило iptables, яке викинуло всі пакети RST, призначені для веб-сервера, у якого виникають проблеми із запитом файлів. І тоді він працював, наприклад, останній FIN, ACK, PSH-пакет 2133 в журналі, зазначеному вище, випадає, але оскільки RST скинуто, веб-сервер встигає отримати весь мурашник ACK, то вирішує повторно передати останній пакет, пакет 2133 ще раз, і тепер він проходить через брандмауер, оскільки модуль контракту бачив, що ACK повертається від клієнта, і дозволяє останній пакет ACK, FIN з кінцевим корисним навантаженням.

Отже, це, безумовно, проблема з тимчасовим вікном / вікном, саме цей файл із тимчасовим часом ACK від клієнта запускає щось у conntrack, що відхиляє остаточний пакет від веб-сервера.

Поки гуглінг та читання документа Kernel не виявляють нічого, що може спричинити таку поведінку, наступним кроком буде зчитування вихідного коду ядра модуля маршрутизації / континтрації.

ПРОБЛЕМА ВИРІШЕНА

Ну, принаймні зараз ми точно знаємо, що відбувається, і маємо вирішення проблеми, яка вирішує проблему.

Сергій вказав на дуже цінне -m стан - правило 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 на мережевій карті на веб-сервері. Коли я почав аналізувати це, я взяв захоплення на веб-сервері, і відповідно до даних trackok trac-кадрів записані слої TCP в ядро, яке потім було сегментоване на менші кадри з MTU = 1500 мережевою картою. Тож очевидно, що це потрібно вирішувати на веб-сервері, оскільки це неправильна поведінка TCP надсилати більше даних, ніж одержувач оголошень у вікні отримання.

І Поліном, і Сергій дали цінний внесок, але Сергій вказав мені на точну поведінку модуля conntrack / NAT щодо переходу пакетів.


Чи є у вашій iptables конфігурації заяви REJECT? Якщо так, подивіться, чи можна за допомогою журналу визначити, яке це правило.
Ladadadada

Ні, жодних правил відхилення здається, що РЕЖЕКТ трапляється поза iptablesm, це відбувається під час рішення про маршрутизацію
ernelli

Чи можливо, що брандмауер не підтримує розсувні вікна? Як порівняння з робочим клієнтом порівнюється з цим?
joeqwerty

Коли він працює, окрім того, що всі пакети правильно передаються клієнтові і не повертаються RST-пакети, клієнт надсилає ACK-адреси перед остаточним FIN з сервера. Я перевірив дамп із великого файлу (300k), і тоді проблем немає. Сліду від невеликого файлу також працює, передається остаточний пакет з FIN. Чи можете ви детальніше
розглянути питання

Чи можете ви розширити зв'язок між маршрутизатором і клієнтом лабораторії? У вас / 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 завжди повинен бути знищений, оскільки NAT не виконується належним чином. , тому адреси в них можуть бути неправильними.

Якщо ваші проблемні пакети дійсно позначені як INVALID, додавання, 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

Я бачив цю поведінку на інших типах брандмауера, і така поведінка була такою ж ідентичною, що я зрозумів, що викину її туди.

Проблема в мене полягала в тому, що брандмауер NAT'ів в той же простір, що і ефемерні порти на коробці. Це спричинило б таку точну поведінку, якби двоє зіткнулися, тому що ядро ​​припускає, що з'єднання призначене для локальної машини. З цією метою є кілька речей, які ви можете перевірити. Спочатку ви вказуєте конфігурацію вихідного порту в iptables (за допомогою --to-ports)? Або ви змінили діапазон ефемерних портів на машині:

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

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

Хоча я ще не впевнений, що це відповідь, але якби я опинився в цій ситуації, я би виключив це спочатку, а потім перегляну пару інших речей.

Це легко відтворити? Чи можливо отримати більше діагностики з брандмауера і побачити проблему? Я б спробував захопити:

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

щосекунди або близько того, намагаючись відтворити і побачити, чи є щось прив’язане локально до порту і як виглядав таблиця маскарадів під час проблеми.

Якщо брандмауер виходить на RST, вихідний ACK від внутрішнього клієнта спричиняє успіх з'єднання?

Останнє, ви бачите всі журнали? Ви вже перевірили dmesg? Ви встановили *. * У вікно брандмауера в конфігурації syslog, щоб переконатися у файлі?

Дайте мені знати, що ви знайдете! Я дуже вдячний за кількість інформації, яку ви надали у запитанні, дякую.


Дякую за ваші зусилля, я можу відтворити помилку на 100%, усі запити через брандмауер працює, за винятком дуже мало. Тим, хто не працює, начебто потрапляє в точний розмір / термін. Я можу додати декілька слідів Wireshark для більших / менших запитів між тим самим клієнтом / веб-сервером через брандмауер, який працює, але вище вказаний слід. Я додав вище нову інформацію, яка може присвятити проблему.
ernelli

/ proc / sys / net / ipv4 / ip_local_port_range встановлено у [32768 61000] netstat не показує жодних локально пов'язаних портів. ip_conntrack показує з'єднання як встановлене, наприклад, вважає, що воно все ще відкрите, оскільки останній FIN не був переданий клієнтові. Статус - пакети = 10 байт = 12084 [ASSURED] mark = 0 secmark = 0 використання = 1
ernelli
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.