ファイアウォール(Ubuntu 8.04)がRSTで最終パケット(FIN、ACK、PSH)を拒否する理由


20

背景には、長い間、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モジュールの正確な動作を指摘しました。


iptables設定にREJECTステートメントがありますか?その場合は、ロギングを使用して、どのルールであるかを判断できるかどうかを確認してください。
ラダダダダ

REJECTのようにいや、何のルールを拒否し、それがルーティングの決定の際に起こる外iptablesm起こらないようで
ernelli

ファイアウォールがスライディングウィンドウをサポートしていない可能性はありますか?動作中のクライアントからのキャプチャは、これと比較してどうですか?
joeqwerty

正常に動作すると、すべてのパケットがクライアントに正しく転送され、RSTパケットが返されないことを除いて、クライアントはサーバーからの最終FINの前にACKを送信します。大きなファイル(300k)からダンプを調べたところ、問題はありません。小さなファイルからのトレースも機能し、FINを含む最終パケットが転送されます。「ファイアウォールはスライディングウィンドウをサポートしていません」について詳しく説明してもらえますか?
11

ルーターとラボクライアント間の接続を拡張できますか?60と126に/ 24のネットマスクがあるので、ラボクライアントがどのようにトラフィックを送信できるかが明確ではありませんか?ネットマスクは/ 24ではありませんか?何らかのプロキシARPが行われていますか?126.0 / 24のeth0:1にエイリアスはありますか?
多項式

回答:


9

同様の状況は、http//www.spinics.net/lists/netfilter/msg51408.htmlで説明されています。NATによって処理されるはずのいくつかのパケットが、ESTABLISHEDではなくINVALIDとしてマークされ、INPUTチェーンに進みました。-m state --state INVALIDこれを確認するためにいくつかのルールを追加する必要があります。また、http://www.spinics.net/lists/netfilter/msg51409.htmlの答えは、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

他の種類のファイアウォールでこの動作を確認しましたが、動作はまったく同じだったので、そこに捨てると思いました。

私が抱えていた問題は、ファイアウォールがボックスの一時ポートと同じスペースにNATを適用していたことです。これは、カーネルが接続がローカルマシン向けであると想定していたため、2つが衝突した場合にこの正確な動作を引き起こします。このために、確認できることがいくつかあります。まず、iptablesでアウトバウンドポート設定を指定していますか(--to-portsを使用)?または、マシンの一時ポート範囲を変更しました:

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

診断するために、キャプチャをセットアップし、同じ外部fw ip、ポートコンボを使用してRST(〜180秒)の前の3 * MSL時間内に他の要求が表示されるかどうかを確認できます。

私はまだそれが答えだとは確信していませんが、もし私がこの状況にあったなら、私はまずそれを除外し、それから他のいくつかのことを見ていきます。

これは簡単に再現できますか?ファイアウォールボックスからさらに診断をキャプチャして、問題が発生するのを確認することはできますか?私はキャプチャしようとします:

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

1秒ごとに、ポートにローカルにバインドされているものがあるかどうか、およびマスカレードテーブルが問題中にどのように見えたかを再現して確認しようとしています。

RSTアウトバウンドをファイアウォールで保護すると、内部クライアントからの最終的なACKにより接続が成功しますか?

最後に、すべてのログを見ていますか?すでにdmesgをチェックしましたか?syslog構成のファイアウォールボックスに*。*を設定してファイルを確認しましたか?

見つけたことを教えてください!質問で提供してくれた情報に感謝します。


あなたの努力のおかげで、私はエラーを100%再現することができます。ファイアウォールを通過するすべてのリクエストはごくわずかを除いて機能します。動作しない人は、正確なサイズ/タイミングの問題に直面しているようです。ファイアウォールを介して同じクライアント/ウェブサーバー間でより大きな/より小さなリクエストのために複数のWiresharkトレースを追加できますが、これらはすべて機能しますが、上記のトレースはスタックします。上記の新しい情報を追加しました。これらの情報は、問題を特定する可能性があります。
エルネリ

/ proc / sys / net / ipv4 / ip_local_port_rangeが[32768 61000]に設定されているnetstatは、ローカルにバインドされたポートを表示しません。ip_conntrackは、接続が確立されていることを示します。たとえば、最後のFINがクライアントに転送されていないため、接続が開いていることを示します。ステータスは、packets = 10 bytes = 12084 [ASSURED] mark = 0 secmark = 0 use = 1
ernelli
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.