ngrokで検証用サーバを公開したものの、私の環境ではちょうど5分間のアイドル時間後にSSHサーバとの接続が切断されてしまいます。私は、Webで情報を確認しながらSSHコンソールでの作業を行うようなやり方をしていますので、5分でセッションが切れてしまうと作業効率が悪くなり問題になります。今回は、SSHのセッション切断を回避するための設定を行います。
なぜタイムアウトがあるのか
SSHの設定ファイルを変更すればセッションタイムアウト時間を変更することができるのですが、その前にもう少しタイムアウトについて深掘りしておきます。
そもそもなぜタイムアウトがあるのかについてです。
ご存じの通り、SSHによってリモートにあるLinux,Mac OS,Windowsなどのコンピュータやサーバを操作・管理することができます。ある時間アイドル状態にあるSSHセッションが切断されるのは、オープン状態で利用されていあにSSHセッションがセキュリティリスクになるからです。そのため、そのようなセッションは強制的に切断されるようになっています。その結果、作業を再開する際には再度ログインが必要となるわけです。
SSHサーバのデフォルトタイムアウト
さて、SSHサーバをインストールした初期状態ではタイムアウトは何分でしょうか。
それはサーバのTCPタイムアウトの設定値に従います。SSHサーバ側ではタイムアウトする設定がなされておらず、デフォルトでは自動的にTCP Keepaliveを使用する設定になっています。
sudo sysctl -a | grep _keepalive [sudo] password for developer: net.ipv4.tcp_keepalive_intvl = 75 net.ipv4.tcp_keepalive_probes = 9 net.ipv4.tcp_keepalive_time = 7200
あれ?上記の値を見ると、確立されたセッションは2時間以上(2時間11分程度 = 7,200秒 + 75秒 × 9回)続くはずですね。でも私の環境では、実際には5分でセッションが切断されます。なぜでしょう。
SSHサーバのデフォルトタイムアウト以外の要因になります。私の検証サーバは社内の検証セグメントにあり、インターネット境界にはファイアウォールが設置されています。多くのファイアウォールは300秒でアイドルセッションを切断します。私がタイムアウトとして感じていたものは、実はファイアウォールによって強制的にセッションが切断されたものだったのです。
ファイアウォールによる強制切断を回避するためには、300秒以内にセッションを保持するための何らかのアクションが必要ということです。アイドルセッションとファイアウォールが認識しなければ、強制的にセッションが切断されることはないためです。対応策としては、サーバ側またはクライアント側でSSHセッションのタイムアウト設定(実際にはキープアライブの設定)を行います。定期的にnullパケットを送信する設定とすることでアイドル状態が続くことを回避します。
サーバ側でのタイムアウト設定
/etc/ssh/sshd_config
ファイルを編集することで、サーバにSSH接続するすべてのクライアントに対するタイムアウトが設定できます。クライアント個別にタイムアウトを設定する場合は、次の節に記載した「クライアント側でのタイムアウト設定」を参照ください。
さて、タイムアウト値は ClientAliveInterval
×
ClientAliveCountMax
となります。よって、設定ファイル内の以下2つのパラメータを調整します。
-
ClientAliveInterval
: 接続を維持するためのnullパケットを送信する間隔 -
ClientAliveCountMax
: nullパケットの送信回数(超過時にセッションが切断)
sudo vi /etc/ssh/sshd_config
スクロールし、ClientAliveInterval
とClientAliveCountMax
パラメータを探します。
# $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. ~ ~ #TCPKeepAlive yes #PermitUserEnvironment no #Compression delayed #ClientAliveInterval 0 #ClientAliveCountMax 3 #UseDNS no
ClientAliveInterval
に300を設定します。また、30分ぐらいはアイドルでもセッションを維持したいので、ClientAliveCountMax
に6を指定します。この設定により、5分間隔で最大6回送信するまでセッションを維持、つまり30分でタイムアウトする設定になります。
ClientAliveInterval 300 ClientAliveCountMax 6
パラメータの編集が完了したらSSHサービスを再起動します。
※私の環境(Ubuntu
20.04 &
PuTTy)ではSSH設定ファイルの再読み込み(reload
)をしてもなぜか設定が反映されず、5分でタイムアウトしていまいました。SSHサービスを再起動したところめでたく想定通りの動きとなり、5分でタイムアウトしなくなりました。
sudo systemctl restart sshd
クライアント側でのタイムアウト設定
PuTTyのようなSSHクライアントを利用している場合は、クライアント側でタイムアウトを設定することができます。この場合、このクライアントのみにタイムアウトが適用されるため、サーバ側のタイムアウト設定が困難な場合はこちらの方法が手っ取り早いですね。
私はPuTTyを使っているため、PuTTyでタイムアウトの設定をする方法を記載します。PuTTyのサイドバーにあるConnectionメニューをクリックすると、Seconds Between Keepalives
というテキストボックスがあります。デフォルトでは0となっていますが、この値を変更することでキープアライブを行うことができます。
タイムアウト値の変更によるリスク
タイムアウト値を変更すると、何度もSSHサーバへ再ログインする必要なく複数のタスクを並行して実施できるようになる点では利便性がよくなります。一方で、例えばSSH接続をオープンしたままコンピュータの前を離れている間、誰かにサーバへのアクセスを許してしまうリスクも増えます。タイムアウトによるセッションの自動切断とは別に、長時間操作をしない場合や作業が終わった際には自発的に接続を切断するような習慣が必要になるかもしれません。