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