web-dev-qa-db-ja.com

サーバーがSYNパケットに応答してSYN / ACKパケットを送信しない

Iptraf、tcpdump、wiresharkを使用すると、SYNパケットの着信が確認できますが、応答パケットにACK FLAGのみが設定されています。

私はカーネル2.6.36でDebian 5を実行しています

Window_scalingとtcp_timestamps、tcp_tw_recycle、tcp_tw_reuseをオフにしました。

cat /etc/sysctl.conf 



net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_timestamps = 0

ワイヤーシャーク出力の画像を添付しました。

http://imgur.com/pECG0.png

Netstatへの出力

netstat -natu | grep '72.23.130.104'

tcp        0      0 97.107.134.212:18000    72.23.130.104:42905     SYN_RECV

私は解決策を見つけるために可能な限りのことをしてきましたが、まだ問題を理解していないので、どんなヘルプ/提案も大歓迎です。

更新1:tcp_syncookies = 0を設定し、50のSYNリクエストごとに1 SYN + ACKで応答していることに気付きました。接続しようとしているホストは、約1秒に1回SYN要求を送信しています。

PCAPファイル

6
jeff

同じ問題が発生した後、ようやく根本原因を突き止めました。

Linuxでは、ソケットがTIME_WAITにあり、新しいSYN追加(ip/port src、ip/port destの同じペアの場合)の場合、カーネルはSYNのSEQ番号が最後に受信したSEQよりも小さいかどうかをチェックします。このソケット。

(PS:この問題に添付されているWireshark出力の画像では、シーケンス番号は相対として表示されます。絶対値として設定しないと、問題を確認できません。キャプチャは、古いセッションも表示する必要があります。配列番号を比較することができます)

  • sYNのSEQ番号が前のパケットのSEQ番号よりも大きい場合、新しい接続が作成され、すべてが機能します。
  • sYNのSEQ番号が前のパケットのSEQ番号よりも小さい場合、カーネルは、受信したSYNが前のソケットの遅延パケットであると考えるため、前のソケットに関連するACKを送信します。

TCPインクリメンタルなコンピュータによって生成されたSEQ番号の最初では、まだTIME_WAITにある以前のソケットのSEQ番号よりも小さいSEQ番号を受け取ることはほとんど不可能でした。 。

コンピュータの帯域幅の増加により、これはほとんど不可能から稀になりました。ただし、ここで最も重要なことは、ほとんどのシステムがランダムISN(最初のSEQ番号)を使用してセキュリティを向上させることです。したがって、新しいソケットのSEQ番号aが前のもののSEQ番号よりも大きくなることを防ぐものは何もありません。

各OSは、この特定の問題を回避するために多かれ少なかれ安全な異なるアルゴリズムを使用します http://www.bsdcan.org/2006/papers/ImprovingTCPIP.pdf 問題を適切に説明します。

最後に注意が必要なことがあるので、カーネルは古いセッションに関連するACKを送信しますか?クライアントOSは、(前のセッションの)ACKを受信する必要があります。クライアントのセッションが閉じられているため、理解しないでください。RSTを送信します。サーバーはこのRSTを受信するとすぐにソケットをクリアします(そのため、TIME_WAITにはありません)。彼の側では、クライアントはSYN/ACKを待っています。それを取得できないため、新しいSYNを送信します。その間、RSTが送信され、サーバー上でセッションがクリアされているため、このセカンダリSYNは機能し、サーバーはSYN/ACKなどに応答します。

したがって、通常の動作では、接続は機能しますが、(セカンダリSYNが送信されるまで)1秒遅れます。ジェフの場合、彼はコメントでフォーティネットファイアウォールを使用していると述べました。これらのファイアウォールは(デフォルトで)古いセッションに関連するACKをドロップします(ファイアウォールがACKに関連する開いているセッションを表示しないため)、クライアントはRSTを送信すると、サーバーはTIME_WAIT状態からセッションをクリアできません(もちろん、TIME_WAITタイマーの終了時を除く)。フォーティネットの「set anti-replaylooose」コマンドを使用すると、このACKパケットをドロップする代わりに転送できます。

6
radius

97.107.134.212はすでに接続があると信じているようです(72.23.130.104:42905, 97.107.134.212:18000)

72.23.130.104:42905がSYNパケットを送信する場合、そのシーケンス番号は246811966です。次は、独自のSEQ番号と246811967のACK値を持つSYN/ACKパケットです。

ただし、SEQ = 1736793629およびACK = 172352206のACKを送信しています。これらはおそらく以前の接続からの値です。

新しい接続の試みは別のポート番号から来るはずです...それは起こっていますか? Wiresharkはこれをpkt#11で指摘しています:「再利用されるTCPポート番号」。

問題は送信者にあるようです。

FWIW、私は接続できますjust結構です:

1   0.000000    192.168.0.135   97.107.134.212  TCP 45883 > biimenu [SYN] Seq=809402803 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSV=2319725 TSER=0 WS=7
2   0.022525    97.107.134.212  192.168.0.135   TCP biimenu > 45883 [SYN, ACK] Seq=4293896301 Ack=809402804 Win=14600 Len=0 MSS=1360 SACK_PERM=1
3   0.022553    192.168.0.135   97.107.134.212  TCP 45883 > biimenu [ACK] Seq=809402804 Ack=4293896302 Win=14600 Len=0
3
MikeyB

これは、送信パケットと受信パケットがネットワーク上で異なるルートを使用していて、受信レッグにステートフルな接続追跡デバイスがあったためです。そのデバイス(私の場合はロードバランサーですが、簡単にファイアウォールにすることもできます)が最初のSYNを見たことがないので、SYN-ACKは偽装としてフロアにドロップされました。

1
sysadmin1138

私はいくつかのことを確認します:

あなたのホストはマルチホームですか(例えば、あなたは複数のイーサネットインターフェースを持っていますか?)-もしそうなら、あなたのルートはめちゃくちゃになるかもしれません。これをテストする最も簡単な方法は、セカンダリインターフェイスを無効にして、問題が解消するかどうかを確認することです。

チェックする他のことは、iptables(または他のファイアウォール)が有効になっているかどうかです。 service iptables stopは、次の再起動までシャットダウンします。問題が解決する場合は、iptables設定を微調整する必要があります。

また、インターフェースでIPv6を有効にしている場合、ipv6ではなくipv4経由のルートが存在することがあります。これが発生すると、ipv6ルートが「デフォルト」になり、パケットは間違ったアドレスを通過する可能性があります(正しいインターフェース上でも)。 ipv6を無効にして、それが問題かどうかを確認してください。

0
Keith

発信パケットもないので、それは単なる非対称以上のものでなければなりません。

SYNは消えますが、着信SYN-ACKは表示されませんorローカルサーバーからの発信ACK。したがって、これらのパケットの両方を別の何かがプロキシしている必要があります。そうすると、着信ACKが表示されます。これは、実際にはシーケンスの4番目のパケットです。

私の推測では、WANアクセラレータの間に誤って設定されています。

0
Paul