SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor ・更新日 2026-09-04

SELinuxとfirewalldでSSHポートを変更する方法

Rocky LinuxやAlmaLinuxでSSHポートを変更する手順を解説します。firewalld、SELinuxのsemanage、sshd_configを正しい順序で設定し、接続を維持します。

SSH ポートの変更にここで 3 つの手順が必要な理由

Rocky Linux、AlmaLinux、CentOS Stream、または Fedora で SSH ポートを変更する場合、1 か所を編集するだけでは不十分です。新しいポートへの接続が機能するかどうかは、3 つの別々のシステムがそれぞれ判断します。firewalld はパケットをサーバーまで到達させるかどうかを判断します。SELinux は、sshd がそのポート番号にバインドすること自体を許可するかどうかを判断します。sshd_config は、デーモンが要求するポートを決定します。SELinux の手順を省くと、デーモンは起動を拒否します。firewalld の手順を省くと、デーモンは起動して待ち受けますが、誰も接続できません。

Ubuntu では、Ubuntu が SELinux ではなく AppArmor を使用し、sshd がバインドできるポートを制限するプロファイルを標準で提供していないため、同じ作業は 1 か所の編集と再起動だけで済みます。そこで ufw が動作している場合は、1 つのルールを追加します。違いはそれだけです。RHEL 系では、初期インストール時から firewalld が動作し、SELinux が enforcing になっており、どちらもポート番号を考慮します。

次の順序で作業すれば、すべての手順で現在のセッションを維持できます。

  1. firewalld で新しいポートを開き、現時点ではポート 22 を開いたままにします。
  2. semanage を使用して、新しいポートの SELinux ラベルを追加します。
  3. sshd の設定でポートを指定します。
  4. sshd を再起動し、最初のターミナルを閉じる前に、2 つ目のターミナルから新しいポートでログインします。
作業を始める前に、プロバイダーの Web コンソール(VNC またはシリアル)を見つけ、そこからログインできることを確認してください。変更に失敗した場合、そのコンソールが復旧経路になります。ポートの変更は、料金を支払ったばかりのサーバーからテナント自身を締め出す原因として、特に多いものの 1 つです。

まず semanage をインストールする

semanage は SELinux ポリシー設定を編集するツールです。Rocky Linux または AlmaLinux の最小構成インストールには含まれていません。policycoreutils-python-utils に含まれています。

sudo dnf install -y policycoreutils-python-utils

このパッケージをインストールする前にコマンドを実行すると、sudo: semanage: command not found が表示されます。この時点で、SELinux がインストールされていないと判断して手順を省略する読者が多くいます。SELinux はインストールされています。不足しているのは管理ツールだけです。dnf の構文に慣れていない場合は、dnf と apt のコマンド対応で、既知の操作との対応を確認できます。

ポートを選び、使用状況を確認する

1024 から 65535 までの空いている TCP ポートなら使用できます。ポートを決める前に、次の 2 点を確認します。

sudo ss -tlnp | grep -w 2222
sudo semanage port -l | grep -w 2222

1 つ目のコマンドで、その番号のポートをプロセスがすでに待ち受けているか確認します。2 つ目のコマンドで、SELinux ポリシーがそのポートを別のサービス種別に割り当てていないか確認します。空いているポートでは、どちらのコマンドも何も出力しません。ポリシーですでに割り当てられている場合、手順 2 の semanage port -a は ValueError: Port tcp/2222 already defined で失敗します。この場合は、別の番号を選びます。

このガイドでは、例として 2222 を一貫して使用します。ただし、スキャナーは 22 の次に最初に試すポートでもあるため、実際のサーバーでは、より推測されにくい番号を選んでください。

Step 1: firewalld でポートを開放する

sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports

--permanent はルールをディスク上のゾーンファイルに書き込みますが、実行中のファイアウォールには反映しません。--reload はディスク上の設定を実行中のファイアウォールに読み込みます。reload を省略すると、ルールは存在していても、次に firewalld が再起動するまで機能しません。このため、手順全体が理由なく失敗したように見えることがよくあります。

ここでは、ssh のサービスエントリはそのままにします。このエントリによってポート 22 が開いた状態に保たれ、テスト中のフォールバックになります。

プロバイダーのコントロールパネルも確認してください。多くのホストでは、OS の外側で VPS の前段にネットワークファイアウォールを配置しています。そのため、firewalld で開放したポートでも、上流で破棄される場合があります。VPS 向け firewalld 基礎ガイドでは、zones と runtime と permanent の違いを説明しています。この構成が初めての場合に参照してください。

手順 2: SELinux 用にポートへラベルを付ける

sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo semanage port -l | grep ssh_port_t

-a は新しいポート割り当てを追加します。-t ssh_port_t は SSH ポートに付与されるタイプです。2 つ目のコマンドは、現在 ssh_port_t が対象としているすべての内容を一覧表示します。デーモンを操作する前に、指定した番号が追加されたことを確認できます。

SELinux がポートをブロックする仕組み

SELinux(security-enhanced Linux)は、システム上のすべてのオブジェクトにラベルを付けます。TCP ポート番号も、ほかのオブジェクトと同様に扱われます。SSH デーモンは sshd_t というドメイン内で制限されて動作します。ポリシーでは、sshd_t が ssh_port_t とラベル付けされた TCP ポートを bind できます。初期状態でこのラベルが付いているポートは 22 だけです。デーモンに 2222 への bind を要求すると、カーネルはラベルを確認します。その番号に割り当てられた汎用タイプを検出し、ソケットでの name_bind 権限を拒否します。

このため、この失敗はファイアウォールの問題とは異なります。カーネルは listening socket が作成される前に拒否するため、sshd がエラーを報告して終了します。ファイアウォールの問題は逆です。デーモンは正常に動作しており、受信途中でパケットが破棄されます。

getenforce を使うと、システムがどのモードで動作しているか確認できます。Permissive では拒否が記録されますが、強制はされません。そのため、ポート変更はいったん機能しても、誰かが setenforce 1 を実行した日や、システムが enforcing モードで再起動したときに失敗します。どちらのモードでも、ポートにラベルを付けてください。サーバー向け SELinux の基本ガイドでは、モード、コンテキスト、boolean について詳しく説明しています。SELinux が影響するのはポートだけではありません。同じポリシーにより、パスのラベルを変更するまでコンテナが mount されたホストディレクトリを読み取れない場合もあります。そのため、Rocky Linux または AlmaLinux への Docker のインストールには SELinux の手順が含まれていますが、Ubuntu 向けガイドには通常この手順がありません。

Step 3: sshd の設定でポートを設定する

Rocky Linux 9 と 10、AlmaLinux 9 と 10、および現在の Fedora では、/etc/ssh/sshd_config は include 行から始まります。そのため、変更内容は drop-in ファイルに記述するのが適切です。これにより、パッケージ更新によって編集内容が上書きされることはありません。

grep -n '^Include' /etc/ssh/sshd_config
echo 'Port 2222' | sudo tee /etc/ssh/sshd_config.d/10-port.conf
sudo sshd -t

grep で Include 行が見つからない場合は、Rocky Linux 8 やその他の古いイメージが該当します。この場合は、Port 2222 を /etc/ssh/sshd_config に直接記述してください。sshd -t は drop-in を含む設定全体を解析し、構文エラーを報告します。再起動する前に、報告された内容をすべて修正してください。設定を解析できない場合、デーモンは再起動後に起動しません。

Port は複数回記述でき、sshd は指定されたすべてのポートで待ち受けます。最初の 1 日は、Port 2222 と併せて Port 22 を残しておくと、低コストの安全策になります。ただし、忘れずに削除してください。

sshd は socket unit によって起動されていますか?

一部のイメージでは、長時間稼働するサービスとしてではなく、systemd の socket activation を通じて SSH を起動します。この構成では、systemd が待ち受けソケットを管理し、接続を sshd に渡します。そのため、sshd_config 内の Port 行は完全に無視されます。何かを再起動する前に確認してください。

systemctl is-enabled sshd.socket

enabled の結果が表示される場合、ポートは sshd_config ではなく socket unit に設定されています。

sudo systemctl edit sshd.socket
[Socket]
ListenStream=
ListenStream=2222

空の ListenStream= は必須です。drop-in 全体で値が蓄積されるため、最初に空の割り当てでリストを消去しないと、ソケットは 2222 だけでなく 22 でも待ち受け続けます。sudo systemctl daemon-reload で適用し、その後 sudo systemctl restart sshd.socket を実行します。unit が無効になっているか、サーバーに存在しない場合、このセクションは該当しません。

手順 4: 再起動後、2 つ目のターミナルからテストする

sudo systemctl restart sshd
systemctl status sshd
sudo ss -tlnp | grep sshd

このターミナルは開いたままにします。ログアウトしないでください。自分のマシンで 2 つ目のターミナルを開き、新しいポートで接続します。

ssh -p 2222 youruser@203.0.113.10

2 つ目のログインが成功したことを確認してから、最初のセッションを閉じます。接続できなくても、すべてを元に戻せるシェルがまだ残っています。この習慣が、5 分で終わる変更と、プロバイダーのコンソールで午後いっぱい費やす作業の違いになります。

ファイアウォールによる drop か SELinux による拒否かを見分ける方法

ラップトップから見ると、2 つの障害はほぼ同じに見えます。サーバー上では、挙動がまったく異なります。

  • systemctl status sshd で unit が failed と表示される場合、daemon はソケットを取得できていません。設定エラーまたは SELinux による拒否です。
  • unit が active で、ss -tlnp に sshd が新しいポートで bind していると表示される場合、daemon に問題はありません。問題はネットワーク経路にあります。firewalld、プロバイダー側の独立したファイアウォール、または接続先に指定したアドレスとポートを確認します。

SELinux が原因の場合は、推測せずに audit レコードを確認します。

sudo ausearch -m AVC -ts recent
sudo journalctl -u sshd -n 50 --no-pager

class tcp_socket に対する name_bind の拒否には、プロセスが comm="sshd"、ポート番号が src=、そのポートに実際に付与されているラベルが tcontext= として記録されます。最後のフィールドが答えです。ssh_port_t 以外の値であれば、使用しているポートに手順 2 が適用されていません。通常は、ポート番号の入力ミスまたはプロトコルの誤りです。レコードを文章に変換して sealert に表示させたい場合は、setroubleshoot-server をインストールします。

カーネルが bind を拒否したときに sshd 自身が出力するメッセージは、次のようになります。

error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.

1024 より大きいポートでは bind に root 権限が不要です。そのポートでの Permission denied は、SELinux による拒否を示します。同じ行にある Address already in use は別の障害を示します。別のプロセスがそのポートを使用しています。クライアント側では、connection refused と connection timed out の違いによって、2 つのネットワーク障害を区別できます。connection refused はパケットがホストに到達し、待ち受けているプロセスがなかったことを意味します。一方、connection timed out は何も応答しなかったことを意味します。

ポート 22 を閉じ、クライアントを更新する

新しいポートでのログインが複数回成功したら、22 番ポートを削除します。

sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

ポート 22 の SELinux ラベルは変更しないでください。これはベースポリシーに由来するため、ファイアウォールがパケットの受信を停止すれば、権限を与えることはありません。

次にクライアントを修正します。デフォルトポートを前提としていたすべてのツールに、新しいポートを指定する必要があるためです。自分のマシンの ~/.ssh/config に一度設定すれば、毎回 -p を入力せずに済みます。

Host myvps
  HostName 203.0.113.10
  Port 2222
  User youruser

scp、sftp、rsync、Ansible はすべてこのファイルを読み込みます。ポート 22 をハードコードしたバックアップジョブ、監視チェック、cron スクリプトはこのファイルを読み込まないため、変更内容を把握しているうちに洗い出してください。

ポート変更で得られるものと得られないもの

ログのノイズを減らせます。自動スキャナーは常に port 22 を大量にスキャンしています。別の port に変更すると、journal に記録されるその種の行の大半がなくなり、実際のイベントを確認しやすくなります。ただし、これはセキュリティ対策ではありません。全 port 範囲をスキャンするスキャナーなら、sshd を見つけてバージョンバナーも読み取れます。ポート変更は整理のための作業と考え、実際の防御は、パスワードログインを無効にした鍵のみの認証で実施してください。手順は VPS 向け SSH 強化ガイドで順を追って説明しています。

上記の手順は、主要な RHEL 再構築版のどちらでも同じように機能します。どちらも同じソースからビルドされているためです。どちらを選ぶかまだ決めていない場合は、Rocky Linux と AlmaLinux の比較を参照してください。似た再構築版が2つあるのは、CentOS が 2020 年にその役割を終えたためです。その経緯は、Red Hat から CentOS、Rocky、AlmaLinux への変遷で詳しく説明しています。古いガイドに従う前に、cat /etc/os-release で実際に提供された release を確認してください。Rocky Linux 8 向けに書かれたガイドは現在も検索順位が高く、semanage と firewall-cmd の手順も正しいままです。ただし、Rocky 8 には sshd_config.d の include 行も、確認すべき socket unit もありません。そのため、これらのガイドにある sshd の手順は、現在のサーバーには適合しません。

fail2ban に新しいポートを知らせる

fail2ban は標準リポジトリには含まれていません。EPEL(Enterprise Linux 用の追加パッケージ)からインストールします。

sudo dnf install -y epel-release
sudo dnf install -y fail2ban fail2ban-firewalld

fail2ban-firewalld サブパッケージを使うと、fail2ban は firewalld 経由で ban を適用します。firewalld がルールセットを管理するサーバーでは、この構成を使用します。

標準の sshd jail では port = ssh が設定されています。この名前は /etc/services によって 22 に解決されます。ポートを変更すると、jail は誰も攻撃していないポートを監視するため、ログイン失敗が 2222 に蓄積しても誰も ban しません。/etc/fail2ban/jail.local でポート番号を設定します。

[sshd]
enabled = true
port = 2222
backend = systemd
maxretry = 5
bantime = 3600

backend = systemd は /var/log/secure ではなく journal から失敗を読み取ります。最小構成のインストールでは rsyslog が存在しない場合があるため、こちらの方が安全です。sudo systemctl enable --now fail2ban で起動し、sudo fail2ban-client status sshd で jail を確認します。jail の構文は、Ubuntu 24.04 での SSH 用 fail2ban 設定と同じです。異なるのは、パッケージの入手元と ban action だけです。

パッチ適用はポート変更より重要

SSH ポートを変更していても、4 か月間セキュリティ更新を適用していないサーバーは、毎晩自動でパッチを適用する port 22 のサーバーより危険な状態です。すでに root で作業している間に、同じセッションで自動更新も有効にします。Rocky Linux と AlmaLinux での dnf 自動更新では、タイマーの設定と、更新をダウンロードするだけにするか適用まで行うかの選択を説明しています。更新をインストールしても、古いコードで実行中のデーモンは再起動されません。そのため、openssh-server またはそれがリンクしているライブラリが更新対象になった場合は、再起動またはリブートが必要なものの確認に 1 分かける価値があります。

FAQ

Rocky Linux でポートを変更した後、sshd の起動に失敗するのはなぜですか?

ほとんどの場合、SELinux のポートラベルが不足しています。sshd は sshd_t ドメインで制限付きで動作し、ポリシーでは ssh_port_t のラベルが付いたポートへのバインドだけが許可されています。デフォルトでは、これはポート 22 だけです。カーネルがバインドを拒否するため、デーモンは待ち受けを開始せずに終了します。journalctl -u sshd には、error: Bind to port 2222 on 0.0.0.0 failed: Permission denied. の形式の行が含まれています。独自のポート番号を指定して sudo semanage port -a -t ssh_port_t -p tcp 2222 を実行し、その後サービスを再起動してください。semanage が見つからない場合は、先に policycoreutils-python-utils をインストールしてください。

SELinux が permissive モードでも semanage は必要ですか?

はい。permissive モードでは拒否が記録されますが、バインド自体は許可されるため、変更が成功したように見えます。ポートラベルは不足したままです。誰かが setenforce 1 を実行した場合や、/etc/selinux/config に SELINUX=enforcing を指定してシステムを起動した場合、その時点で sshd はそのポートで起動しなくなります。ラベルの追加は 1 コマンドで済みます。追加しておけば、明確な原因が分からないまま数週間後に発生する障害を防げます。

ポートにはラベルが付いていて sshd も実行中なのに、接続がタイムアウトするのはなぜですか?

デーモンが実行中なら、SELinux は問題ありません。したがって、パケットは受信経路の途中で破棄されています。sudo firewall-cmd --list-ports で使用するポートを確認してください。また、--permanent ルールの後に firewall-cmd --reload を実行したことも確認してください。永続ルールを追加しただけでは、実行中のファイアウォールには反映されません。次に、VPS の前段に別のネットワークファイアウォールがないか、ホストのコントロールパネルで確認します。ここが 2 つ目の遮断箇所です。オペレーティングシステム内の設定やログには何も表示されません。

22 の代わりにどのポートを使用すべきですか?

1024 から 65535 までの、空いている TCP ポートを使用できます。実運用サーバーでは 2222 と 22222 は避けてください。スキャナーは 22 の直後にこれらのポートも試すためです。sudo ss -tlnp で番号が空いていることを確認し、sudo semanage port -l で SELinux ポリシーがその番号をすでに使用していないことを確認してください。また、後でインストールする可能性があるサービスに割り当てられたポートは避けます。覚えにくい大きな番号でも問題ありません。~/.ssh/config に 1 回記述すれば、その後入力する必要はないためです。