フォローアップ:数か月ごとに各サーバーを実行すると同時に発生する一連の切断が急速に発生するのは偶然の一致であり、実際の問題を明らかにするのに役立っているようです。再接続に失敗した理由は、ほぼ確実にAliveInterval値(kasperdの回答)によるものです。 ExitOnForwardFailureオプションを使用すると、再接続する前にタイムアウトが適切に発生し、ほとんどの場合問題が解決されます。 MadHatterの提案(killスクリプト)は、他のすべてが失敗した場合でもトンネルが再接続できるようにするためのおそらく最良の方法です。
ファイアウォールの背後にサーバー(A)があり、小さなDigitalOcean VPS(B)へのいくつかのポートでリバーストンネルを開始するため、BのIPアドレスを介してAに接続できます。トンネルは約3か月間一貫して動作していますが、過去24時間に4回突然失敗しました。同じことが別のVPSプロバイダーでしばらく前に起こりました-数ヶ月の完全な動作、そして突然複数の急速な障害。
マシンAに、トンネルコマンド(ssh -R *:X:localhost:X address_of_B
各ポートX)ですが、実行するとWarning: remote port forwarding failed for listen port X
。
Sshdに入る/var/log/secure
サーバー上で次のエラーが表示されます:
bind: Address already in use
error: bind: Address already in use
error: channel_setup_fwd_listener: cannot listen to port: X
解決するには、VPSを再起動する必要があります。それまでは、再接続の試行はすべて「リモートポート転送に失敗しました」というメッセージが表示され、機能しません。トンネルが止まるまで約4時間しか続かないようになりました。
VPSで何も変更されておらず、リバーストンネルエンドポイントとしてのみ機能する使い捨てのシングルユーザーマシンです。 CentOS 6.5でOpenSSH_5.3p1を実行しています。接続が失われたときに、sshdがその端のポートを閉じていないようです。その理由を説明するのに途方に暮れているか、またはほぼ完璧な動作の数か月後に今それが突然起こるのはなぜですか.
明確にするために、トンネルが失敗した後、sshdがポートをリッスンしない理由を最初に理解する必要があります。これは、sshdがポートを開いたままにし、ポートを閉じないことが原因であると思われます。それが主な問題のようです。期待どおりの動作(つまり、ポートをすぐに閉じてスクリプトを再接続できるようにする)を数ヶ月行った後、何が原因でこのように動作するのかわかりません。
MadHatterに同意します。これは、機能していないssh接続からのポート転送である可能性が高いということです。現在の問題が別の問題であることが判明した場合でも、遅かれ早かれ、このような機能しないssh接続に遭遇すると予想できます。
このような機能しない接続が発生する可能性のある方法は3つあります。
上記の3つのうちどれが起こっているかを把握することは、3つすべてに対処する方法があるため、それほど重要ではありません。それがキープアライブメッセージの使用です。
sshd_config
のClientAliveInterval
キーワードと、ssh_config
または~/.ssh/config
のServerAliveInterval
間隔を調べる必要があります。
ループでssh
コマンドを実行すると問題なく動作します。何らかの理由で接続が失敗したときにサーバーにフラッディングが発生しないように、ループにもスリープを挿入することをお勧めします。
サーバー上で接続が終了する前にクライアントが再接続すると、新しいssh接続は有効であるがポート転送がない状況になる可能性があります。これを回避するには、クライアント側でExitOnForwardFailure
キーワードを使用する必要があります。
そのサーバーのポートをバインドしているプロセスを見つけることができます
Sudo netstat -apn|grep -w X
それは半端なsshd
である可能性が非常に高いようですが、データを持つことができると仮定するのはなぜですか?これは、スクリプトがトンネルを再起動する前に信号9を送信するPIDを見つけるのに良い方法でもあります。
私にとっては、ssh
トンネルが切断されると、接続がリセットされるまでにしばらく時間がかかるため、ssh
プロセスが引き続きブロックされ、アクティブなトンネルがなくなり、理由がわかりません。回避策は、ssh
を-f
でバックグラウンドに配置し、古い接続がリセットされるのを待たずに新しい接続を生成することです。 -o ExitOnForwardFailure=yes
を使用して、新しいプロセスの数を制限できます。 -o ServerAliveInterval=60
は、現在の接続の信頼性を向上させます。
ssh
コマンドを頻繁に繰り返すことができます。たとえば、cron
、または次のようなスクリプトのループで、ssh
コマンドを実行します。 3分ごと:
while (1)
do
ssh -f user@hostname -Rport:Host:hostport -N -o ExitOnForwardFailure=yes -o ServerAliveInterval=60
sleep 180
done
私の経験では、リモートシステムで「何か」がまだ実行されている場合、sshは正常に終了しないという少し厄介な癖を持っています。例えば。バックグラウンドで開始しました。これは次の方法で再現できます。
ssh <server>
while true; do sleep 60; done&
exit
Sshはログアウトしますが、実際にはセッションを閉じません-リモートプロセスが終了するまで(「trueの間」のループであるため、終了しません)。それは同様のことが起こっている可能性があります-あなたのセッションにはsshによって引き起こされている「スタック」プロセスがあります。ポートは使用中のままであるため、ローカルプロセスで再利用することはできません。