本記事には広告(アフィリエイトリンク)が含まれます。

SSH応用 多段SSH・ハードニング・tmux

Linuxエンジニア養成講座 第27回|全36回・フェーズ3「ネットワークとインフラ基盤」の最終回(12/12回目)です。
前回まで: 第16回でTCP/IPの基礎、第17回でnmcliによるIP設定と疎通確認、第18回でプロキシ・DNS・NTPのクライアント設定、第19回でパッケージ管理、第20回でfirewalldによる通信制御、第21回第22回で発展トピック(ボンディング・VLAN)、第23回でログ管理、第24回でcron / systemd timer、第25回でLVMによるストレージ管理、第26回でシェルスクリプト実践を学びました。
今回学ぶこと: SSHの鍵認証・多段接続・サーバー設定のハードニング・tmuxによるセッション管理を実践します。

前回の予告で「多段SSH(ProxyJump)による alma-main 経由での alma-sub 接続、sshd 設定のハードニング、tmux によるセッション管理」とお伝えしました。今回はその内容を順に進めていきます。フェーズ3の最終回として、SSHをより安全かつ便利に使いこなす技術を身につけます。

この記事を読み終えると、以下のことができるようになります。

  • VM間(alma-main → alma-sub)でSSH鍵認証を設定し、パスワードなしで接続できる
  • ProxyJump(多段SSH)の仕組みを理解し、~/.ssh/config で設定できる
  • sshd の設定をハードニング(強化)し、構文チェック後に安全に反映できる
  • tmux でセッションを管理し、SSH切断時にも作業を継続できる

SSH 鍵認証(alma-main → alma-sub)

第5回で、ホストPC から alma-main への SSH 鍵認証を体験しました。あのときは「パスワード認証よりも安全な接続方法」として紹介しましたが、今回は VM 間の接続に鍵認証を設定します。

なぜ VM 間の鍵認証が必要なのでしょうか。インフラの現場では、あるサーバーから別のサーバーへ自動でファイルを転送したり、スクリプトでリモートコマンドを実行したりする場面が頻繁にあります。そのたびにパスワードを手入力するわけにはいきません。第35回で学ぶ Ansible も、SSH 鍵認証が前提です。

鍵ペアの生成

alma-main の developer ユーザーで鍵ペア(秘密鍵と公開鍵)を生成します。alma-main で実行してください。

実行コマンド:

$ ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519

各オプションの意味は以下のとおりです。

  • -t ed25519 … 鍵の種類を指定します。ed25519 は現在推奨されるアルゴリズムです
  • -N "" … パスフレーズを空にします。自動化用途ではパスフレーズなしが一般的です
  • -f ~/.ssh/id_ed25519 … 鍵ファイルの保存先を指定します

生成されたファイルを確認します。

実行コマンド:

$ ls -la ~/.ssh/

実行結果:

合計 12
drwx------. 2 developer developer  69  4月  4 01:41 .
drwx------. 3 developer developer  95  3月 24 13:10 ..
-rw-------. 1 developer developer 101  3月 24 13:06 authorized_keys
-rw-------. 1 developer developer 411  4月  4 01:41 id_ed25519
-rw-r--r--. 1 developer developer 101  4月  4 01:41 id_ed25519.pub

id_ed25519 が秘密鍵、id_ed25519.pub が公開鍵です。秘密鍵のパーミッションが 600(所有者のみ読み書き可)になっている点に注目してください。秘密鍵は名前のとおり秘密にするファイルですので、他のユーザーに読まれてはいけません。

公開鍵の中身も見てみます。

実行コマンド:

$ cat ~/.ssh/id_ed25519.pub

実行結果:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIApWPevx9uJd7r3PGal1eAKqRi8qEsqbzTTY+zD66yJB developer@alma-main

「アルゴリズム名 鍵データ コメント」の3つのフィールドからなる1行のテキストです。このテキストを接続先の alma-sub に登録します。

公開鍵を alma-sub にコピー

ssh-copy-id コマンドを使うと、公開鍵を接続先サーバーの ~/.ssh/authorized_keys に自動で追記してくれます。alma-main で実行してください。

実行コマンド:

$ ssh-copy-id developer@10.0.1.3

初回接続時はフィンガープリントの確認(yes/no)が表示されます。yes と入力してください。その後、alma-sub の developer ユーザーのパスワードを入力すると、公開鍵がコピーされます。成功すると「Number of key(s) added: 1」のようなメッセージが表示されます。

ssh-copy-id が内部で行っていることは、次の2ステップです。

  1. 接続元の公開鍵(~/.ssh/id_ed25519.pub)を読み取る
  2. 接続先の ~/.ssh/authorized_keys ファイルに追記する

手動で公開鍵をコピー & ペーストすることもできますが、ssh-copy-id を使えばディレクトリ作成やパーミッション設定も自動で行ってくれるため、設定ミスが起きにくくなります。

鍵認証での接続テスト

パスワードなしで alma-sub に接続できるか確認します。alma-main で実行してください。

実行コマンド:

$ ssh developer@10.0.1.3 hostname

実行結果:

alma-sub

パスワードを聞かれずに alma-sub と表示されれば成功です。ssh コマンドの後ろにコマンドを指定すると、接続先でそのコマンドを実行して結果を返すという使い方は、スクリプトからリモートサーバーを操作するときに多用します。

鍵認証の詳細なオプションを知りたい場合は man ssh-keygen を参照してください。

多段SSH(ProxyJump)

ここまでは「alma-main から alma-sub に直接接続する」という構成でした。しかし現場では、本番サーバーに直接SSHさせず「踏み台サーバー(bastion)」を経由させる設計が一般的です。

踏み台を経由させる目的はセキュリティにあります。

  • アクセス制御の一元化 — 全SSH接続を踏み台1台に集約することで、誰がいつどのサーバーにアクセスしたかを管理できる
  • 攻撃面の縮小 — インターネットや社内ネットワークに直接晒すサーバーを踏み台1台に限定し、本番サーバーを外部から隠す
  • 監査ログの確保 — 踏み台を通過するすべての接続を記録し、セキュリティ監査に対応できる

検証環境に当てはめると、ホストPC → alma-main(踏み台)→ alma-sub(目的のサーバー)という経路になります。alma-sub は Internal Switch のみに接続されており、ホストPCから直接到達できない設計です。踏み台である alma-main を経由することで、アクセス経路を制御しつつ alma-sub に接続します。

多段SSH(ProxyJump)の経路。ホストPCはExternal Switch経由でalma-main(192.168.1.121)に接続できるが、alma-subのInternal IP(10.0.1.3)には直接アクセスさせない設計。ProxyJumpを使いalma-mainを踏み台として経由することで、アクセスを1点に集約し監査・制御する

ProxyJump の概念

SSH にはこのような多段接続を1コマンドで行う -J(ProxyJump)オプションがあります。ホストPCの PowerShell から実行する場合のコマンドは次のとおりです(概念説明のため、ここでは実行しません)。

ホストPCでの実行例(概念):

PS> ssh -J developer@192.168.1.121 developer@10.0.1.3

-J developer@192.168.1.121 が「alma-main を踏み台として経由する」という指定です。SSH クライアントが自動的に alma-main への接続を確立し、そこから alma-sub への接続をトンネリングします。

~/.ssh/config で設定を簡略化

毎回 -J オプションを入力するのは手間です。~/.ssh/config に設定を書いておくと、ホスト名だけで接続できるようになります。

まず alma-main の ~/.ssh/config に alma-sub への接続情報を登録します。alma-main で実行してください。

実行コマンド:

$ vi ~/.ssh/config

以下の内容を入力してください。

Host alma-sub-internal
    HostName 10.0.1.3
    User developer

各行の意味は以下のとおりです。

  • Host alma-sub-internal … この設定を呼び出すときの名前です。ssh コマンドの引数に使います
  • HostName 10.0.1.3 … 実際の接続先IPアドレスです
  • User developer … 接続時のユーザー名です

config ファイルのパーミッションを設定します。

実行コマンド:

$ chmod 600 ~/.ssh/config

設定した名前で接続できるか確認します。alma-main で実行してください。

実行コマンド:

$ ssh alma-sub-internal "hostname"

実行結果:

alma-sub

developer@10.0.1.3 と入力する代わりに alma-sub-internal だけで接続できるようになりました。管理するサーバーが増えるほど、この config ファイルの価値が高まります。

ホストPCからの ProxyJump 設定例

参考として、ホストPCの ~/.ssh/config に ProxyJump を設定する例を紹介します。この設定を書いておけば、ホストPCから ssh alma-sub-jump と入力するだけで alma-main 経由で alma-sub に接続できます。

Host alma-sub-jump
    HostName 10.0.1.3
    User developer
    ProxyJump developer@192.168.1.121

ProxyJump ディレクティブが「alma-main(192.168.1.121)を踏み台にする」という指定です。-J オプションと同じ動作を config ファイルに書いた形になります。

ssh_config の詳細なディレクティブを知りたい場合は man ssh_config を参照してください。

sshd 設定のハードニング

SSHサーバー(sshd)は、デフォルト設定のまま運用すると、パスワード総当たり攻撃の対象になるリスクがあります。ここでは sshd の設定を強化(ハードニング)して、攻撃への耐性を高める方法を学びます。

ハードニングで最も重要な鉄則があります。鍵認証でログインできることを確認してから、パスワード認証を無効にすることです。順序を間違えると、どこからもログインできなくなります。前のセクションで alma-main → alma-sub の鍵認証を設定済みですので、alma-sub の sshd を安全にハードニングできる状態です。

現在の設定を確認

まず sshd -T で現在の有効な設定値を確認します。alma-main で実行してください。

実行コマンド:

$ sudo sshd -T | grep -E "^(permitrootlogin|passwordauthentication|maxauthtries|pubkeyauthentication)"

実行結果:

maxauthtries 6
permitrootlogin without-password
pubkeyauthentication yes
passwordauthentication yes

各設定の意味は以下のとおりです。

  • maxauthtries 6 … 認証の最大試行回数。6回まで試せる
  • permitrootlogin without-password … root の鍵認証は許可するが、パスワード認証は拒否する
  • pubkeyauthentication yes … 公開鍵認証を許可する
  • passwordauthentication yes … パスワード認証を許可する(ここを no にしたい)

sshd -T(大文字の T)は、設定ファイルを読み込んだ後の実効値を一覧表示するコマンドです。sshd_config に書かれた値とデフォルト値が混在して表示されるため、「今どの設定が有効か」を正確に把握できます。

ハードニング設定の追加

AlmaLinux 9 の sshd は /etc/ssh/sshd_config.d/ ディレクトリ配下の .conf ファイルを自動で読み込みます。メインの設定ファイル(/etc/ssh/sshd_config)を直接編集するのではなく、専用ファイルを追加する方式が推奨されます。設定変更の追跡がしやすく、元に戻すときもファイルを削除するだけで済むためです。

alma-main で実行してください。

実行コマンド:

$ sudo vi /etc/ssh/sshd_config.d/99-hardening.conf

以下の内容を入力してください。

PermitRootLogin no
PasswordAuthentication no
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2

各設定の意味は以下のとおりです。

  • PermitRootLogin no … root での SSH ログインを完全に禁止する
  • PasswordAuthentication no … パスワード認証を無効にする。鍵認証のみ許可
  • MaxAuthTries 3 … 認証の最大試行回数を3回に制限する
  • ClientAliveInterval 300 … 300秒(5分)ごとにクライアントの生存確認を送る
  • ClientAliveCountMax 2 … 生存確認に2回連続で応答がなければ切断する

ファイル名の先頭に 99- を付けている理由は、sshd_config.d 内のファイルは名前順に読み込まれるためです。99 は最後に読み込まれるため、他の設定を上書きできます。

SSHポートの変更(22番から別のポートへ)はハードニングの一つとして紹介されることがありますが、ポート変更には SELinux の設定変更が必要です。第28回で SELinux を学んだ後であれば理解しやすいため、今回は扱いません。

構文チェックと反映

設定を反映する前に、構文チェックを行います。これは sshd 設定変更の鉄則です。構文エラーがあるまま再起動すると、sshd が起動しなくなり、SSH接続ができなくなるためです。

alma-main で実行してください。

実行コマンド:

$ sudo sshd -t

何も出力されなければ構文エラーはありません。エラーがある場合は行番号と内容が表示されるので、修正してから再度チェックしてください。

構文チェックが通ったら、sshd を再起動して設定を反映します。

実行コマンド:

$ sudo systemctl restart sshd

別セッションからの接続確認

第20回の firewalld で「設定変更後は別のターミナルから接続を試す。今のセッションは閉じない」という鉄則を学びました。sshd の設定変更でもこの鉄則は同じです。

今の SSH セッションは閉じずに、別のターミナルウィンドウを開いて alma-main に SSH 接続してみてください。鍵認証で接続できれば成功です。

設定が正しく反映されたか確認します。alma-main で実行してください。

実行コマンド:

$ sudo sshd -T | grep -E "^(permitrootlogin|passwordauthentication|maxauthtries|clientaliveinterval|clientalivecountmax)"

実行結果:

maxauthtries 3
clientaliveinterval 300
clientalivecountmax 2
permitrootlogin no
passwordauthentication no

すべての設定が反映されていることを確認できました。

鍵認証でリモートコマンドが正常に動作するかも確認します。alma-main で実行してください。

実行コマンド:

$ ssh alma-sub-internal "echo hardening test OK"

実行結果:

hardening test OK

先ほど ~/.ssh/config に登録した alma-sub-internal を使って、鍵認証で接続できています。

sshd_config の全ディレクティブを知りたい場合は man sshd_config を参照してください。

ヒヤリハット: パスワード認証を無効にしたらログインできなくなった

ある現場で、新しく構築したサーバーの sshd を「セキュリティ強化」として PasswordAuthentication no に変更しました。ところが、鍵認証の設定が完了していない状態で変更を反映してしまい、どこからも SSH ログインできなくなりました。

復旧にはサーバーのコンソール(仮想化ソフトのコンソール機能、データセンターであればリモートKVMやiLO/iDRAC)からログインして設定を戻す必要がありました。データセンターにあるサーバーの場合、現地に行くか遠隔のKVM装置を使わなければならず、大きな時間ロスになります。

教訓: 鍵認証での接続を確認してから、パスワード認証を無効にする。この順序を守る。

tmux によるセッション管理

SSH で作業中にネットワークが一瞬途切れた、あるいはノートPCの蓋を閉じてしまった、という経験はないでしょうか。通常の SSH セッションでは、接続が切れるとその時点で実行中のコマンドも終了します。長時間かかる dnf update やスクリプトの実行中にこれが起きると、作業が中途半端な状態になり、復旧に手間がかかります。

tmux(Terminal Multiplexer)を使えば、SSH 接続が切れてもサーバー上のセッション(作業環境)が残り続けます。再接続後にセッションに復帰すれば、切断前の状態からそのまま作業を続けられます。

tmux のインストール

tmux は AppStream リポジトリで提供されています。alma-main で実行してください。

実行コマンド:

$ sudo dnf install -y tmux

インストール後、バージョンを確認します。

実行コマンド:

$ tmux -V

実行結果:

tmux 3.2a

基本操作: セッションの作成・デタッチ・復帰・削除

tmux の基本は4つの操作です。

  1. セッション作成 … 名前を付けて作業環境を開始する
  2. デタッチ … セッションを残したまま抜ける(SSH が切れても残る)
  3. アタッチ(復帰) … セッションに戻る
  4. セッション削除 … 不要になったセッションを終了する

順番に試してみます。まず名前付きセッションを作成します。-d オプションを付けると、セッションをバックグラウンドで作成します。alma-main で実行してください。

実行コマンド:

$ tmux new-session -d -s work

セッションが作成されたか確認します。

実行コマンド:

$ tmux list-sessions

実行結果:

work: 1 windows (created Sat Apr  4 01:41:55 2026)

work という名前のセッションが1つ存在しています。このセッションにアタッチ(入る)します。

実行コマンド:

$ tmux attach -t work

画面の下部に緑色のステータスバーが表示されます。これが tmux セッションの中にいる目印です。

次にデタッチ(セッションを残して抜ける)を行います。キーボードで Ctrl+b を押してから d を押してください(同時押しではなく、Ctrl+b を押して離してから d を押します)。元のシェルに戻ります。

再度 tmux list-sessions を実行すると、work セッションがまだ存在していることを確認できます。SSH 接続が切れた場合でも、このセッションはサーバー上で動き続けます。

セッションが不要になったら削除します。

実行コマンド:

$ tmux kill-session -t work

削除されたか確認します。

実行コマンド:

$ tmux list-sessions

実行結果:

no server running on /tmp/tmux-1000/default

セッションがなくなったことを確認できました。

tmux の操作まとめ

操作コマンド / キー説明
セッション作成tmux new-session -s 名前名前付きセッションを作成して入る
セッション一覧tmux list-sessions存在するセッションの一覧を表示
デタッチCtrl+b dセッションを残して抜ける
アタッチ(復帰)tmux attach -t 名前セッションに戻る
セッション削除tmux kill-session -t 名前セッションを終了・削除する

tmux には他にもウィンドウ分割(Ctrl+b % で縦分割、Ctrl+b " で横分割)などの機能がありますが、まずは「セッション作成 → デタッチ → アタッチ」の3操作を覚えれば実務で十分に役立ちます。

なお、tmux と似たツールに screen があります。screen は歴史が長く、古いサーバーで見かけることがありますが、AlmaLinux 9 では tmux が AppStream で提供されており、新規に使い始めるなら tmux を選ぶのが一般的です。

tmux の詳細なオプションを知りたい場合は man tmux を参照してください。

やってみよう

今回の内容を定着させるために、2つの課題に取り組んでください。すべて alma-main で実行します。

課題1: 鍵認証でリモートコマンドを実行する

alma-main から alma-sub に鍵認証で SSH 接続し、hostnameuptime の2つのコマンドをリモート実行してください。

ヒント: ssh コマンドの後ろに実行したいコマンドを指定します。~/.ssh/config に登録した名前が使えます。

解答例:

$ ssh alma-sub-internal "hostname"
$ ssh alma-sub-internal "uptime"

パスワードを聞かれずに結果が返れば成功です。hostname は alma-sub が返り、uptime はサーバーの稼働時間が表示されます。

課題2: tmux セッションを操作する

以下の手順を順番に行ってください。

  1. 「practice」という名前の tmux セッションを作成して入る
  2. セッション内で echo "tmux is working" を実行する
  3. デタッチする(Ctrl+b d)
  4. tmux list-sessions でセッションが残っていることを確認する
  5. セッションに再接続する
  6. セッションを削除する
  7. セッション一覧で削除されたことを確認する

解答例:

$ tmux new-session -s practice
(セッション内で)
$ echo "tmux is working"
(Ctrl+b d でデタッチ)
$ tmux list-sessions
$ tmux attach -t practice
(再接続を確認したら Ctrl+b d でデタッチ)
$ tmux kill-session -t practice
$ tmux list-sessions

最後の tmux list-sessions で「no server running on …」と表示されればすべて完了です。

クリーンアップ

演習で変更した sshd の設定を元に戻します。alma-main で実行してください。

実行コマンド:

$ sudo rm /etc/ssh/sshd_config.d/99-hardening.conf

実行コマンド:

$ sudo systemctl restart sshd

デフォルトに戻ったことを確認します。

実行コマンド:

$ sudo sshd -T | grep -E "^(permitrootlogin|passwordauthentication)"

実行結果:

permitrootlogin without-password
passwordauthentication yes

デフォルトの設定に戻りました。

残っている tmux セッションがあれば削除してください。

実行コマンド:

$ tmux list-sessions

「no server running on …」と表示されればセッションは残っていません。セッション名が表示された場合は tmux kill-session -t セッション名 で削除してください。

SP6 スナップショットの取得

今回でフェーズ3「ネットワークとインフラ基盤」(第16回〜第27回)が完了しました。次回からのフェーズ4「サーバー構築と運用」の起点として、全VMのスナップショット(SP6_phase3-done)を取得してください。

スナップショットの取得前に、すべてのVMを停止します。ホストPCで実行してください。

ホストPCで実行(PowerShell の例):

PS> Stop-VM -Name 'alma-main' -Force
PS> Stop-VM -Name 'alma-sub' -Force
PS> Stop-VM -Name 'alma-proxy' -Force
PS> Checkpoint-VM -Name 'alma-main' -SnapshotName 'SP6_phase3-done'
PS> Checkpoint-VM -Name 'alma-sub' -SnapshotName 'SP6_phase3-done'
PS> Checkpoint-VM -Name 'alma-proxy' -SnapshotName 'SP6_phase3-done'
PS> Start-VM -Name 'alma-main'
PS> Start-VM -Name 'alma-sub'
PS> Start-VM -Name 'alma-proxy'

上記は Hyper-V の例です。VirtualBox や VMware など他の仮想化環境を使用している場合は、それぞれの方法でスナップショットを取得してください。名前は「SP6_phase3-done」としておくと、以降の回で参照しやすくなります。

まとめと次回予告

今回は SSH の応用として、VM間の鍵認証、ProxyJump による多段接続、sshd のハードニング、tmux によるセッション管理を学びました。

今回でフェーズ3「ネットワークとインフラ基盤」(全12回)が完了です。フェーズ3で学んだ内容を振り返ります。

  • 第16回 TCP/IP、サブネット、ポート、DNS解決の基礎
  • 第17回 nmcli によるIP設定と疎通確認の切り分け
  • 第18回 プロキシ・DNS・NTPのクライアント設定
  • 第19回 dnf によるパッケージ管理、EPEL、GPG鍵
  • 第20回 firewalld によるファイアウォール制御
  • 第21回第22回 ボンディング・VLAN(発展トピック)
  • 第23回 journalctl、rsyslog、logrotate によるログ管理
  • 第24回 cron / systemd timer による定期実行
  • 第25回 LVM によるストレージ管理
  • 第26回 シェルスクリプトによる運用自動化
  • 第27回(今回)SSH鍵認証、ProxyJump、sshdハードニング、tmux

これらの知識は、次のフェーズ4「サーバー構築と運用」のすべての回で活用します。

次回は第28回「SELinux」です。フェーズ4の最初の回として、SELinux の仕組みと基本操作(getenforce、semanage、restorecon)を学びます。「Enforcing のまま運用する」ことの意味と、SELinux が原因でサービスが動かない場合の切り分け方を身につけます。

理解度チェック

今回の内容を振り返り、○×で答えてください。

Q1. ssh-copy-id は接続先の ~/.ssh/authorized_keys に公開鍵を追記するコマンドである。

Q2. ProxyJump(-J オプション)は、踏み台サーバーを経由して目的のサーバーに接続する機能である。

Q3. sshd -t は sshd を再起動するコマンドである。

Q4. PasswordAuthentication no に変更した後は、パスワードでの SSH ログインができなくなる。

Q5. tmux でデタッチすると、セッション内で実行中のコマンドは終了する。

Q6. sshd の設定変更後は、現在のセッションを維持したまま別セッションで接続確認すべきである。

以下、解答です。

Q1. ○ — ssh-copy-id は公開鍵を読み取り、接続先の ~/.ssh/authorized_keys に追記します。ディレクトリの作成やパーミッションの設定も自動で行われます。

Q2. ○ — ProxyJump は踏み台サーバーへの SSH 接続を自動的に確立し、そこから目的サーバーへの接続をトンネリングします。~/.ssh/config に ProxyJump ディレクティブを書いておけば、毎回 -J オプションを指定する必要がなくなります。

Q3. × — sshd -t(小文字の t)は設定ファイルの構文チェックを行うコマンドです。再起動は systemctl restart sshd で行います。構文チェックは再起動前に必ず行う鉄則です。

Q4. ○ — パスワード認証が無効になるため、鍵認証が設定されていないユーザーはログインできなくなります。変更前に鍵認証での接続を必ず確認してください。

Q5. × — デタッチはセッションを残したまま抜ける操作です。セッション内で実行中のコマンドはそのまま動き続けます。これが tmux の最大の利点です。

Q6. ○ — 設定ミスでログインできなくなるリスクを避けるためです。既存セッションを閉じてしまうと、設定ミスがあった場合に復旧手段がなくなります。第20回の firewalld でも同じ鉄則を学びました。

シリーズ一覧

フェーズ1: エンジニアのいろは(第1回〜第3回)

フェーズ2: Linux基礎(第4回〜第15回)

フェーズ3: ネットワークとインフラ基盤(第16回〜第27回)

フェーズ4: サーバー構築と運用(第28回〜第36回)