背景には、長い間、TCPがタイムアウトするまでHTTPリクエストが部分的にロードされたままになることがあるというファイアウォールの問題がありました。
ファイアウォールでトラフィックをトレースした後、特定のタイミング条件でのみ発生することに気付きました。たとえば、クライアントがペイロードで2番目のACKを送信する前にWebサーバーが応答全体を送信した場合です。[SYN、SYN / ACK、ACK]が交換され、REQUESTが送信され、ACKされ、最初のRESPONSEパケットが受信され、ACKされた後、ウェブサーバーは残りの応答本文を1ショットで送信します(8パケット最後のFIN、PSHを含み、クライアントがそれらのいずれかにACKを返す前に、ファイアウォールはWebサーバーに対してRSTで拒否し、クライアントを無限にハングさせ続けます。
これは、ファイアウォールの両側からのパケットを含むWiresharkトレース全体です。192.168.126.161は、クライアントのプライベートNAT'et IPアドレスです。172.16.1.2はWebサーバー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を通過したが失われたようです。iptablesにはREJECTルールがありません。すべてのDROPルールをログに記録しますが、パケット2133が失われた場所を示すルールはありません。
着信フィルターでTRACEターゲットを使用したいのですが、残念ながら、ubuntu 8.04にはTRACEターゲットのサポートが含まれていません。
したがって、何らかの理由で接続をリセットする内部の暗黙的なルーティング/ conntrack /マングリングルールが適用されると考えています。トラフィックがDOS保護をトリガーすることもありますが、どこで設定/分析するのかわかりません。最もイライラすることは、パケットが拒否され、何も記録されないことです...
また、このファイルの要求はWindowsホストから100%動作しますが、特定のLinuxホストでは失敗し、すべての要求の99.9%が通過しますが、パケットのタイミングがファイアウォールでこの動作をトリガーすることがあります。
編集 OK
ファイアウォールを正常に通過するパケットの場合、次の手順が実行されます。ここからの表/手順の参照
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
奇妙なことは、ステップ5でのパケット2133のルーティング決定が、他のパケットのルーティング決定と異なることです。動いているリクエスト、例えばスタックしないリクエストを分析する場合、最後のFINでも適切にルーティングされます。カーネルのバグのようであるか、何らかの方法でルーティングの決定がステートフルであるようです。
編集
これらの問題を引き起こす可能性のあることの1つは、次の事実です。トラフィックはファイアウォールとローカルLANの間でルーティングされるため、クライアントLANは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が構成されており、残りは使用されているものとまったく同じであることに注意してください。eth0(192.168.60.254)からラボネットワークに到達するには、192.168.126.0 / 24ルートを手動で追加する必要がありました。
次に、ローカルホスト(ファイアウォールなど)にルーティングされたために拒否される最後のパケット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
もう一度、fw外部IPは10.1.1.1に置き換えられ、NATされたネットワーク外のWebサーバーのIPは172.16.1.2に置き換えられました
最新ニュースを編集!
OK最後の試みはRSTパケットをドロップすることでした。非常に興味深いので、ファイルの要求に問題のあるWebサーバーを宛先とするすべてのRSTパケットをドロップするiptablesルールを追加しました。そして、それは機能しました。たとえば、上記のログの最後のFIN、ACK、PSHパケット2133がドロップされますが、RSTがドロップされるため、ウェブサーバーはすべてのACKのアリを取得する時間があり、最後のパケット、パケット2133をもう一度送信することを決定し、そして、contrackモジュールがACKがクライアントから戻ってくるのを確認し、最後のペイロードを持つ最後のACK、FINパケットを許可するため、ファイアウォールを通過します。
したがって、これは間違いなくタイミング/ウィンドウの問題です。この特定のファイルは、クライアントからのACKのタイミングで、Webサーバーからの最終パケットを拒否するconntrackで何かをトリガーします。
これまでのところ、カーネルのドキュメントをグーグルで調べて読むと、この動作を引き起こす可能性のあるものは何も明らかになりません。次のステップは、ルーティング/ conntrackモジュールのカーネルソースコードを読むことです。
問題が解決しました
さて、少なくとも今は何が起こるかを正確に知っており、問題を解決する回避策があります。
セルゲイは非常に価値のある-m state --state INVALIDマッチングルールを指摘しましたが、これはデバッグに大いに役立ちましたが、INVALIDパケットの明示的なルールのないiptablesセットアップは完全ではないので、奇妙な動作がときどき起こるようです。
無効なパケットの原因について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は外部Webサーバー(正しく動作しない)であり、10.1.1.1はファイアウォールの外部アドレスです。
Webサーバーは、クライアントが受信ウィンドウでアドバタイズしたよりも多くのデータをネットワーク経由でプッシュします(conntrackはステートフルであり、これを検証します)以前。
Webサーバー上のネットワークカードでのTCPのオフロードが間違っていることが原因であると考えています。これを分析し始めたとき、ウェブサーバーでキャプチャを取得し、tcpdump / wiresharkトレースに従って、ジャンボフレームはカーネルのTCPレイヤーによって書き込まれ、ネットワークカードによってMTU = 1500の小さなフレームにセグメント化されました。したがって、明らかに、受信者が受信ウィンドウに広告を持っているよりも多くのデータを送信するのは正しいTCPの振る舞いではないため、これはWebサーバーで対処する必要があります。
多項式とセルゲイの両方が貴重な入力を提供しましたが、セルゲイはパケットトラバーサルに関するconntrack / NATモジュールの正確な動作を指摘しました。