SSH Keepalive入門:簡単設定で接続を維持しよう
はじめに:なぜあなたのSSH接続は切れるのか?
SSH(Secure Shell)は、リモートのサーバーに安全に接続し、コマンドを実行したりファイルを転送したりするための、システム管理者や開発者にとって不可欠なツールです。しかし、SSHを使っていると、しばしば「接続が突然切断される」という問題に遭遇することがあります。特に、しばらく操作せずに放置しておくと、次にコマンドを入力しようとしたときに Write failed: Broken pipe
や Connection closed by remote host
といったエラーが表示されてしまう、という経験は多くの人がしているのではないでしょうか。
この接続切断の問題は、作業の流れを妨げ、時には重要な作業の中断につながり、非常にフラストレーションがたまります。では、なぜこのようなことが起こるのでしょうか? そして、どうすれば安定したSSH接続を維持できるのでしょうか?
その鍵となるのが、「SSH Keepalive」という機能です。SSH Keepaliveを適切に設定することで、アイドル状態が続いても接続が維持され、突然の切断を防ぐことができます。
この記事では、SSH接続が切れる根本的な原因から、SSH Keepaliveの仕組み、クライアント側とサーバー側での具体的な設定方法、そして設定時の注意点やトラブルシューティングまでを、初心者の方にも分かりやすく、かつ技術的な詳細も踏まえながら徹底的に解説します。約5000語のボリュームで、SSH Keepaliveに関する疑問をすべて解消し、あなたのSSHライフをより快適にすることを目指します。
さあ、SSH接続の不安定さにサヨナラし、快適なリモート作業環境を手に入れましょう!
SSH接続が切れる根本的な原因を知る
SSH Keepaliveの設定方法に入る前に、なぜSSH接続が切れるのか、その技術的な原因を理解しておくことは非常に重要です。原因を知ることで、Keepaliveがどのように機能し、問題を解決するのかがより明確になります。SSH接続が切れる主な原因は以下の通りです。
-
ネットワークのアイドルタイムアウト: これが最も一般的な原因です。SSH接続は通常、TCP/IPプロトコル上で確立されます。TCP接続では、一定時間データのやり取りがない状態(アイドル状態)が続くと、ネットワーク機器(ルーター、ファイアウォールなど)やオペレーティングシステムがその接続が「死んでいる」と判断し、強制的に切断することがあります。これは、使用されていないコネクションを解放し、リソースを効率的に使うための仕組みですが、SSHのように長時間アイドル状態になる可能性のあるプロトコルにとっては、意図しない切断の原因となります。
- NAT (Network Address Translation) タイムアウト: 特に家庭用ルーターや企業のファイアウォールで使用されるNATは、内部ネットワークからの外部へのコネクションを管理しています。NATデバイスは、アクティブなコネクションを追跡し、一定時間(多くの場合数分から数十分)データが流れないコネクションをテーブルから削除します。これにより、そのコネクションに関する情報が失われ、以降そのコネクションを通じたパケットが適切にルーティングされなくなり、結果としてSSH接続が切断されます。
- ステートフルファイアウォール: ファイアウォールもまた、TCPコネクションの状態を追跡し、アイドルタイムアウトを設定していることがあります。これは、不要なセッションを閉じ、ファイアウォールの状態テーブルのサイズを管理し、セキュリティリスクを減らすために行われます。
- OSのTCPアイドルタイムアウト: クライアントまたはサーバーのオペレーティングシステム自体にも、TCPコネクションに対するアイドルタイムアウト設定が存在する場合があります。
-
不安定なネットワーク環境: ネットワークの品質が低い場合、パケットロスや遅延が頻繁に発生します。TCPはパケットロスを検知すると再送を試みますが、あまりにも頻繁なパケットロスや長い遅延は、TCPの再送メカニズムが機能しきれなくなり、コネクションがタイムアウトして切断されることがあります。特に、Wi-Fi接続やモバイルネットワークなど、有線接続に比べて不安定になりがちな環境では起こりやすい問題です。
-
サーバー側の負荷または障害: 接続先のサーバーが高負荷状態にある場合、SSHデーモン(
sshd
)がクライアントからの応答を受け付けられなくなることがあります。また、サーバー自体の再起動、ネットワーク設定の変更、SSHデーモンのクラッシュなども、既存のSSH接続を切断する原因となります。 -
クライアント側の障害: クライアント側のマシンのスリープ、ネットワーク接続の切断(Wi-Fiのオフ、ケーブルの抜き差しなど)、SSHクライアントプログラムのクラッシュなども、当然ながら接続切断の原因となります。
SSH Keepaliveは、これらの原因のうち、主に「1. ネットワークのアイドルタイムアウト」による切断を防ぐための機能です。定期的に小さなパケットを送り合うことで、接続がアイドル状態ではないとネットワーク機器やOSに認識させ、タイムアウトによる強制切断を回避します。
SSH Keepaliveとは?その仕組み
SSH Keepaliveは、SSH接続を維持するために、クライアントまたはサーバーが定期的に何らかのデータを相手に送信し、その応答を確認する機能です。これにより、接続がアクティブであるかのように振る舞い、前述のようなネットワーク機器やOSによるアイドルタイムアウトを回避します。
SSH Keepaliveには、大きく分けて2種類の設定があります。
- クライアント側のKeepalive (
ServerAliveInterval
,ServerAliveCountMax
): SSHクライアントがサーバーに対して定期的にパケットを送信します。 - サーバー側のKeepalive (
ClientAliveInterval
,ClientAliveCountMax
): SSHサーバー(sshd
)がクライアントに対して定期的にパケットを送信します。
これらの設定は、どちらか一方、あるいは両方で有効にすることができます。
Keepaliveの仕組みの詳細
SSH Keepaliveが送信するパケットは、実際のコマンド実行やデータ転送のためのパケットとは異なり、非常に小さく、接続が「生きている」ことを確認するためだけのものです。
-
クライアント側Keepalive (
ServerAliveInterval
):- SSHクライアントは、指定された秒数ごとに、サーバーに対してSSHプロトコルレベルのNULLパケット(またはnoop: no operationメッセージ)を送信します。
- サーバーがこのパケットを受信すると、クライアントに対して応答を返します。
- クライアントは、この応答があることで、サーバーがまだ稼働しており、接続が有効であることを確認します。
- もし、指定された回数(
ServerAliveCountMax
で設定)だけパケットを送信してもサーバーからの応答がない場合、クライアントはサーバーが応答不能になったと判断し、自身から接続を切断します。
-
サーバー側Keepalive (
ClientAliveInterval
):- SSHサーバー(
sshd
)は、指定された秒数ごとに、クライアントに対してSSHプロトコルレベルのNULLパケットを送信します。 - クライアントがこのパケットを受信すると、サーバーに対して応答を返します。
- サーバーは、この応答があることで、クライアントがまだ接続されており、応答可能であることを確認します。
- もし、指定された回数(
ClientAliveCountMax
で設定)だけパケットを送信してもクライアントからの応答がない場合、サーバーはクライアントが切断された、あるいは応答不能になったと判断し、自身から接続を切断します。
- SSHサーバー(
どちらの場合も、Keepaliveパケットのやり取りがあることで、TCPコネクション上で常にデータが流れている状態を維持できます。これにより、NATやファイアウォール、OSのアイドルタイムアウト設定に引っかかることなく、接続を維持することが可能になります。
TCP Keepaliveとの違い
SSH Keepaliveと混同しやすいものに、TCP Keepaliveがあります。TCP Keepaliveは、SSHプロトコルよりも下位層にあたるTCPプロトコル自体が持つ機能です。
-
TCP Keepalive:
- OSのTCPスタックが管理します。
- 一定時間アイドル状態が続いた後(デフォルトでは非常に長い時間、例:2時間)、相手に対してTCPレベルのKeepaliveパケット(データ部を持たないACKパケットなど)を送信します。
- 応答があるかどうかで、TCPコネクションがまだ有効かを確認します。
- OSレベルで設定するため、そのOS上のすべてのTCPコネクションに影響を与える可能性があります(ただし、ソケットオプションで個別に設定することも可能)。
- NATや一部のファイアウォールによっては、TCP Keepaliveパケットがフィルタリングされてしまうことがあります。
-
SSH Keepalive:
- SSHプロトコル(アプリケーション層)が管理します。
- SSHクライアントまたはサーバーの設定ファイルで個別に設定します。
- 定期的な間隔(秒単位)でパケットを送信するように設定できます。
- SSHプロトコルレベルのパケットであるため、SSH接続を許可しているファイアウォールであれば、通常は通過します。
一般的なSSH接続の切断問題(特にNATタイムアウトなど)に対しては、SSH Keepaliveの方がより効果的で、かつ設定が簡単です。OS全体のTCP設定を変更するよりも、SSHクライアントやサーバーの設定を変更する方が影響範囲も限定的で安全です。そのため、SSH接続を維持したい場合は、まずSSH Keepaliveの設定を検討するのが良いでしょう。
SSH Keepaliveの設定方法:クライアント側 (~/.ssh/config
)
SSH Keepaliveを導入する際に最も一般的で推奨される方法は、SSHクライアントの設定を変更することです。クライアント側の設定は、その設定を行ったユーザーにのみ影響し、接続先のサーバーに負荷をかけすぎないという利点があります。
クライアント側の設定は、通常、ユーザーのホームディレクトリにある .ssh
ディレクトリ内の config
ファイルで行います。このファイルがない場合は新規作成します。
設定ファイル: ~/.ssh/config
“`bash
設定ファイル全体のコメント
各ホストに対する設定は ‘Host’ ディレクティブで開始する
例1: すべてのホストに対するデフォルト設定
Host *
# サーバーが生きているか確認するための間隔を秒単位で指定
# 指定した秒数ごとに、クライアントからサーバーへNULLパケットを送信する
# 例えば 60 なら、60秒ごとにパケットを送信
ServerAliveInterval 60
# ServerAliveInterval でパケットを送信した後、応答がない場合に
# 何回リトライするかを指定する。
# 指定回数だけ応答がなかった場合、クライアントは接続を切断する。
# 例えば 3 なら、60秒間隔で3回応答がなければ(合計約180秒間応答がなければ)切断
# -1 は無制限(推奨されない)
ServerAliveCountMax 3
例2: 特定のホスト(例: myserver.example.com)に対する設定
デフォルト設定よりもこちらの特定ホスト設定が優先される
Host myserver.example.com
ServerAliveInterval 30
ServerAliveCountMax 5
例3: 別の特定のホスト(IPアドレスでも指定可能)に対する設定
Host 192.168.1.100
ServerAliveInterval 120
ServerAliveCountMax 2
例4: 別名(Alias)を使った設定
ssh myalias と打つと、UserやHostnameなどの設定が適用される
Host myalias
Hostname actual_server_address.com
User your_username
Port 22
ServerAliveInterval 90
ServerAliveCountMax 3
“`
ServerAliveInterval
パラメータの詳細
- 意味: SSHクライアントが、接続先のサーバーに対して生存確認用のパケット(SSHプロトコルレベルのNULLパケット)を送信する間隔を秒単位で指定します。
- 単位: 秒
- デフォルト値: 多くのSSHクライアントでは0(ゼロ)、つまりデフォルトではKeepaliveは無効です。
- 推奨値の考え方:
- ネットワークのアイドルタイムアウトが発生するまでの時間よりも短い間隔に設定する必要があります。一般的なNATやファイアウォールのタイムアウトは数分から数十分(例: 5分, 10分, 30分)であることが多いですが、これは環境によって大きく異なります。
- あまり短すぎる間隔(例: 1秒や5秒)に設定すると、不要なネットワークトラフィックが増加し、クライアントやサーバーにわずかながら負荷をかける可能性があります。特に多くのSSH接続を同時に開いている場合や、バッテリー駆動のノートPCで接続している場合は、消費電力にも影響する可能性があります。
- 一般的な環境であれば、
30
秒から120
秒(2分)程度の間隔が推奨されます。これでほとんどのNATやファイアウォールのタイムアウトに対処できるでしょう。 - もしあなたの環境のネットワーク機器のタイムアウト時間が分かっている場合は、それより十分短い間隔に設定してください。例えば、NATタイムアウトが5分(300秒)なら、
ServerAliveInterval
を60秒や120秒に設定すれば十分です。
- 設定例:
ServerAliveInterval 60
これは、60秒ごとにサーバーに生存確認パケットを送信するという設定です。
ServerAliveCountMax
パラメータの詳細
- 意味:
ServerAliveInterval
で設定された間隔で生存確認パケットを送信した際、サーバーからの応答が何回連続でなかったら、クライアントが接続を切断するかを指定します。 - 単位: 回
- デフォルト値: 通常は3です。
- 推奨値の考え方:
- 一時的なネットワークの瞬断やサーバーの一時的な応答遅延を考慮して、ある程度の回数リトライできるように設定するのが一般的です。
- デフォルト値の
3
は多くのケースで適切ですが、ネットワークが非常に不安定な環境では、もう少し大きな値(例:5
や10
)に設定することも考えられます。 - この値を大きくしすぎると、実際にはサーバーが応答不能になっているにも関わらず、クライアントが切断せずに待機し続ける時間が長くなり、問題の診断を遅らせる可能性があります。
ServerAliveCountMax
にN
を設定した場合、クライアントはServerAliveInterval
秒ごとにパケットを送信し、N
回応答がなかった時点で切断します。つまり、アイドル状態がServerAliveInterval * (ServerAliveCountMax + 1)
秒程度続くと切断される可能性があります(最初のパケット送信から応答がない場合)。例えばServerAliveInterval 60
、ServerAliveCountMax 3
の場合、最初のパケット送信から約60 * (3 + 1) = 240
秒(4分)応答がなければ切断されます。-1
を設定すると、応答がない場合でも無制限にリトライし続けます。これは、サーバーが完全にダウンしている場合でもクライアントが切断しないため、リソースを無駄に消費したり、問題のある接続に気づきにくくなったりする可能性があるため、推奨されません。
- 設定例:
ServerAliveCountMax 3
これは、3回連続でサーバーからの応答がなかった場合に切断するという設定です。
クライアント側設定のまとめと設定例
多くの環境で効果的なクライアント側Keepalive設定の例です。~/.ssh/config
ファイルに追加してください。
“`bash
~/.ssh/config ファイル
Global settings for all hosts (*)
Adjust these values based on your network environment.
Host *
ServerAliveInterval 60 # Send a keepalive packet every 60 seconds
ServerAliveCountMax 3 # Disconnect after 3 consecutive unresponsive packets (approx 60 * 4 = 240 seconds of unresponsiveness)
You can override the global settings for specific hosts if needed.
Example: For a host with a known aggressive NAT timeout
Host problematic-server.com
ServerAliveInterval 30
ServerAliveCountMax 5
“`
設定を変更したら、~/.ssh/config
ファイルを保存します。設定は、次にSSH接続を開始したときから有効になります。既存の接続には影響しません。
設定の確認方法
設定が正しく適用されているかを確認するには、ssh
コマンドに -v
オプション(verboseモード)を付けて実行します。これにより、SSHクライアントの詳細なログが表示されます。
bash
ssh -v your_server_address
出力の中に、以下のような行が表示されていれば、Keepalive設定が読み込まれ、適用されていることが分かります。
...
debug1: Reading configuration data /home/your_user/.ssh/config
debug1: /home/your_user/.ssh/config line 7: Applying options for *
debug1: /home/your_user/.ssh/config line 13: Applying options for your_server_address # もし特定ホスト設定があれば
debug1: Setting ServerAliveInterval based on config: 60
debug1: Setting ServerAliveCountMax based on config: 3
...
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Offering publickey authentication: /home/your_user/.ssh/id_rsa
debug1: Server accepts key: pkalg ssh-rsa blksize 32
debug1: Authentication succeeded (publickey).
Authenticated to your_server_address (via proxy: none).
debug1: channel 0: new [client-session]
debug1: Requesting [email protected]
debug1: Entering interactive session.
debug1: pledge: filesystem
debug1: Sending environment.
debug1: Sending subsystem sftp
debug1: subsystem request sent
debug1: server_alive_interval 60
debug1: server_alive_count_max 3
...
上記のログで server_alive_interval
と server_alive_count_max
が設定した値になっていることを確認してください。接続が確立された後、設定した ServerAliveInterval
秒が経過すると、以下のようなログが表示されるはずです(ただし、ServerAliveCountMax
に達して切断される場合などに明確なメッセージが出る場合が多いです)。
debug1: Sending SSH2_MSG_KEXINIT
... (しばらく待つ - ServerAliveInterval秒後) ...
debug1: Sending keep alive packet
SSH Keepaliveの設定方法:サーバー側 (/etc/ssh/sshd_config
)
サーバー側のKeepalive設定は、そのサーバーに接続するすべてのクライアントに影響します。これは、特定のユーザーだけでなく、サーバーに接続する誰もがKeepaliveの恩恵を受けられるという利点がある一方で、設定によってはサーバーに不要な負荷をかけたり、DoS攻撃のリスクをわずかに高めたりする可能性もあるという点を理解しておく必要があります。
サーバー側の設定は、SSHデーモン(sshd
)の設定ファイルである /etc/ssh/sshd_config
で行います。このファイルは通常、管理者権限(root権限)でのみ編集可能です。
設定ファイル: /etc/ssh/sshd_config
“`bash
設定ファイル全体のコメント
SSHデーモンの設定
クライアントが生きているか確認するための間隔を秒単位で指定
指定した秒数ごとに、サーバーからクライアントへNULLパケットを送信する
デフォルトは 0 (無効) またはサーバーの設定に依存
例: 60秒ごとに送信
ClientAliveInterval 60
ClientAliveInterval でパケットを送信した後、応答がない場合に
何回リトライするかを指定する。
指定回数だけ応答がなかった場合、サーバーはクライアントとの接続を切断する。
デフォルトは 3
例: 3回応答がなければ切断
ClientAliveCountMax 3
その他のsshd設定が続く…
Port 22
ListenAddress 0.0.0.0
Protocol 2
…
“`
ClientAliveInterval
パラメータの詳細
- 意味: SSHサーバー(
sshd
)が、接続しているクライアントに対して生存確認用のパケット(SSHプロトコルレベルのNULLパケット)を送信する間隔を秒単位で指定します。 - 単位: 秒
- デフォルト値: 通常は0(ゼロ)、つまりデフォルトではサーバー側Keepaliveは無効です。ただし、OSのディストリビューションによってはデフォルト値が設定されている場合もあります。
- 推奨値の考え方:
- これもクライアント側の
ServerAliveInterval
と同様に、ネットワークのアイドルタイムアウト時間よりも短い間隔に設定する必要があります。 - サーバーに接続するクライアントの数が多い場合、あまり短い間隔に設定すると、サーバーが多数のKeepaliveパケットを送信・処理することになり、サーバーの負荷が増加する可能性があります。
- 一般的な環境であれば、
60
秒から300
秒(5分)程度の間隔が推奨されます。クライアント側の設定よりも、サーバー側ではやや長めの間隔を設定することが多いです。 ClientAliveInterval
を設定すると、そのサーバーに接続するすべてのクライアントがこの影響を受けます。
- これもクライアント側の
ClientAliveCountMax
パラメータの詳細
- 意味:
ClientAliveInterval
で設定された間隔で生存確認パケットを送信した際、クライアントからの応答が何回連続でなかったら、サーバーが接続を切断するかを指定します。 - 単位: 回
- デフォルト値: 通常は3です。
- 推奨値の考え方:
- クライアント側の
ServerAliveCountMax
と同様に、一時的なネットワークの瞬断やクライアントの一時的な応答遅延を考慮して設定します。 - デフォルト値の
3
は多くのケースで適切です。これを大きくしすぎると、実際にはクライアントが切断されているにも関わらず、サーバー側で不要なリソース(TCPコネクション、プロセスなど)を保持し続ける時間が長くなります。これは、特にサーバーのリソースが限られている場合や、多数のクライアントが接続する可能性がある場合に問題となることがあります。 ClientAliveCountMax
にN
を設定した場合、サーバーはClientAliveInterval
秒ごとにパケットを送信し、N
回応答がなかった時点で切断します。つまり、クライアントがアイドル状態になってから約ClientAliveInterval * (ClientAliveCountMax + 1)
秒後にサーバー側から切断されます。
- クライアント側の
サーバー側設定のまとめと設定例
サーバー側の /etc/ssh/sshd_config
に追加する設定例です。
“`bash
/etc/ssh/sshd_config ファイル
Keepalive settings
Uncomment or add these lines
Send keepalive packets to clients every 60 seconds
ClientAliveInterval 60
Disconnect client after 3 consecutive unresponsive packets (approx 60 * 4 = 240 seconds of unresponsiveness)
ClientAliveCountMax 3
Make sure these values are shorter than your network’s idle timeout for sessions.
“`
設定を変更したら、/etc/ssh/sshd_config
ファイルを保存します。設定を有効にするには、SSHデーモン(sshd
)を再起動する必要があります。
SSHデーモンの再起動方法
使用しているLinuxディストリビューションによってコマンドが異なります。Systemdを使用している最近のディストリビューション(CentOS 7/8, RHEL 7/8, Ubuntu 15.04以降, Debian 8以降など)では以下のコマンドを使用します。
bash
sudo systemctl restart sshd
Systemdを使用していない古いディストリビューション(CentOS 6, Ubuntu 14.04など)では以下のコマンドを使用します。
“`bash
sudo service ssh restart
または
sudo /etc/init.d/ssh restart
“`
再起動が成功したか確認するには、ステータスを確認します。
“`bash
sudo systemctl status sshd
または
sudo service ssh status
“`
sshd
の再起動に失敗した場合、設定ファイルに文法エラーがある可能性があります。再起動前に設定ファイルの構文チェックを行うこともできます(Systemdの場合)。
bash
sudo sshd -t
エラーが表示されなければ、設定ファイルは正しい構文です。
サーバー側設定の注意点
- 管理者権限が必要:
/etc/ssh/sshd_config
の編集とsshd
の再起動にはroot権限が必要です。 - 全クライアントに影響: この設定は、そのサーバーに接続するすべてのクライアントに対して適用されます。一部のクライアントにだけKeepaliveを有効にしたい場合は、クライアント側設定を利用すべきです。
- サーバー負荷: クライアント数が非常に多い場合や、
ClientAliveInterval
を短く設定しすぎると、サーバーの負荷が増加する可能性があります。慎重に値を設定してください。 - DDoSリスク (低リスク): 極端なケースですが、大量の偽のクライアントが接続を試み、応答しないKeepaliveパケットをサーバーに大量に送りつけさせるようなDDoS攻撃のシナリオも理論上は考えられます。しかし、現実的には他の攻撃手法の方が容易であるため、Keepalive設定自体が主要なDDoS攻撃ベクトルとなることは稀です。適切な
ClientAliveCountMax
設定により、応答しないクライアントは早めに切断されるため、このリスクは軽減されます。
一般的には、特定のユーザーが自分の環境で接続を維持したい場合はクライアント側設定を、そのサーバーへのすべての接続を維持したい場合は(サーバー負荷に注意しつつ)サーバー側設定を行うのが良いでしょう。両方設定されている場合は、サーバー側設定が優先されます。これは、サーバーがクライアントの切断を検出してリソースを解放することを優先するためです。
SSH Keepaliveの設定方法:コマンドラインオプション
~/.ssh/config
ファイルや /etc/ssh/sshd_config
を変更することなく、一時的に特定のSSH接続でKeepaliveを有効にしたい場合は、ssh
コマンドを実行する際にオプションとして指定することも可能です。
クライアント側のKeepaliveオプションは -o
を使って指定します。
ServerAliveInterval <seconds>
ServerAliveCountMax <count>
例:SSH接続を開始する際に、Keepaliveを有効にする
bash
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 your_server_address
このコマンドは、~/.ssh/config
に記述されている設定よりも優先されます(ただし、Host *
の設定よりは優先され、特定ホストの設定と同じ優先度になりますが、コマンドラインオプションが最も優先されます)。
これは、一時的に特定の接続だけKeepaliveを試したい場合や、設定ファイルを変更する権限がない場合などに便利です。ただし、毎回コマンドを入力するのは手間なので、恒久的に設定したい場合は設定ファイルに記述するのが一般的です。
TCP Keepaliveとの比較とどちらを使うべきか
前述の通り、SSH Keepaliveはアプリケーション層(SSHプロトコル)、TCP Keepaliveはトランスポート層(TCPプロトコル)で動作します。では、どちらを使うべきなのでしょうか?
結論から言うと、SSH接続の安定性を目的とする場合は、まずSSH Keepalive(特にクライアント側設定)を利用するのが推奨されます。
その理由は以下の通りです。
- 設定の容易さと影響範囲: SSH KeepaliveはSSHクライアント/サーバーの設定ファイルで簡単に設定でき、その影響範囲はSSH接続のみに限られます。一方、TCP KeepaliveはOSレベルの設定変更が必要になることが多く、そのOS上のすべてのTCPコネクションに影響する可能性があります。
- NATやファイアウォールでの通過: SSHプロトコルは通常、SSHポート(デフォルト22)を開けているファイアウォールを通過できます。SSH KeepaliveパケットもSSHプロトコルの仕様内のデータであるため、同様に通過しやすい傾向があります。一方、TCP Keepaliveパケットはプロトコルとして異なる特性を持つため、一部のNATやステートフルファイアウォールによって正しく扱われず、タイムアウトを回避できない場合があります。
- 目的の明確さ: SSH KeepaliveはSSHセッションの生存確認に特化しています。アイドル状態のSSHセッションを意図的に維持するためのものです。TCP Keepaliveは汎用的なTCPコネクションの生存確認であり、デフォルト設定では非常に長い間隔が設定されており、多くの場合アイドルタイムアウトを回避する目的には適していません。
- 応答性の確認: SSH Keepaliveは、相手のSSHデーモン(またはクライアントプログラム)が応答しているかを確認します。TCP Keepaliveは、相手のOSのTCPスタックが応答しているかを確認するに過ぎません。SSHデーモンがクラッシュしている場合でも、OSは応答する可能性があります。SSH Keepaliveの方が、より「リモートシェルとして利用可能か」という観点での生存確認に適しています。
ただし、以下のようなケースではTCP Keepaliveも検討に値するかもしれません。
- SSH以外のTCPアプリケーションでも同様のアイドル切断問題が発生している場合。
- 非常に古いOSやSSHクライアント/サーバーでSSH Keepaliveが利用できない場合。
- (稀ですが)SSH Keepaliveパケットが特定のネットワーク機器で問題を起こす場合。
多くのLinuxシステムでTCP Keepalive関連の設定を確認・変更するには、sysctl
コマンドを使用します。
“`bash
TCP Keepaliveが有効か (1なら有効)
sysctl net.ipv4.tcp_keepalive_intvl
TCP Keepaliveのアイドル時間 (秒) – この時間アイドル状態が続くと最初のKeepaliveパケットが送信される
sysctl net.ipv4.tcp_keepalive_time
TCP Keepaliveの再送間隔 (秒)
sysctl net.ipv4.tcp_keepalive_intvl
TCP Keepaliveの再送回数
sysctl net.ipv4.tcp_keepalive_probes
“`
これらの設定は /etc/sysctl.conf
や /etc/sysctl.d/
以下で永続化できますが、通常はSSH Keepaliveを設定するだけで十分であり、OS全体のTCP設定を変更する必要はありません。
結論として、SSH接続の切断に悩んでいるなら、まずクライアント側の .ssh/config
で ServerAliveInterval
と ServerAliveCountMax
を設定することから始めるのが、最も簡単で効果的なアプローチです。サーバー側の sshd_config
で ClientAliveInterval
と ClientAliveCountMax
を設定するのは、そのサーバーに接続するすべてのユーザーに対して接続維持を強制したい場合に検討すると良いでしょう。
Keepalive設定のトラブルシューティング
SSH Keepaliveを設定したにも関わらず、やはり接続が切れてしまう場合、いくつかの原因が考えられます。トラブルシューティングのポイントを見ていきましょう。
-
設定ファイルが正しく読み込まれているか?
- クライアント側:
.ssh/config
ファイルの場所は正しいか? (~/.ssh/config
)。ファイル名やディレクトリ名に間違いはないか? ファイルのパーミッションは適切か?(自分だけが読み書きできるようにchmod 600 ~/.ssh/config
を推奨)。設定を保存した後、新しいSSH接続で試したか?(既存の接続には反映されない)。ssh -v
オプションを使って、設定ファイルが読み込まれているか、Keepalive関連のオプションが設定されているかを確認する(前述の「設定の確認方法」を参照)。 - サーバー側:
/etc/ssh/sshd_config
ファイルの場所は正しいか? ファイルのパーミッションは適切か? 設定を保存した後、sshd
サービスを再起動したか? 再起動は成功したか?sudo systemctl status sshd
やsudo service ssh status
で確認する。sshd -t
で設定ファイルの構文チェックを行う。
- クライアント側:
-
設定値は適切か?
ServerAliveInterval
やClientAliveInterval
の値は、ネットワークのアイドルタイムアウト時間よりも十分短いか? 例えKeepaliveを設定しても、Keepalive間隔よりも短い時間でNATやファイアウォールがタイムアウトする設定になっている場合は効果がありません。ネットワーク管理者やISPに確認するか、推測で安全側の短い間隔(例: 30秒)から試してみる。ServerAliveCountMax
やClientAliveCountMax
の値が0
や1
になっていないか? これでは一時的な瞬断で即座に切断されてしまいます。少なくとも3
以上の値に設定するのが一般的です。- 値の単位は秒であることに注意。例えば「5分おき」にしたい場合は
300
と設定します。
-
ファイアウォールによるブロック?
- クライアント側またはサーバー側のファイアウォールが、Keepaliveパケット(通常はSSHポート上の小さなTCPパケット)を誤ってブロックしている可能性は低いですが、全くないとは言えません。特に厳格なファイアウォールポリシーが設定されている場合は確認が必要です。SSH自体の通信が許可されているなら、Keepaliveパケットも許可されているはずですが、念のため確認しましょう。
- 中間にあるネットワーク機器(企業のファイアウォールなど)が、SSH Keepaliveパケットの挙動を不審と見なしてブロックしている可能性もゼロではありません。
-
ネットワーク自体の問題が深刻すぎる?
- Keepaliveは「アイドルタイムアウト」を防ぐためのものであり、根本的な「ネットワークの不安定性」(頻繁なパケットロス、高い遅延、帯域不足)を解決するものではありません。もしネットワークが非常に不安定で、通常データ通信すらままならないような状況であれば、Keepaliveパケットの応答すら返ってこないため、Keepaliveを設定しても結局切断されてしまいます。
- この場合は、ネットワーク環境自体を見直す必要があります。有線接続に切り替える、Wi-Fiルーターを再起動する、他のネットワークトラフィックが帯域を圧迫していないか確認する、といった対策が必要です。
-
サーバー側の根本的な問題?
- サーバーが高負荷で応答が非常に遅延している、
sshd
プロセスがハングしている、サーバーのネットワークインターフェースに問題があるなど、サーバー側の問題でKeepaliveパケットに応答できない可能性もあります。サーバー側のリソース使用状況やログを確認してみましょう。
- サーバーが高負荷で応答が非常に遅延している、
-
両方設定している場合の優先順位:
- クライアント側とサーバー側の両方でKeepalive設定を行っている場合、通常はサーバー側の設定が優先されます。これは、サーバーがクライアントの状態を判断し、不要なリソースを解放することを優先するためです。もしクライアント側で設定した値よりも、サーバー側で設定した値の方が切断までの時間が短い場合、サーバー側の設定によって切断されることになります。両方設定している場合は、どちらの設定値が「より早く切断するか」を確認し、意図した通りになっているか確認しましょう。
トラブルシューティングの際は、まず ssh -v
の出力でKeepalive設定が正しく認識されているかを確認し、次にKeepalive間隔や回数の設定値を見直すのが基本的なステップです。それでも解決しない場合は、ネットワーク環境やサーバー側の問題も含めて広範囲に調査する必要があります。
Keepalive設定のベストプラクティス
安定したSSH接続を維持するためのKeepalive設定のベストプラクティスをまとめます。
-
基本はクライアント側設定から:
- 特別な理由がない限り、まずはSSHクライアントの
~/.ssh/config
ファイルでServerAliveInterval
とServerAliveCountMax
を設定することから始めましょう。 - これにより、自分のSSH接続だけにKeepaliveが適用され、接続先のサーバーに不要な負荷をかけずに済みます。また、自分のネットワーク環境や接続先サーバーの特性に合わせて柔軟に設定値を調整できます。
- 特別な理由がない限り、まずはSSHクライアントの
-
適切な間隔 (
ServerAliveInterval
/ClientAliveInterval
) の設定:- ネットワークのアイドルタイムアウト時間よりも短く、かつ短すぎない値を選びましょう。
- 一般的な家庭環境やVPN経由の接続であれば、
60
秒から120
秒程度が妥当な出発点です。 - サーバー側で設定する場合は、接続クライアント数やサーバー負荷を考慮し、クライアント側よりもやや長めの間隔(例:
60
秒から300
秒)を設定することが多いです。
-
適切なリトライ回数 (
ServerAliveCountMax
/ClientAliveCountMax
) の設定:- 一時的なネットワークの瞬断や応答遅延を許容するために、デフォルト値の
3
は多くの場合適切です。 - ネットワークが極端に不安定な場合は、少し増やしても良いですが、あまり大きくしすぎないようにしましょう(例えば
5
や10
)。 -1
(無制限) の設定は、リソースを無駄にする可能性があるため避けましょう。
- 一時的なネットワークの瞬断や応答遅延を許容するために、デフォルト値の
-
両方設定する場合の考慮事項:
- クライアント側とサーバー側の両方でKeepaliveを設定している場合、サーバー側の設定が切断を判断する上で優先されることを理解しておきましょう。サーバー側の
ClientAliveInterval * (ClientAliveCountMax + 1)
秒が、クライアント側のServerAliveInterval * (ServerAliveCountMax + 1)
秒よりも短い場合、サーバー側の設定に基づいてより早く切断されます。 - サーバー側設定は、すべてのクライアントに対して接続維持ポリシーを強制したい場合に有効ですが、サーバー負荷やDDoSリスク(わずかですが)を考慮する必要があります。
- クライアント側とサーバー側の両方でKeepaliveを設定している場合、サーバー側の設定が切断を判断する上で優先されることを理解しておきましょう。サーバー側の
-
verboseモード (
ssh -v
) で確認:- 設定変更後は、必ず
ssh -v
で設定が正しく読み込まれているか、そしてKeepaliveパケットの送受信が行われているか(Sending keep alive packet
などのログ)を確認しましょう。
- 設定変更後は、必ず
-
ネットワーク環境を考慮:
- 接続先のネットワーク環境(安定性、NAT/ファイアウォールの種類と設定)によって、最適なKeepalive設定は異なります。可能であれば、ネットワーク管理者にタイムアウト設定などを確認できると、より適切な値を設定できます。
これらのベストプラクティスに従うことで、多くのSSH接続切断問題を解決し、安定したリモート作業環境を構築できるでしょう。
Keepalive以外の接続維持策
SSH Keepaliveは最も一般的で効果的な接続維持策ですが、Keepaliveだけでは解決できない問題があったり、他の目的で別のツールがより適していたりする場合があります。Keepalive以外の接続維持策もいくつか知っておくと良いでしょう。
-
screen
やtmux
の利用:screen
やtmux
は、リモートサーバー上で仮想端末(セッション)を作成し、そのセッションをデタッチ(detach)してSSH接続を切断しても、サーバー上でセッションを実行し続けることができるツールです。- 次に接続する際に、そのセッションにアタッチ(attach)することで、前回の作業状態(実行中のプログラムやシェル履歴など)をそのまま引き継いで作業を再開できます。
- SSH接続が切断されてもサーバー上のセッションは生き残るため、長時間のコンパイルやデータ処理など、途中で接続が切れてほしくない作業を行う際に非常に有効です。
- これはKeepaliveのようにSSH接続自体を維持するのではなく、「接続が切れても作業は失われないようにする」というアプローチです。Keepaliveと併用することも可能です。
-
欠点としては、事前にリモートサーバーに
screen
やtmux
をインストールしておく必要がある点と、SSH接続が切れている間は作業中の画面を見ることができない点です。 -
簡単な使い方(tmuxの例):
- サーバーにSSH接続後、
tmux
コマンドを実行して新しいセッションを開始します。 - 作業中に接続を維持したい場合は、
Ctrl+b
の後にd
を押してセッションをデタッチします。SSH接続はそのまま切断します。 - 再び作業を再開したい場合は、サーバーにSSH接続し、
tmux attach
またはtmux a
コマンドを実行して前回のセッションにアタッチします。 - 実行中のセッションリストを確認するには
tmux ls
コマンドを使用します。
- サーバーにSSH接続後、
-
Mosh (Mobile Shell) の利用:
- Moshは、SSHに代わるリモートシェルとして開発されたツールです。不安定なネットワーク環境(特にモバイルネットワークやWi-Fi)での利用に特化しており、SSHよりも優れた応答性と接続維持能力を持っています。
- MoshはTCPではなくUDPプロトコルを使用します。これにより、IPアドレスが変わっても(ローミングしても)セッションを維持したり、一時的なネットワークの瞬断にも強くなっています。
- クライアント側の入力に対する応答が非常に速く、ローカルでの入力と同じような感覚で作業できる「ローカルエコー」機能も特徴です。
-
欠点としては、クライアントとサーバーの両方にMoshをインストールする必要がある点と、TCPではなくUDPポートを開ける必要がある点です。また、ポートフォワーディングなど、SSHの高度な機能の一部は直接サポートされていません。
-
簡単な使い方:
- クライアントとサーバーの両方にMoshをインストールします。
- クライアントで
mosh your_server_address
コマンドを実行します(SSHポートではなくUDPポートを使用します)。
-
定期的に簡単なコマンドを実行するスクリプト:
- これはあまりエレガントな方法ではありませんが、SSH接続上で定期的に
date
やpwd
のような簡単なコマンドを実行するスクリプトをバックグラウンドで実行しておくことで、人工的に通信を発生させ、アイドルタイムアウトを防ぐという力技です。 - 例えば、SSH接続後に
while true; do date; sleep 60; done &
のようなコマンドを実行しておけば、60秒ごとに日付が表示され、接続がアクティブな状態を維持できます。 - この方法はKeepaliveパケットよりも大きなデータを送信するため、ネットワーク帯域やサーバー負荷の観点からはKeepaliveよりも効率が悪いです。また、サーバー側のログインシェルや設定によっては意図した通りに動作しない可能性もあります。Keepaliveが使えない場合の最後の手段として考える程度が良いでしょう。
- これはあまりエレガントな方法ではありませんが、SSH接続上で定期的に
これらの方法も、SSH接続の維持や作業の中断防止に役立ちますが、それぞれ目的や仕組みが異なります。Keepaliveは「接続を維持すること自体」に特化しており、最もシンプルかつSSHプロトコル標準の機能です。まずはKeepaliveの設定を試し、それで不十分な場合や別の要件(作業の中断からの復帰など)がある場合に、screen
/tmux
や Mosh を検討すると良いでしょう。
まとめ:快適なSSH接続のために
この記事では、SSH接続がなぜ切れるのかという基本的な疑問から出発し、SSH Keepaliveの仕組み、クライアント側とサーバー側での具体的な設定方法、TCP Keepaliveとの違い、トラブルシューティング、そしてKeepalive以外の対策まで、SSH Keepaliveに関する詳細な情報を提供しました。
多くのSSH接続切断の原因は、ネットワーク機器やOSによるアイドルタイムアウトです。これを防ぐ最も効果的で簡単な方法は、SSHクライアントまたはサーバーでKeepalive機能を有効にすることです。
- クライアント側 (
~/.ssh/config
):ServerAliveInterval
とServerAliveCountMax
を設定するのが最も一般的で推奨される方法です。自分のホームディレクトリの設定ファイルを編集するだけで済み、他のユーザーやサーバーに影響を与えずに、自分の環境に合わせて設定を調整できます。 - サーバー側 (
/etc/ssh/sshd_config
):ClientAliveInterval
とClientAliveCountMax
を設定すると、そのサーバーに接続するすべてのクライアントにKeepaliveが適用されます。ただし、設定変更には管理者権限が必要で、サーバー負荷への考慮も必要です。 - 設定値:
ServerAliveInterval
やClientAliveInterval
はネットワークのアイドルタイムアウト時間より短く、かつ頻繁すぎない間隔(例: 60秒)、ServerAliveCountMax
やClientAliveCountMax
は一時的な瞬断を許容できる回数(例: 3回)に設定するのが良いでしょう。 - トラブルシューティング: 設定ファイルや
sshd
サービスの再起動を確認し、ssh -v
オプションで詳細なログを見て問題の原因を探るのが基本です。 - Keepalive以外の対策:
screen
/tmux
はセッションのデタッチ/アタッチによる作業継続に、Moshは不安定なネットワークでの接続維持と応答性向上に優れています。Keepaliveで不十分な場合や、別の要件がある場合に検討しましょう。
SSH Keepaliveを適切に設定することで、アイドル状態が続いても接続が維持され、「放置しておくと切れてしまう」というストレスから解放されます。これは、サーバーでの長時間の作業や、不安定なネットワーク環境からの接続において、作業効率と快適性を大きく向上させます。
さあ、ぜひあなたのSSHクライアントまたはサーバーの設定ファイルを開き、SSH Keepaliveを有効にしてみてください。きっと、より安定した、快適なSSH接続環境を手に入れることができるはずです。
この記事が、あなたのSSH Keepalive導入の助けとなり、よりスムーズなリモート作業の実現に貢献できれば幸いです。