web-dev-qa-db-ja.com

SSHトンネルを確実に開いたままにする方法

私は仕事からSSHトンネルを使用して、さまざまな風変わりなファイアウォールを回っています(私の上司には問題ありません)。問題は、しばらくするとssh接続が通常ハングし、トンネルが壊れることです。

少なくともトンネルを自動的に監視することができれば、トンネルがハングしたときにトンネルを再起動することはできますが、その方法を考え出すことすらできません。

私のSSH接続がハングするのを防ぐ方法を私に言うことができる人にはもちろん、ボーナスポイントがあります!

226
Peltier

あなたは autossh を必要とするように聞こえます。これはSSHトンネルを監視し、必要に応じて再起動します。私たちは数年間それを使ってきました、そしてそれはうまくいくようです。

autossh -M 20000 -f -N your_public_server -R 1234:localhost:22 -C

-Mパラメータ の詳細はこちら

270
KeithB

すべてのステートフルファイアウォールは、しばらくの間その接続のパケットが表示されないと接続を忘れます(接続を閉じずに状態テーブルに接続がいっぱいになるのを防ぐため)。ほとんどのTCP実装は、反対側からの通知なしに、長い時間の経過後にキープアライブパケットを送信します(2時間が一般的な値です)。ただし、キープアライブパケットを送信する前に接続を忘れるステートフルファイアウォールがあると、長命ではあるがアイドル状態の接続がなくなります。

その場合、解決策は接続がアイドル状態にならないようにすることです。 OpenSSHには ServerAliveInterval というオプションがあり、接続が長時間アイドル状態になるのを防ぐことができます(ボーナスとして、ピアが死んだときに検出されます)。接続がアイドル状態であっても早くなります。

37
CesarB

あなた自身のMacまたはLinuxマシンであなたのsshを設定して3分ごとにサーバsshを生き続けるようにしてください。端末を開き、あなたの目に見えない.sshをあなたの家に持って行きます。

cd ~/.ssh/ 

それから1行の設定ファイルを作成します。

echo "ServerAliveInterval 180" >> config

また追加する必要があります:

ServerAliveCountMax xxxx (high number)

デフォルトは3なので、ServerAliveInterval 180は9分後に送信を停止します(ServerAliveIntervalで指定された3分間隔のうち3つ)。

23
David Shaw

次のBashスクリプトを使用して、前のものが死んだときに新しいsshトンネルを生成し続けます。追加のパッケージをインストールしたくない、またはインストールできない場合、またはコンパイラを使用できない場合は、スクリプトを使用すると便利です。

while true
do
  ssh <ssh_options> [user@]hostname
  sleep 15
done

これには接続を自動的に確立するためのキーファイルが必要ですが、autosshの場合も同様です。

21
Jawa

Systemdはこれに理想的です。

以下を含むサービスファイル/etc/systemd/system/sshtunnel.serviceを作成します。

[Unit]
Description=SSH Tunnel
After=network.target

[Service]
Restart=always
RestartSec=20
User=sshtunnel
ExecStart=/bin/ssh -NT -o ServerAliveInterval=60 -L 5900:localhost:5900 user@otherserver

[Install]
WantedBy=multi-user.target

(sshコマンドを適切に変更してください)

  • これはユーザーsshtunnelとして実行されるので、そのユーザーが最初に存在することを確認してください
  • ブート時に開始するように設定するためにsystemctl enable sshtunnelを発行する
  • すぐに起動するためにsystemctl start sshtunnelを発行する

更新2018年1月1日:いくつかのディストリビューション(例えばFedora 27)はSELinuxポリシーを使って防ぐことができます。 systemd initからSSHを使用する場合、必要な免除を提供するためにカスタムポリシーを作成する必要があります。

14
IanB

ServerAliveCountMaxをすべて誤って解釈しているようです。私がドキュメントを理解しているように、接続が切断されずに返事がない場合があるのはサーバーの生きているメッセージの数です。したがって、ここで説明しているような場合には、これを高い値に設定すると、ハングした接続が検出されて終了しないようになります。

ServerAliveIntervalを設定するだけで、接続を忘れるファイアウォールの問題を解決でき、ServerAliveCountMaxをlowにしておくと、発信側は失敗に気付き、接続が失敗した場合は終了することができます。

必要なのは、1)通常の状況下で接続を永続的に開いたままにする、2)接続失敗を検出し、失敗した場合に発信側を終了する、3)毎回sshコマンドを再発行することです。終了(どのようにするかは非常にプラットフォームに依存します。Jawaによって提案された「真の間」のスクリプトは一方向です、OS XIでは実際にlaunchd項目を設定します)。

10
user2793784

トンネルの問題が期限切れのNATセッションによって生成される場合は、常にServerAliveInterval SSHオプションを使用してください。

接続性が完全に低下した場合に備えて、必ず再生成方法を使用してください。少なくとも3つの選択肢があります。

  • autosshプログラム
  • bashスクリプト(while true do ssh ...; sleep 5; done)はsleepコマンドを削除しません、sshはすぐに失敗するかもしれず、あなたはあまりにも多くのプロセスを再生成するでしょう
  • /etc/inittab、ボックスにポートを転送せずに、NATの背後にある別の国に出荷および設置されているボックスにアクセスできるようにするために、あなたへのsshトンネルを作成するように設定できます。

    tun1:2345:respawn:/usr/bin/ssh -i /path/to/rsaKey -f -N -o "ServerAliveInterval 180" -R 55002:localhost:22 user@publicip 'sleep 365d'
    
  • /etc/inittabが利用できないUbuntu上の起動スクリプト:

    start on net-device-up IFACE=eth0
    stop on runlevel [01S6]
    respawn
    respawn limit 180 900
    exec ssh -i /path/to/rsaKey -N -o "ServerAliveInterval 180" -R 55002:localhost:22 user@publicip
    post-stop script
        sleep 5
    end script
    

または常に両方の方法を使用してください。

9
claudiuf

私はこれでこの問題を解決しました:

編集する

~/.ssh/config

そして加えなさい

ServerAliveInterval 15
ServerAliveCountMax 4

Ssh_configの マニュアルページ によると、

ServerAliveCountMax
         Sets the number of server alive messages (see below) which may be
         sent without ssh(1) receiving any messages back from the server.
         If this threshold is reached while server alive messages are
         being sent, ssh will disconnect from the server, terminating the
         session.  It is important to note that the use of server alive
         messages is very different from TCPKeepAlive (below).  The server
         alive messages are sent through the encrypted channel and there‐
         fore will not be spoofable.  The TCP keepalive option enabled by
         TCPKeepAlive is spoofable.  The server alive mechanism is valu‐
         able when the client or server depend on knowing when a connec‐
         tion has become inactive.

         The default value is 3.  If, for example, ServerAliveInterval
         (see below) is set to 15 and ServerAliveCountMax is left at the
         default, if the server becomes unresponsive, ssh will disconnect
         after approximately 45 seconds.  This option applies to protocol
         version 2 only.

 ServerAliveInterval
         Sets a timeout interval in seconds after which if no data has
         been received from the server, ssh(1) will send a message through
         the encrypted channel to request a response from the server.  The
         default is 0, indicating that these messages will not be sent to
         the server.  This option applies to protocol version 2 only.
6
nachopro

ExitOnForwardFailure yesは他の提案への良い付属です。接続していてもポート転送を確立できない場合は、まったく接続していない場合と同じくらい無用です。

3
jcomeau_ictx

ちょっとしたハックですが、これを維持するためにscreenを使うのが好きです。私は現在、何週間も実行されているリモートフォワードを持っています。

例、ローカルから始めます。

screen
ssh -R ......

リモート転送が適用されていて、リモートコンピュータにシェルがある場合

screen
Ctrl + a + d

これで、中断のないリモート転送が可能になりました。トリックは、両端で画面を実行することです

1
landypro

パスワードログインを使用する場合は毎回パスワードを再入力する必要があるため、最近この問題が発生しました。バッチファイルにパスワードが含まれないようにするために、プロンプトでsshpassを繰り返し使用しました。

他の誰かが同じ問題を抱えている場合に備えて、私はこの問題について私の解決策を共有したいと思いました:

#!/bin/bash
read -s -p "Password: " pass
while true
do
    sshpass -p "$pass" ssh user@address -p port
    sleep 1
done
1
Brainfloat

私はSSHトンネルを長期間維持する必要がありました。私の解決策はLinuxサーバから実行されていました、そしてそれは鍵ベースの認証を使用してsshを再生成する小さなCプログラムです。

ハングアップについてはよくわかりませんが、タイムアウトによりトンネルが死んでしまいました。

私は、リスポナーのためのコードを提供したいのですが、今それが見つからないようです。

1
baumgart

sshセッションを再開するのに役立つautosshのようなツールがありますが…本当に便利だと思うのは 'screen'コマンドを実行することです。切断した後でもsshセッションを再開することができます。あなたの接続が本来あるべきほど信頼できない場合に特に便利です。

...それがあなたを助けているのであれば、これが「正しい」答えであることを忘れないでください! ;-)

1
koss

autosshは私たちのニーズを満たしていないので(最初の試みでサーバーに接続できない場合はエラーで存在します)、純粋なbashアプリケーションを書きました: https:// github.com/aktos-io/link-with-server

デフォルトでは、サーバー上のNODEのsshdポート(22)にリバーストンネルを作成します。他の操作(追加のポートの転送、接続時のメールの送信など)を実行する必要がある場合は、スクリプトのon-connectおよびon-disconnectフォルダーを配置できます。

0
ceremcem

私は以前のISPと同様の問題を抱えています。私にとっては、TCP接続、Webサイトの閲覧、メールの送信と同じでした。

解決策は、UDP経由のVPN接続を設定することでした(私はOpenVPNを使っていました)。この接続は、切断の原因となったものすべてに対してより耐性がありました。その後、この接続を通じて任意のサービスを実行できます。

それでも接続に問題がある可能性がありますが、トンネルはより寛容になるので、どのsshセッションでも切断されるのではなく短いホールドアップを感じるようになります。

これを行うには、あなたがあなた自身のサーバー上でセットアップできるVPNサービスをオンラインで必要とするでしょう。

0
hultqvist