W tle od dłuższego czasu mieliśmy problemy z naszą zaporą ogniową, która czasami zawieszała częściowo żądania HTTP do czasu przekroczenia limitu czasu TCP.
Po prześledzeniu ruchu na zaporze sieciowej zauważyłem, że występuje on tylko w określonych warunkach czasowych, np. Gdy serwer WWW wysłał całą odpowiedź, zanim klient wysłał swoje drugie ACK na ładunku. [SYN, SYN / ACK, ACK] zostało wymienione, ŻĄDANIE zostało wysłane i POTWIERDZONE, a pierwszy pakiet RESPONSE został odebrany i potwierdzony, a następnie serwer internetowy wysyła resztę treści odpowiedzi w jednym ujęciu (8 pakietów łącznie z ostatnim FIN, PSH) i zanim klient potwierdzi którekolwiek z nich, Firewall ODRZUCA RST do serwera WWW i utrzymuje klienta w stanie nieskończoności.
Oto cały ślad wireshark z pakietami po obu stronach zapory. 192.168.126.161 jest prywatnym adresem IP NAT'et klienta. 172.16.1.2 to adres IP serwera WWW (nie pokazuje rzeczywistego publicznego adresu IP), a 10.1.1.1 to zewnętrzny adres IP zapory (nie pokazuje prawdziwego publicznego adresu 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
Kopałem i rejestrowałem przechodzenie pakietów zgodnie z tym wykresem i wydaje się, że ostatni przychodzący pakiet 2133 mija RAW-PREROUTING, conntrack, Mangle-PREROUTING, ale potem jest zgubiony. Nie mam reguł ODRZUCENIA w moich iptables, rejestruję wszystkie reguły DROP i żadna z nich nie pokazuje, gdzie pakiet 2133 się gubi.
Chciałbym użyć celu TRACE na filtrze przychodzącym, ale niestety Ubuntu 8.04 nie jest dostarczane z obsługą celu TRACE.
Uważam więc, że obowiązują niektóre wewnętrzne reguły routingu / conntrack / mangling, które z jakiegoś powodu resetują połączenie. Może ruch wyzwala pewną ochronę DOS, ale nie mam pojęcia, gdzie to skonfigurować / przeanalizować. Najbardziej frustrujące jest to, że pakiet jest odrzucany i nic nie jest rejestrowane ...
Żądanie tego pliku działa również w 100% z hostów systemu Windows, ale nie działa na niektórych hostach systemu Linux i 99,9% wszystkich żądań przechodzi, ale czasami synchronizacja pakietów wyzwala takie zachowanie w naszej zaporze.
EDYCJA Ok, teraz dodałem tony logowania do iptables i wygląda na to, że dzieje się tak (wciąż nie wiem dlaczego!)
W przypadku pakietów pomyślnie przechodzących przez zaporę wykonuje się następujące kroki, odniesienia do tabeli / kroku stąd
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]
Pakiet 2133, który zostanie odrzucony, przechodzi przez następujące kroki:
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
Dziwne jest to, że decyzja o routingu dla pakietu 2133 w kroku 5 jest teraz inna niż decyzja o routingu dla innych pakietów. Podczas analizy żądań, które działają, np. Nie zacinają się, nawet ostatni FIN jest odpowiednio trasowany. Wydaje się, że jest to błąd w jądrze lub że decyzja o routingu jest w jakiś sposób uzasadniona.
EDYTOWAĆ
Jedną z rzeczy, które mogą powodować te problemy, jest fakt, że ruch jest kierowany między zaporą a lokalną siecią LAN, więc klient sieci LAN nie jest bezpośrednio połączony z zaporą przez 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 ) | |
+---------------------------+ +------------------+ +------------------------+
Na tym obrazie 10.1.1.1 reprezentuje zewnętrzny adres IP zapory, wszystkie pozostałe adresy są rzeczywistymi wykorzystanymi adresami IP.
Oto tabela routingu w zaporze:
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
Zauważ, że 10.1.1.0 i domyślny gw 10.1.1.15 są wykonane, reszta jest dokładnie taka sama jak używana. Musiałem ręcznie dodać trasę 192.168.126.0/24, aby dotrzeć do sieci laboratoryjnej z eth0 (192.168.60.254).
Oto kilka obszernych dzienników podczas przechodzenia pakietu dla ostatniego pakietu 2133, który zostaje odrzucony z powodu przekierowania do lokalnego hosta (np. Zapory ogniowej).
[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
Po raz kolejny nasz zewnętrzny adres IP fw został zastąpiony przez 10.1.1.1, a ip serwera WWW poza siecią NAT jest zastąpiony przez 172.16.1.2
EDIT Breaking News!
Ok, ostatnia próba polegała na DROPowaniu pakietu RST, bardzo, bardzo interesujące, dodałem regułę iptables, która upuściła wszystkie pakiety RST przeznaczone na serwer, z którego mamy problem z żądaniem plików. I wtedy zadziałało, np. Ostatni pakiet FIN, ACK, PSH 2133 w powyższym dzienniku został usunięty, ale ponieważ RST jest upuszczony, serwer sieciowy ma czas na pobranie wszystkich mrówek ACK, a następnie decyduje się na retransmisję ostatniego pakietu, pakietu 2133 jeszcze raz, a teraz przechodzi przez zaporę ogniową, ponieważ moduł antykryzysowy widział teraz powrót ACK od klienta i pozwala na ostatni pakiet ACK, FIN z ostatecznym ładunkiem.
Jest to więc z pewnością problem z timingiem / oknem, ten konkretny plik, wraz z timingiem ACK od klienta, wyzwala coś w conntrack, który odrzuca końcowy pakiet z serwera WWW.
Jak dotąd, przeglądanie i czytanie dokumentacji Kernela nie ujawnia niczego, co mogłoby spowodować takie zachowanie, następnym krokiem będzie odczytanie kodu źródłowego jądra dla modułu routingu / conntrack.
PROBLEM ROZWIĄZANY
Cóż, przynajmniej teraz wiemy dokładnie, co się dzieje i mamy obejście, które rozwiązuje problem.
Sergey wskazał na bardzo cenną regułę dopasowania stanu INMALID stanu -m, która bardzo pomogła w debugowaniu, teraz zdaję sobie sprawę, że konfiguracja iptables bez wyraźnej reguły dla pakietów INVALID nie jest kompletna, więc czasami zdarza się dziwne zachowanie.
Po włączeniu logowania do modułu conntrack, co powoduje nieprawidłowy pakiet, co się dzieje, jest to dość oczywiste i miałem co do tego podejrzenia.
[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
Po raz kolejny 172.16.1.2 jest zewnętrznym serwerem WWW (który zachowuje się nieprawidłowo), a 10.1.1.1 to zewnętrzny adres zapory.
Serwer przesyła przez sieć więcej danych niż klient ogłosił w oknie odbioru (conntrack jest pełny i sprawdza to), wydaje się, że to właśnie wtedy, gdy przybywa pakiet FIN, conntrack wysyła baila, ponieważ okno odbioru jest w rzeczywistości znacznie przekroczone wcześniej.
Uważam, że może to być spowodowane nieprawidłowym odciążeniem TCP karty sieciowej na serwerze WWW. Kiedy zacząłem to analizować, wziąłem przechwytywanie na serwerze sieciowym i zgodnie ze śladami tcpdump / wireshark jumbo zapisywało duże ramki przez warstwę TCP w jądrze, które następnie było dzielone na mniejsze ramki o MTU = 1500 przez kartę sieciową. Oczywiście należy to zaadresować na serwerze internetowym, ponieważ wysyłanie większej ilości danych nie jest poprawnym działaniem protokołu TCP, ponieważ odbiornik ma reklamy w oknie odbioru.
Zarówno Polynomial, jak i Sergey dostarczyły cennych informacji, ale Sergey wskazał mi dokładne zachowanie modułu conntrack / NAT w odniesieniu do przechodzenia pakietów.