web-dev-qa-db-ja.com

不安定なSSH接続を自動的に再開するための画面など

信頼性の低いwifi環境では、ssh経由でサーバーに接続する必要があります。サーバーでscreenを実行しているので、接続が切断された場合は、再接続してscreenセッションを再開し、中断したところから再開できますが、接続の喪失は依然として大きな時間のシンクです。サーバー上にいると、ターミナルウィンドウがフリーズする傾向があります。そのタブを強制終了し、新しいタブを開いてサーバーにSSHで接続し、スクリーンセッションを再開する必要があります。私はこれをサーバー上で実行中の画面とローカルで画面で試しました。どちらにしても、接続が切断されるとフリーズする傾向があります。

自動的に再接続を試みてセッションを実行し続けるように、画面または画面自体に似た方法を使用できるので、手動で再接続し続ける必要はありませんか?私が接続を失ったとき、それはごく短い期間だと思うことがよくあります-おそらく1秒未満です。

私はUbuntu 14.04 LTSを使用しています、MATEエディション。ありがとう

18
Max Williams

あなたはmoshを使用して見ることができます: https://mosh.org/

moshを使用して接続する信頼性の高いインターネット接続で「ジャンプ」サーバーを設定し、管理する各サーバーへのsshセッションを使用できます。ジャンプサーバーの使用をお勧めするのは、管理しているサーバーにmoshをインストールしたくない場合があるためです。

moshのもう1つの利点は、TCPではなくUDPに基づいており、セッションがIPアドレスの変更、たとえばWiFiからモバイルインターネット接続への移行に耐えることができることです。

明確にするために、moshscreenの代わりではなく、sshです。 screen自体は、クライアントが何らかの理由で停止した場合にセッションに再接続する方法を提供しないため、moshをそれと一緒に使用することをお勧めします。

23

私は tmux をここ数年使用しており、私の経験では、自動的に再接続します。少なくとも、接続が比較的短時間だけ失敗した場合。 tmuxをバックエンドとして byobu を実際に使用していることに注意してください。この堅牢性がtmuxまたはbyobuの機能なのか、それとも2つの組み合わせの機能なのかはわかりませんが、両方を試してみることをお勧めします。

ローカルのArchインストールからさまざまなリモートUbuntuサーバーにVPN経由で接続します。リモコンに接続している間にネットワークケーブルを抜いて、今すぐテストしました。セッションはハングしましたが、ケーブルが再び差し込まれるとすぐに、シームレスに再開しました。

しかし、ルーターを再起動してテストしたところ、接続が戻りませんでした。ネットワークがダウンしていた時間と関係があると思いますが、数秒間ダウンしているだけなら再接続しているようです。

必要に応じて、ターミナルエミュレータとして terminator を使用してこのすべてを行います。

3つすべてがUbuntuリポジトリで利用できます。

Sudo apt-get install tmux terminator byobu

ただし、tmuxまたはbyobuのどちらがssh切断の処理に優れているかは、私にはまったくわかりません。私が知っているのは、私の経験では、短い接続の切断から戻ってくることが多いということだけです。それは私の設定の他の側面にダウンしているかもしれません。

3
terdon

SshのServerAliveオプションを使用して、接続が失敗したことを検出します。

ServerAliveCountMax
ssh(1)がサーバーからメッセージを受信せずに送信できるサーバー生存メッセージ(下記参照)の数を設定します。サーバーアライブメッセージの送信中にこのしきい値に達すると、sshはサーバーから切断し、セッションを終了します。サーバーアライブメッセージの使用は、TCPKeepAlive(下記)とは大きく異なることに注意してください。サーバーアライブメッセージは暗号化されたチャネルを介して送信されるため、なりすましはできません。 TCPKeepAliveによって有効にされるTCPキープアライブオプションはスプーフィング可能です。サーバーアライブメカニズムは、クライアントまたはサーバーが接続がいつ非アクティブになったかを知ることに依存している場合に役立ちます。

デフォルト値は3です。たとえば、ServerAliveInterval(下記参照)が15に設定され、ServerAliveCountMaxがデフォルトのままである場合、サーバーが応答しなくなると、sshは約45秒後に切断します。

ServerAliveInterval
タイムアウト間隔を秒単位で設定します。その後、サーバーからデータが受信されない場合、ssh(1)は暗号化されたチャネルを介してメッセージを送信し、サーバーからの応答を要求します。デフォルトは0で、これらのメッセージがサーバーに送信されないことを示します。

したがって、ServerAliveIntervalを5に設定すると、ネットワークが15秒間フレークアウトすると、sshは自動的に切断されます。

2
Barmar

同様の状況で、Emacs内でeshellを(sshを介して)TRAMPとともに使用する傾向があります。 TRAMPは、必要に応じて、リモートシェルに必要なコマンドを与えるのにそれほど問題を起こすことなく、再接続を処理します。

ただし、eshellは端末としては適していません。つまり、端末で何か特別なことを行うコマンドを実行したり、かなりの期間にわたって継続的に(増分的に)何かを出力したりするコマンドを実行することはできません。

基本的に、EmacsでTRAMPを使って使い始めるのは非常に簡単です。

M-x eshell
cd /user@Host:

免責事項

SSH接続が短時間のネットワーク障害に耐えられない場合は、他の何かが起こっているため、sshとTCPが通常のことを実行できません。

詳細については、以下を参照してください。とにかく:

最も速くて最も汚い無依存ソリューション

次のようなシェルスクリプトを作成します。

#!/bin/sh -

# Tune these numbers depending on how aggressively
# you want your SSH session to get reconnected.
timeout_options='-o ServerAliveInterval=4 -o ServerAliveCountMax=2'

# 255 is the status OpenSSH uses to signal SSH errors, which
# means we want to connect. All other exit statuses suggest
# an intentional exit.
status=255

# Keep opening the SSH connection and immediately dropping into
# `screen` until an intentional exit happens.
while [ "$status" = 255 ]
do
    ssh $timeout_options -t "$@" screen -dR
    status=$?
    # You can add a `sleep` command here or a counter or whatever
    # you might need as far as rate/retry limiting.
done
exit "$status"

これは単にsshに接続してscreenに接続しようとする愚かな単純なループを実行するだけです。ホストまたは通常はssh呼び出しに渡す他のすべてをコマンドライン引数として渡します。

再接続は、SSHが接続でエラーを報告するかどうかに基づいています。つまり、「文字通りWiFIがオンになっていない」などの非SSHエラーを検出するインテリジェンスはありませんが、おそらくそれは問題ではありません君は。

私はあなたがssh-agentまたはパスフレーズなしのSSHキーを持っていると仮定しています。これにより、追加の入力なしで再接続が機能するようになります。

小さな競合状態が発生し、再接続中に人間が認識できないほんの一瞬の間に^Cを押すと、^Cをクライアントターミナルに渡す代わりに、スクリプトを強制終了してしまう可能性があります。接続のハングは、^Cをあまり熱心にマッシュしないでください。

最も簡単な追加ソフトウェアソリューション

あなたはプログラム autossh を試すことができます、それはあなたのUbuntuパッケージリポジトリで利用可能でなければなりません。

ソースからビルドまたは監査する必要がある場合、それは依存関係として追加のライブラリなしでコンパイルされる単一のCプログラムであり、上記の私のハックよりも接続の活性をチェックすることについてより多くのインテリジェンスを持っているようです、およびrscreenに自動接続するscreenスクリプトコマンド。

細部

sshが通常回復する方法

確認のために、私は自分でチェックせずに話すのは好きではないので、答える前に少しテストを実行しました。

Linuxデバイスを使用してWiFiに接続し、LAN上の別のデバイスにSSH接続し、もう一方の端へのssh接続が機能していることを確認し(コマンドを実行できるなど)、クライアントでWiFiを切断した(インターフェースを構成解除する:これ以上のIPアドレスはありません)、sshセッションにさらに多くの文字を入力し(もちろん応答なし)、その後私のWiFiに再接続しました-再接続が実際に少なくとも1回失敗したため信号とその他の要因が悪いため、最終的に再接続しました:sshセッションが回復するまで約5秒間待機しましたが、何も起こらなかったため、もう1つのキーを押すと、sshセッションがすぐに再びアクティブになりました。コマンドラインに表示される切断。

参照してください、sshは、TCPネットワークソケットに書き込み/読み取りを行うだけで、OSが問題を通知し、TCPは実際に非常に長い長時間の接続切断を許容します。

デフォルトのカーネル設定を持つ独自のデバイスに任せると、LinuxのTCPスタックは、接続が停止していることを宣言してsshにエラーを報告する前に、何分もの間完全に無音になる接続を喜んで許容します。 30分以内、または少なくとも確かに、接続のしゃっくりが1秒または1分持続するのに十分な長さの球場で話します。

カバーの下では、Linux TCPスタックは徐々に遅延を増やしながらメッセージを再試行します。つまり、接続が回復するまでに、sshセッションが開始される前に追加の遅延が発生している可能性があります "生きている」。

なぜこれが壊れるのか

多くの場合、TCPスタックが許容する量よりも大幅に短い非アクティブ期間の後に)何かがアクティブに接続を閉じ、その接続状態をsshクライアントに報告できません。

有望な候補者は次のとおりです。

  1. ファイアウォールまたはNATを実行するルーターは、メモリを使用して各ライブTCP接続を記憶する必要があります-DOS攻撃に対する最適化と軽減策として、単に忘れる接続を行い、その後黙って既存の接続を覚えていない場合、接続の途中のパケットは無効に見えるため、無視その結果のパケット。

  2. より適切に動作するファイアウォール/ルーターは、TCP RSTパケットを挿入します。これは通常、connection reset by peerエラーメッセージとして現れますが、リセットパケットはファイアアンドフォーゲットであるため、クライアントへの接続でまだ問題が発生している場合その瞬間にリセットパケットもドロップすると、クライアントは接続がまだ生きていると考えます。

  3. サーバー自体は、予期しないパケットを静かにドロップするファイアウォールポリシーを持っている可能性があります。これにより、サーバーが接続を閉じたとクライアントが認識しない場合は常に、クライアントの接続再開の試行が中断されます。クライアントは接続を継続しようとし続けますが、これらのパケットが属しているライブ接続がサーバーのファイアウォール状態にないため、サーバーはそれを単に無視しています。

    Linuxを実行しているので、サーバーのiptables/ip6tablesまたは、新しいものを使用している場合はnft)をチェックして、許可するものと削除するものを正確に確認してください。 TCP SSHポートで_(新しい/ 確立済み/ 関連パケット)を許可することは非常に一般的ですが、not"無効な"パケット-サイレントでドロップしている場合許可されていないものはすべて、この一般的なセットアップにより、短時間の接続問題の後にこの種のフリーズが発生する可能性があります。

  4. SSHサーバー自体は、TCPのOpenSSHオプションまたはSSHクライアントキープアライブパケットのいずれかを使用して、非アクティブな期間が経過すると接続を閉じるように構成されている可能性があります。これだけでは無期限のハングは発生しませんが、上記のいずれかの状態になる可能性があります。

  5. sshセッションがハングアップした状態になった後、それだけで「ハング解除」するための十分な時間が与えられていない可能性があります。

1
mtraceur