以下は、発生している問題のwiresharkダンプであり、IPアドレスは「client」と「server」に置き換えられています。
4414.229553 client -> server TCP 62464 > http [SYN] Seq=0 Win=65535 Len=0 MSS=1452 WS=3 TSV=116730231 TSER=0
4414.229633 server -> client TCP http > 62464 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=2406364374 TSER=116730231 WS=6
4414.263330 client -> server TCP 62464 > http [ACK] Seq=1 Ack=1 Win=524280 Len=0 TSV=116730231 TSER=2406364374
4418.812859 server -> client TCP http > 62464 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=2406365520 TSER=116730231 WS=6
4418.892176 client -> server TCP [TCP Dup ACK 778#1] 62464 > http [ACK] Seq=1 Ack=1 Win=524280 Len=0 TSV=116730278 TSER=2406365520
4424.812864 server -> client TCP http > 62464 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=2406367020 TSER=116730278 WS=6
4424.891240 client -> server TCP [TCP Dup ACK 778#2] 62464 > http [ACK] Seq=1 Ack=1 Win=524280 Len=0 TSV=116730337 TSER=2406367020
したがって、サーバーがACKを解釈していないように見えることを除いて、通常のSYN、SYN + ACK、ACKシーケンスが発生しているように見えます。代わりに、SYN + ACKを再送信し続けます。これは、クライアントが前のACKの複製で忠実に応答し続けます。これがどのように起こるのかわかりません。
Iptables接続追跡はこれらの接続が確立されたと見なし、120時間のタイムアウトの間、それらをメモリに保持するため、問題に気づきました。実際に多くの接続をアクティブにすることなく、制限に達した多数の同時接続を防ぐためのファイアウォールルールがいくつかあります。 netstat
コマンドは、これらのファントム接続を表示しません。
他の情報:
サーバーは、ストックカーネルを備えた標準のDebianLennyシステムです。
Linux tb 2.6.26-2-686 #1 SMP Wed Aug 19 06:06:52 UTC 2009 i686 GNU/Linux
ランニング:
Apache/2.2.9 (Debian) mod_ssl/2.2.9 OpenSSL/0.9.8g
クライアントにすべての情報がありません(ローカルで再現できません)が、Chromeブラウザを実行しているMacです。
ACKパケットをいじるファイアウォールルールはありません。基本的に私はSYNパケットのみをフィルタリングし、他のすべてのTCPパケットは通過を許可されます。したがって、同時接続のカウントとTCP確立パケットのグラフ化以外は、実際にはファイアウォールの接続追跡を使用しません。他のパケットタイプと比較して。
編集:私のiptables-TCPポート80に関連するルール:
iptables -P INPUT ACCEPT
iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 50 -j LOGDROP-CONN
iptables -A INPUT -p tcp --syn -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -p tcp --syn -j REJECT --reject-with tcp-reset
iptables -A LOGDROP-CONN -m limit --limit 1/minute --limit-burst 1 -j LOG --log-prefix "ConConn "
iptables -A LOGDROP-CONN -j DROP
編集2:今度はtcpdump -vvを使用して別のダンプ:
16:05:52.999525 IP (tos 0x0, ttl 55, id 46466, offset 0, flags [DF], proto TCP (6), length 64) client.50538 > server.www: S, cksum 0x4429 (correct), 38417001:38417001(0) win 65535 <mss 1452,nop,wscale 3,nop,nop,timestamp 117224762 0,sackOK,eol>
16:05:52.999580 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) server.www > client.50538: S, cksum 0xa2ab (correct), 3062713115:3062713115(0) ack 38417002 win 5792 <mss 1460,sackOK,timestamp 2418739698 117224762,nop,wscale 6>
16:05:53.321788 IP (tos 0x0, ttl 55, id 24299, offset 0, flags [DF], proto TCP (6), length 52) client.50538 > server.www: ., cksum 0xe813 (correct), 1:1(0) ack 1 win 65535 <nop,nop,timestamp 117224765 2418739698>
16:05:56.252697 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) server.www > client.50538: S, cksum 0x9f7a (correct), 3062713115:3062713115(0) ack 38417002 win 5792 <mss 1460,sackOK,timestamp 2418740512 117224765,nop,wscale 6>
16:05:56.277250 IP (tos 0x0, ttl 55, id 15533, offset 0, flags [DF], proto TCP (6), length 52) client.50538 > server.www: ., cksum 0xe4c4 (correct), 1:1(0) ack 1 win 65535 <nop,nop,timestamp 117224798 2418740512>
総当たり攻撃します。まず、iptablesを停止して動作するかどうか試してみます。もしそうなら、それはiptablesの何かです。
次に、ルールを1つずつ追加し、どのルールが接続障害の原因になるかを監視します。次に、トラフィックを完全に中断することなく、必要な処理が実行されるまで、そのルールを試してみました。
Iptablesを停止しても機能しない場合は、非常に奇妙になり始めます。
わかりました。完全な答えはありませんが、この問題が最初に発生して以来、多くのことを学びました。ここで私の洞察を共有します。
telnet www.website.com 80
やテストしたサーバーはすべてLinuxを実行している可能性があるため、データを送信しません。この動作はiptables-rulesがロードされていない場合にも発生するため、実際にはカーネルに関連しています。iptables
connection-trackingはこのロジックを共有していないようです。そのため、接続はタイムアウトするまでESTABLISHED
状態のままになります。これのデフォルトのタイムアウトは5日(!)です。これを数時間など、もっと賢明なものに減らすことを計画しています。nc -l ###
でリスニングポートを開いてそれに接続したときに表示されなかったためです。したがって、Apacheがリスニングソケットに設定する特定のTCPオプションである可能性があります。または、Apacheに完全に固有のものである可能性があります。他のほとんどのデーモンは、接続直後にアナウンスするため、有効なテストケースではありません。このため、接続は3ウェイハンドシェイクを実行し、すぐにアイドル状態になる必要があります。しかし、上記の洞察に感謝しますが、それらはこれの根底に到達するのに役立ちました。