SSH接続拒否エラーを素早く修正する方法

sshdの状態、ポート、ファイアウォールルール、sshd_config、SELinux、サーバーログを確認して、SSH接続拒否エラーを修正します。

SSH接続拒否エラーを素早く修正する方法

SSH(Secure Shell)はリモートサーバー管理の基盤であり、ローカルマシンとリモートサーバー間の安全で暗号化された通信を可能にします。しかし、ssh: connect to host <IP_ADDRESS> port 22: Connection refused というエラーに遭遇すると、重要なシステムにアクセスできなくなる厄介な障害となります。

この記事では、一般的な「接続拒否」エラーを診断し解決するための包括的なステップバイステップガイドを提供します。非アクティブなSSHデーモンから誤設定されたファイアウォールやサーバー設定まで、主な原因を探り、サーバーへのアクセスを迅速に回復するための知識とコマンドを身につけます。

「接続拒否」エラーの理解

Connection refused エラーを受け取ると、SSHクライアントがリモートサーバーに正常に到達したものの、サーバーが指定されたポートでの接続を明示的に拒否したことを意味します。これは、クライアントがサーバーにまったく到達できない Connection timed out エラーや、ネットワークパスが壊れている No route to host エラーとは異なります。

「拒否」ステータスは、SSHサービスが接続を受け入れないように積極的に妨げている サーバー側 の問題を直接示しています。これは通常、SSHデーモンが実行されていない、ファイアウォールが接続をブロックしている、またはSSHサービス自体の設定ミスが原因です。

「接続拒否」の一般的な原因

いくつかの要因がSSH接続の拒否につながる可能性があります。これらを理解することで、トラブルシューティングのプロセスを絞り込むのに役立ちます。

  • SSHデーモン(sshd)が実行されていない: 最も一般的な原因です。SSHサーバープロセスがクラッシュしたり、停止されたり、起動時に起動に失敗した可能性があります。
  • ファイアウォールがポート22(またはカスタムポート)をブロックしている: サーバーのファイアウォール(例:UFW、firewalld、iptables)がSSHポートへの着信接続を妨害しています。
  • SSHデーモンの設定が正しくない: sshd_config ファイルが誤って設定され、SSHデーモンが異なるポートや間違ったネットワークインターフェースでリッスンしたり、特定のユーザーやメソッドの接続を拒否したりする可能性があります。
  • ネットワーク接続の問題(「拒否」ではあまり一般的ではない): 「拒否」エラーの可能性は低いですが、基本的なネットワークの問題が予期せず発生することがあります。
  • SELinuxまたはAppArmorの制限: SELinuxやAppArmorなどのセキュリティ強化機能が、特にカスタム設定やシステム変更後に、sshd の正しい動作を妨げている可能性があります。

ステップバイステップのトラブルシューティングガイド

「接続拒否」エラーを診断して修正するための実践的な手順を見ていきましょう。

ステップ1:サーバー上のSSHデーモンの状態を確認する

最初に確認するのは、リモートマシンでSSHサーバーデーモン(sshd)が実際に実行されているかどうかです。SSHが完全にアクセスできない場合、これらのチェックを実行するには通常、コンソールアクセス(例:クラウドプロバイダーのコンソールや物理接続経由)が必要です。

  1. SSHデーモンの状態を確認する: 最新のほとんどのLinuxディストリビューション(Ubuntu、CentOS 7+、Debian 8+などの systemd を使用するもの):
    sudo systemctl status sshd
    

Debian/Ubuntuでは、サービス名が ssh の場合があります:

sudo systemctl status ssh ``` sshd が実行されていない場合、出力は inactive (dead) または同様のステータスを示します。

  1. SSHデーモンを起動する: ステータスが非アクティブの場合は、サービスの起動を試みます:
    sudo systemctl start sshd
    

または Debian/Ubuntu:

sudo systemctl start ssh ```

  1. SSHデーモンを起動時に有効にする: 再起動後にSSHが自動的に起動するようにするには、有効にします:
    sudo systemctl enable sshd
    

または Debian/Ubuntu:

sudo systemctl enable ssh ```

  1. SSHデーモンのログを確認する: sshd の起動に失敗した場合、そのログが重要な手がかりを提供します。systemd システムの場合:
    sudo journalctl -u sshd --since "10 minutes ago"
    

または、ディストリビューションが ssh ユニットを使用している場合:

sudo journalctl -u ssh --since "10 minutes ago" または、一般的な認証ログを確認します: bash sudo tail -f /var/log/auth.log # RHEL/CentOSの場合: sudo tail -f /var/log/secure ```

ステップ2:ファイアウォールルールを確認する

サーバー側のファイアウォールが接続拒否の原因であることがよくあります。デフォルトのSSHポート(22)や使用しようとしているカスタムポートをブロックしている可能性があります。ファイアウォールがSSHポートへの着信接続を許可していることを確認する必要があります。

  1. ファイアウォールを特定する: 一般的なファイアウォールには以下が含まれます:

    • UFW(Uncomplicated Firewall): Ubuntu/Debianで一般的。
    • firewalld: CentOS/RHEL 7+で一般的。
    • iptables: Linuxの基盤となるファイアウォールで、直接またはフロントエンドを介して設定されます。
  2. ファイアウォールのステータスとルールを確認する:

    • UFW:
      sudo ufw status verbose
      
      port 22(またはカスタムSSHポート)へのトラフィックを許可するルールを探します。SSHがリストされている場合は、ALLOW されていることを確認します。
    • firewalld:
      sudo firewall-cmd --list-all
      
      services セクションと ports セクションで ssh または port 22/tcp を確認します。
    • iptables:
      sudo iptables -L -v -n
      
      この出力は複雑になる可能性があります。INPUT チェーンで tcp dpt:22(またはカスタムポート)に関連する DROP または REJECT ルールを探します。
  3. ファイアウォールでSSHポートを許可する:

    • UFW:
      sudo ufw allow ssh        # ポート22を許可
      # または、カスタムポート(例:2222)の場合:
      sudo ufw allow 2222/tcp
      sudo ufw enable           # UFWが非アクティブの場合
      
    • firewalld:
      sudo firewall-cmd --permanent --add-service=ssh
      # または、カスタムポート(例:2222)の場合:
      sudo firewall-cmd --permanent --add-port=2222/tcp
      sudo firewall-cmd --reload
      
    • iptables: iptables ルールを直接追加するのはより複雑で、保存しない限り一時的です。利用可能な場合は firewalld または ufw を使用することをお勧めします。簡単なテスト(永続的ではない)の場合:
      sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
      sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
      # 再起動後もルールを維持するには、これらのルールを保存する必要があります。
      

    警告: 特にリモートサーバーにSSH接続しているときにファイアウォールルールを変更する場合は注意してください。誤ったルールは永続的にロックアウトする可能性があります。現在のSSHセッションを閉じる前に、変更が機能することを常に確認してください(開いているセッションがある場合)。

ステップ3:SSH設定(sshd_config)を確認する

SSHデーモンの設定ファイル(/etc/ssh/sshd_config)は、サービスの動作方法を決定します。ここでの設定ミスは接続拒否につながる可能性があります。

  1. sshd_config を見つける: 主要な設定ファイルは通常 /etc/ssh/sshd_config にあります。

  2. 主要な設定を検査する: テキストエディタ(例:nanovi)でファイルを開きます:

    sudo nano /etc/ssh/sshd_config
    

    次のディレクティブを探します:

    • Port: sshd がリッスンするポートを指定します。クライアントから接続しようとしているポートと一致していることを確認します。コメントアウトされている場合(#)、デフォルトのポート22になります。
    • ListenAddress: 存在する場合、sshd がリッスンするIPアドレスを指定します。内部IP(例:127.0.0.1)に設定されていて、外部ネットワークから接続している場合、接続を拒否します。すべてのインターフェースでリッスンするには、通常コメントアウトされるか、0.0.0.0 または ::(IPv6用)に設定されます。
    • PermitRootLogin: no に設定されている場合、rootとしてログインできません。厳密には「接続拒否」ではありません(多くの場合、接続の権限拒否です)が、ログイン試行を妨げる可能性があります。
    • PasswordAuthentication: no に設定されている場合、パスワード認証が無効になり、キーベースの認証が必要になります。

    ヒント: sshd_config を変更した後は、変更を有効にするためにSSHサービスを再起動する必要があります:

    sudo systemctl restart sshd
    

ステップ4:ネットワーク接続(基本チェック)

「接続拒否」は通常サーバーに到達したことを意味しますが、クライアントマシンからサーバーのIPアドレスへの基本的なネットワーク到達可能性をすばやく確認することをお勧めします。

  1. サーバーにpingを実行する: クライアントマシンから、サーバーのIPアドレスまたはホスト名にpingを試みます:

    ping <SERVER_IP_ADDRESS_OR_HOSTNAME>
    

    pingが失敗した場合(100%パケットロス)、SSHの前に解決する必要があるより基本的なネットワーク問題(例:誤ったIP、サーバーオフライン、ネットワークルーティングの問題)があります。

  2. nc または telnet を使用する(クライアントから): クライアントの観点からポートが開いていてリッスンしているかをテストするには:

    # netcat (nc) を使用
    nc -zv <SERVER_IP_ADDRESS> 22
    
    # telnet を使用
    telnet <SERVER_IP_ADDRESS> 22
    

    ncConnection refused を表示するか、telnet がすぐに終了する場合、サーバーがそのポートで積極的に拒否していることを確認し、SSHデーモンまたはファイアウォールに問題があることを示しています。

ステップ5:SELinuxまたはAppArmorを確認する(上級者向け)

一部の強化された環境や、カスタム設定後には、SELinux(Security-Enhanced Linux)またはAppArmorが sshd の正しい動作を妨げている可能性があります。特に非標準のSSHポートを使用している場合に顕著です。

  1. SELinuxのステータスを確認する:

    sestatus
    

    SELinuxが enforcing の場合、カスタムポートで sshd を許可するためにポリシーを調整する必要があるかもしれません。 例えば、SSH用にポート2222を許可するには:

    sudo semanage port -a -t ssh_port_t -p tcp 2222
    sudo systemctl restart sshd
    

    semanage が利用できない場合はインストール: Debian/Ubuntuでは sudo apt install policycoreutils-python-utils、RHEL系リリースでは sudo yum install policycoreutils-python-utils または対応するパッケージ)。

  2. AppArmorのステータスを確認する:

    sudo aa status
    

    AppArmorが enforcing の場合、sshd に関連する拒否がないかログ(/var/log/syslog または dmesg)を確認します。

ステップ6:サーバーログを再度確認する

前の手順を試した後は、sshd に関連する新しいエラーメッセージがないか、常にサーバーのログを再確認してください。これはサーバーが何を経験しているかについての究極の情報源です。

  • sudo journalctl -u sshd
  • sudo tail -f /var/log/auth.log(または /var/log/secure

サービスが起動しない理由、接続が切断されている理由、またはその他の関連情報を示すメッセージを探します。

将来の問題を防ぐためのベストプラクティス

  • OSを定期的に更新する: サーバーのオペレーティングシステムと openssh-server を含むパッケージを最新の状態に保ちます。
  • ファイアウォールルールをテストする: ファイアウォールルールを実装または変更した後は、すぐにテストします。
  • sshd_config をバックアップする: /etc/ssh/sshd_config を変更する前に、バックアップを作成します(sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak)。
  • 管理コンソールを使用する: クラウドインスタンスの場合、SSHが利用できないときにネットワーク問題をトラブルシューティングするために、サーバーのコンソール(例:AWS EC2シリアルコンソール、Google Cloud Console)にアクセスする方法を知っておきます。
  • ログを監視する: 異常なアクティビティや永続的なエラーがないか、定期的に auth.log または secure ログを確認します。

最終的な要点

SSH接続拒否エラーは通常、サーバーに到達可能であるが、そのポートで接続を受け入れているものがないことを意味します。ディストリビューションのSSHサービス名を確認し、ポートがリッスンしていることを確認し、ファイアウォールを開放し、sshd_config を検証し、大きな変更を行う前にログを読みます。まだ機能しているセッションが開いている場合は、新しいログインが成功するまで開いたままにしておきます。