「OpenSSH」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(→‎設定: 修正)
(→‎参照: 同期)
662行目: 662行目:
   
 
== 参照 ==
 
== 参照 ==
  +
*[http://www.la-samhna.de/library/brutessh.html Defending against brute force ssh attacks]
 
  +
* [https://www.la-samhna.de/library/brutessh.html Defending against brute force ssh attacks]
*IBM developerWorks の [https://www.ibm.com/developerworks/jp/linux/library/l-keyc/ OpenSSH キー (鍵) の管理: 第 1 回] と [https://www.ibm.com/developerworks/jp/linux/library/l-keyc2/ 第 2 回]
 
  +
* OpenSSH 鍵管理: IBM developerWorks の [https://www.ibm.com/developerworks/library/l-keyc/index.html Part 1]、funtoo.org の [[Funtoo:OpenSSH Key Management, Part 2|Part 2]]、[[Funtoo:OpenSSH Key Management, Part 3|Part 3]]
 
* [https://stribika.github.io/2015/01/04/secure-secure-shell.html Secure Secure Shell]
 
* [https://stribika.github.io/2015/01/04/secure-secure-shell.html Secure Secure Shell]

2023年4月25日 (火) 08:05時点における版

この記事あるいはセクションは翻訳の途中です。
ノート: 飜訳および編集が必要です。英語版を参照してください。 (議論: トーク:OpenSSH#)

関連記事

OpenSSH (OpenBSD Secure Shell) は、Secure Shell (SSH) プロトコルを用いてコンピュータネットワーク経由の暗号化された通信セッションを提供するコンピュータプログラム群です。OpenSSH は、SSH Communications Security によって提供されているプロプライエタリな Secure Shell ソフトウェアスイートのオープンソースな代替として作成されました。OpenSSH は OpenBSD プロジェクトの一部として開発されており、Theo de Raadt によって率いられています。

OpenSSH は、似た名前の OpenSSL と混同されることがあります。しかし、これらのプロジェクトの目的は異なり、開発チームも異なります。この似たような名前は、ただ単にゴールが似ているからです。

目次

インストール

openssh パッケージをインストールしてください。

クライアントの使用

サーバに接続するには、以下を実行してください:

$ ssh -p ポート ユーザ@サーバアドレス

サーバが公開鍵認証のみを許可している場合、SSH 鍵 の記事に従ってください。

設定

クライアントは、共通のオプションとホストを保存するように設定することができます。全プションは、グローバルに、あるいは特定のホストに制限して宣言することができます。例えば:

~/.ssh/config
# グローバルなオプション
User user

# 特定のホストのオプション
Host myserver
    Hostname server-address
    Port     port

このような設定を用いると、以下の2つのコマンドは等価になります:

$ ssh -p port user@server-address
$ ssh myserver

詳細は ssh_config(5) を見てください。

一部のオプションには等価なコマンドラインスイッチがありません。しかし、コマンドラインで -o フラグを用いることで設定オプションを指定できます。例えば: -oKexAlgorithms=+diffie-hellman-group1-sha1

サーバの使用

sshd は OpenSSH サーバのデーモンです。/etc/ssh/sshd_config で設定され、sshd.service によって管理されます。設定を変更する際は、サーバを再起動する前に sshd をテストモードで使用し、サーバが正しく起動できることを確認してください。設定が有効である場合は、何も出力されません。

# sshd -t

設定

一部のユーザにのみアクセスを許可するには、以下の行を追加してください:

AllowUsers    user1 user2

一部のグループにのみアクセスを許可するには:

AllowGroups   group1 group2

素晴らしいウェルカムメッセージを (/etc/issue ファイルなどから) 追加するには、Banner オプションを設定してください:

Banner /etc/issue

公開ホスト鍵と秘密ホスト鍵は、sshdgenkeys サービスによって /etc/ssh 内に自動で生成されます。sshd_config 内の HostKeyAlgorithms オプションによって一部の署名アルゴリズムしか許可されていない場合でも、鍵が存在しない場合、再生成されます。dsa、rsa、ecdsa、そして ed25519 アルゴリズムに基づく4組の鍵のペアが提供されます。sshd に特定の鍵を使用させるには、以下のオプションを指定してください:

HostKey /etc/ssh/ssh_host_rsa_key

サーバを WAN に公開するつもりであるならば、以下のようにデフォルトのポートを 22 から別のランダムで大きい値に変更することが推奨されます:

Port 39901
ヒント:
  • 一般的なサービスにまだ割り当てられていない代替ポートを探すには、TCP と UDP のポート番号一覧を見てください。また、/etc/services にあるローカルのポート番号情報を見ることもできます。デフォルトのポート 22 番からポートを変更すると、自動化された認証試行によるログエントリ数が減るでしょう。しかし、そのような攻撃を排除することはできません。関連する情報は ポートノッキング を参照してください。
  • パスワードログインを完全に無効化することが推奨されます。そうすることで、セキュリティが格段に向上します。詳細は #公開鍵認証を強制する を参照してください。他の推奨されるセキュリティ手法については #保護 を参照してください。
  • 設定ファイル内に複数の Port port_number 行を記述することにより、OpenSSH に複数のポートをリッスンさせることができます。
  • 新しい (或いは存在しない) ホスト鍵ペアは、置き換えたいペアを /etc/ssh から削除し ssh-keygen -A を root として実行することで、生成することができます。

デーモンの管理

sshd.service起動/有効化してください。これは、SSH デーモンを永続的にアクティブ状態に保ち、各着信接続に対してフォークします。[1]

ノート: Systemd のソケットアクティベーションを使用する sshd.socket は、DOS (サービス拒否) の影響を受けやすいため、openssh 8.0p1-3 で削除されました。詳細は FS#62248 を参照してください。openssh 8.0p1-3 に更新する時に sshd.socket が有効化されていた場合、sshd.socketsshd@.service ユニットは /etc/systemd/system/ にコピーされ、再有効化されます。これは、既存のセットアップを破壊しないためだけに行われるのであって、ユーザは依然として sshd.service に移行することが推奨されます。
警告: sshd.socket の使用を継続するならば、このユニットの問題に注意してください:
  • sshd.socket ユニットは (例えばメモリ不足の状況などにより) 失敗する場合があり、Restart=always はソケットユニットに対しては指定できません。systemd issue 11553 を参照。
  • ソケットアクティベーションの使用は、接続が多すぎるとサービスのアクティブ化が拒否される可能性があるため、サービス拒否を引き起こす可能性があります。FS#62248 を参照。
ノート: sshd.socket を使用すると ListenAddress の設定が無効化され、任意のアドレスを介して接続できるようになってしまいます。ListenAddress の設定に効力を持たせるには、sshd.socket編集して、ポートと IP の両方ListenStream で設定しなければなりません (例: ListenStream=192.168.1.100:22)。また、[Socket] セクションに FreeBind=true も追加しなければなりません。さもないと、IP アドレスを設定した時に ListenAddress を指定した時と同じ欠点が生じます: ネットワークが時間内に立ち上がっていない場合、ソケットは起動に失敗します。
ヒント: ソケットアクティベーションを使用すると、各接続に対して sshd@.service の一時的なインスタンスが (異なるインスタンス名で) 開始されます。ゆえに、sshd.socket もデーモンの通常の sshd.service も、接続試行をログでモニタできません。ソケットアクティベートされた SSH インスタンスのログは、journalctl -u "sshd@*" を root として実行するか、journalctl /usr/bin/sshd を root として実行することで、確認することができます。

保護

SSH によるリモートログインを許可することは管理業務においては良いことですが、サーバーのセキュリティに脅威を及ぼすことにもなりえます。総当り攻撃の標的になりやすいので、SSH のアクセスは制限して、第三者がサーバーにアクセスできないようにする必要があります。

ssh-audit は、サーバとクライアントの設定の自動化された解析を提供します。このトピックに関して、いくつか他のガイドやツールが利用できます。例えば:

公開鍵認証を強制する

デフォルトでは、クライアントが公開鍵で認証できない場合、SSH サーバはパスワード認証にフォールバックします。なので、悪意のあるユーザがパスワードのブルートフォースによるアクセスを試みることができてしまいます。このような攻撃から保護する最も効果的な方法の1つが、パスワードログインを完全に無効化し、SSH 鍵の使用を強制することです。これは、デーモンの設定ファイルで以下のオプションを設定することで可能です:

/etc/ssh/sshd_config
PasswordAuthentication no
AuthenticationMethods publickey
警告: これを設定に追加する前に、SSH アクセスを必要とする全アカウントが、対応する authorized_keys ファイルで公開鍵認証をセットアップしていることを確認してください。詳細は SSH 鍵#リモートサーバーに公開鍵をコピー を参照してください。

二要素認証と公開鍵

SSH は、認証に複数の方法を要求するようにセットアップすることができます。AuthenticationMethods オプションを使うことで、どの認証方法を要求するかを指定することができます。これにより、公開鍵と2要素認証を使用することができます。

認証プロバイダ

Google Authenticator をセットアップする方法については Google Authenticator を参照してください。

Duo の場合、pam_duo.so モジュールを提供する duo_unixAURインストールしてください。必須の Duo 認証情報 (Integration Key、Secret Key、API Hostname) をセットアップする方法に関するインストラクションは Duo Unix ドキュメント を参照してください。

PAM セットアップ

PAM を OpenSSH で使用するには、以下のファイルを編集してください:

/etc/ssh/sshd_config
KbdInteractiveAuthentication yes
AuthenticationMethods publickey keyboard-interactive:pam

これで、PAM セットアップによって要求されるユーザ認証か公開鍵のどちらか一方でログインできます。

一方、PAM セットアップによって要求されるユーザ認証と公開鍵の両方でユーザを認証したい場合、AuthenticationMethods の分割にスペースではなくコンマを使用してください:

/etc/ssh/sshd_config
KbdInteractiveAuthentication yes
AuthenticationMethods publickey,keyboard-interactive:pam

要求される公開鍵と pam 認証の両方を用いて、パスワード要件を無効化すると良いでしょう:

/etc/pam.d/sshd
auth      required  pam_securetty.so     #disable remote root
#Require google authenticator
auth      required  pam_google_authenticator.so
#But not password
#auth      include   system-remote-login
account   include   system-remote-login
password  include   system-remote-login
session   include   system-remote-login

ブルートフォース攻撃に対する保護

ブルートフォース (総当り) は単純なコンセプトです: 大量のランダムなユーザ名とパスワードの組み合わせを用いて、あるウェブページやサーバの SSH のようなログインプロンプトに絶え間なくログインを試みるのです。

iptables については ufw#ufw によるレート制限シンプルなステートフルファイアウォール#ブルートフォース攻撃 を参照してください。

あるいは、fail2bansshguard などの自動スクリプトを使うことで攻撃者をブロックすることでブルートフォース攻撃から身を守ることができます。

  • 信頼された場所からの着信 SSH 接続のみを許可する。
  • fail2bansshguard を使用して、パスワード認証に失敗しすぎた IP アドレスを自動的にブロックする。
  • pam_shield を使用して、特定の時間内に多くのログイン試行を行った IP アドレスをブロックする。fail2bansshguard とは対照的に、このプログラムはアカウントへのログイン成功や失敗を考慮しません。

root ログインの制限

この記事またはセクションは情報が古くなっています。
理由: 現在のバージョンでは、root ログインは上流でデフォルトで無効化されています。 (Discuss)

一般的に、root ユーザが制限無しで SSH を介してログインできることはバッドプラクティスだと考えられています。セキュリティを向上させるために SSH の root アクセスを制限する方法は2つあります。

拒否

Sudo を使うことで、root アカウントの認証を行うことなく、必要に応じて root 権限を選択的に付与することができます。このため SSH による root ログインを拒否して、攻撃者にパスワードに加えて (root でない) ユーザー名も推測させる必要を生じさせることで、ブルートフォース攻撃を困難にすることが可能です。

デーモンの設定ファイルで "Authentication" セクションを編集することで SSH からの root ユーザのログインを拒否するように設定できます。PermitRootLoginno に設定してください:

/etc/ssh/sshd_config
PermitRootLogin no

次に、SSH デーモンを再起動してください。

これで、SSH を使って root でログインすることはできなくなります。ただし、通常ユーザーでログインしてから susudo を使ってシステム管理を行うことは依然として可能です。

制限

自動的な作業の中にも、リモートによるフルシステムバックアップなど、root 権限を必要とするものがあります。セキュアな方法で root を許可したい場合、SSH による root ログインを無効化する代わりに、特定のコマンドだけ root ログインを許可することができます。~root/.ssh/authorized_keys を編集して、以下のように特定のキーの前にコマンドを記述します:

command="/usr/lib/rsync/rrsync -ro /" ssh-rsa …

上記の設定で、特定の鍵を使ってログインした場合はクォートで囲ったコマンドを実行できるようになります。

ログイン時に root ユーザーの名前を出すことで攻撃する対象が増えてしまうことに対しては sshd_config に以下を追加することで埋め合わせができます:

PermitRootLogin forced-commands-only

上記の設定は root が SSH で実行できるコマンドを制限するだけでなく、パスワードの使用も無効化して、root アカウントでは強制的に公開鍵認証を使うようになります。

root で使えるコマンドは制限しないで公開鍵認証の強制だけをするという手もあり、それでもブルートフォース攻撃はほぼ不可能です。その場合、以下を設定:

PermitRootLogin prohibit-password

authorized_keys ファイルのロック

警告: このファイルをロックしても、ユーザの間違いや特定の単純な対人攻撃からの保護しかできません。この方法は、悪意のあるプログラムや侵入に対するあらゆる保護も提供しません。多要素認証、ファイアウォール、そして縦深防御を用いて、侵入を未然に防いでください。

何らかの理由により、疑いのあるユーザに既存の鍵を追加/変更させるべきではないと思われる場合、そのファイルを操作できないようにできます。

サーバでは、ユーザの authorized_keys ファイルを読み取り専用にして、他の全パーミッションを禁止してください:

$ chmod 400 ~/.ssh/authorized_keys

ユーザがパーミッションを元に戻せないようにするには、authorized_keys ファイルに変更不可のビットを設定してください。ユーザが ~/.ssh ディレクトリをリネームして新しい ~/.ssh ディレクトリと authorized_keys ファイルを作成できないようにするには、~/.ssh ディレクトリにも変更不可のビットを設定してください。鍵を追加/削除するには、authorized_keys から変更不可のビットを削除して一時的に書き込み可能にする必要があります。

ヒント: auditd などを用いて、authorized_keys ファイルの変更を記録することが推奨されます。

ヒントとテクニック

暗号化 SOCKS トンネル

暗号化トンネルは信頼ができない様々なワイヤレス接続を使用するノートパソコンなどで非常に有用です。必要なのは SSH サーバーが安全な場所 (家や仕事場など) で動作していることだけです。DynDNS などのダイナミック DNS サービスを利用すれば IP アドレスを覚える必要もありません。

手順 1: 接続の開始

以下のコマンドを実行することで接続を開始できます:

$ ssh -TND 4711 user@host

user はユーザー名に host は SSH サーバーが動作しているホストに置き換えてください。パスワードを入力すると接続が行われます。N フラグはインタラクティブプロンプトを無効化し、D フラグは listen するローカルポートを指定します (ポート番号は何でもかまいません)。T フラグは疑似 tty アロケーションを無効化します。

verbose (-v) フラグを追加することで、接続が成功していることを出力から確認することができます。

手順 2: ブラウザ (やその他のプログラム) の設定

新しく作成した socks トンネルを使用するようにウェブブラウザ (や他のプログラム) を設定しないと上記の作業は無意味です。最新バージョンの SSH は SOCKS4 と SOCKS5 に対応しているため、どちらかを使うことができます。

  • Firefox の場合: 編集 → 設定 → 詳細 → ネットワーク → 接続 → 接続設定:
ラジオボタンの手動でプロキシを設定するにチェックを入れて、SOCKS ホストテキストフィールドに localhost と、次のテキストフィールドにポート番号を入力してください (上の例では 4711)。

Firefox はデフォルトでは DNS リクエストの作成に socks トンネルを使用しません。以下の手順で設定することでプライバシーを守ることができます:

  1. Firefox のロケーションバーに about:config と入力。
  2. network.proxy.socks_remote_dns を検索。
  3. 値を true に設定。
  4. ブラウザを再起動。
  • Chromium の場合: 環境変数やコマンドラインオプションで SOCKS の設定ができます。以下の関数を .bashrc に追加することを推奨します:
function secure_chromium {
    port=4711
    export SOCKS_SERVER=localhost:$port
    export SOCKS_VERSION=5
    chromium &
    exit
}

もしくは:

function secure_chromium {
    port=4711
    chromium --proxy-server="socks://localhost:$port" &
    exit
}

ターミナルから以下のように実行してください:

$ secure_chromium

X11 フォワーディング

X11 フォワーディングはリモートシステムで X11 プログラムを動作させて、グラフィカルインターフェイスをローカルのクライアントマシンで表示させるメカニズムです。X11 フォワーディングではリモートホストに X11 システムを完全にインストールさせる必要はなく、xauth をインストールするだけで十分です。xauth は、、X11 セッションの認証を行うために必要なサーバーとクライアントによって使用される Xauthority の設定を管理するユーティリティです (ソース)。

警告: X11 フォワーディングにはセキュリティ的に重要な問題があります。ssh, sshd_config, ssh_config のマニュアルページの該当するセクションを読んで最低限の知識をつけてください。こちらの記事 も参照。

セットアップ

リモート側
クライアント側

クライアント側では、接続するたびにコマンドラインで -X スイッチを指定して ForwardX11 オプションを有効にするか、openSSH クライアントの設定ファイルForwardX11yes に設定してください。

ヒント: GUI の描画がおかしい場合やエラーが表示されるときは ForwardX11Trusted オプションを有効にできます (コマンドラインでは -Y スイッチ)。X11 フォワーディングが X11 SECURITY 拡張 の制御から外れるようになります。使用するときはセクション冒頭の警告を読んでください。

使用方法

通常通りリモートマシンにログインします、クライアント側の設定ファイルで ForwardX11 を有効にしていない場合は -X スイッチを指定します:

$ ssh -X user@host

グラフィカルなアプリケーションを実行しようとするとエラーが表示される場合、代わりに ForwardX11Trusted を試してみて下さい:

$ ssh -Y user@host

リモートサーバーで X プログラムが起動できるようになったら、出力がローカルセッションに転送されます:

$ xclock

"Cannot open display" エラーが表示される場合、root 以外のユーザーで以下のコマンドを実行してみてください:

$ xhost +

上記のコマンドは全てのユーザーに X11 アプリケーションの転送を許可します。特定のホストだけに転送を制限するには:

$ xhost +hostname

hostname は転送先のホストの名前に置き換えてください。詳しくは man xhost を参照。

特定のアプリケーションではローカルマシンでインスタンスが動作しているかチェックが実行されます。例えば Firefox は以下の起動パラメータを使用してローカルマシンでリモートインスタンスを起動する必要があります:

$ firefox --no-remote

接続時に "X11 forwarding request failed on channel 0" と表示される場合 (サーバーの /var/log/errors.log に "Failed to allocate internet-domain X11 display socket" と出力される場合)、xorg-xauth パッケージがインストールされていることを確認してください。上手く機能しない場合、以下の設定を試してみてください:

  • サーバーの sshd_configAddressFamily any オプションを有効にする。
  • サーバーの sshd_configAddressFamily オプションを inet に設定する。

IPv4 で Ubuntu クライアントを使っている場合は inet に設定することで問題が解決します。

SSH サーバーの他のユーザーで X アプリケーションを実行するには SSH でログインしているユーザーの xauth list の認証行を xauth add する必要があります。

他のポートのフォワーディング

SSH は X11 をサポートしているだけでなく、TCP 接続のセキュアなトンネル化に使用することもできます。ローカルフォワーディングとリモートフォワーディングの両方が使えます。

ローカルフォワーディングはローカルマシンのポートを開いて、リモートホストに接続が転送されます。転送先をリモートホストと同じにすることで、同一マシンでセキュアな VNC 接続などができます。ローカルフォワーディングは -L スイッチで利用することができ <tunnel port>:<destination address>:<destination port> という形式で転送先を指定します:

$ ssh -L 1000:mail.google.com:25 192.168.0.100

上記のコマンドは SSH で 192.168.0.100 にログインしてシェルを開きます。そしてローカルマシンの TCP ポート 1000 から mail.google.com のポート 25 にトンネルが作成されます。接続が確立すると localhost:1000 への通信は Gmail の SMTP ポートに接続されます。Google から見ると、192.168.0.100 から接続が来ているように見えます (必ずしも接続と一緒にデータが運ばれるとは限りません)。データはローカルマシンと 192.168.0.100 の間は安全に運ばれます。

同じように以下のコマンドは localhost:2000 に接続することができ、リモートホストのポート 6001 に透過的に送信されます:

$ ssh -L 2000:192.168.0.100:6001 192.168.0.100

前者の例はセキュリティ上問題がある (tightvncAUR パッケージに含まれている) vncserver ユーティリティによる VNC 接続などで有用です。

リモートフォワーディングは SSH トンネルとローカルマシンを通してリモートホストから任意のホストに接続できるようにします。ローカルフォワーディングとは逆の機能であり、ファイアウォールによってリモートホストの接続が限られている場合などに有用です。リモートフォワーディングは -R スイッチで使うことができ <tunnel port>:<destination address>:<destination port> という形式で転送先を指定します:

$ ssh -R 3000:irc.freenode.net:6667 192.168.0.200

上記のコマンドは 192.168.0.200 にシェルを立ち上げて、192.168.0.200 からローカルホストの3000番ポートへの接続をトンネルを通して送信し、それから irc.freenode.net のポート 6667 に転送します。ポート 6667 がブロックされている場合でもリモートホストから IRC プログラムを利用することができるようになります。

ローカルフォワーディングとリモートフォワーディングはどちらもセキュアなゲートウェイとして使用することができます。<tunnel address>:<tunnel port>:<destination address>:<destination port> のようにバインドアドレスをつかうことで、SSH や SSH デーモンを動かしていなくても他のコンピュータが SSH トンネルを利用することが可能です。<tunnel address> はトンネルの入り口となるマシンのアドレスです: localhost, * (あるいは空)。特定のアドレス経由の接続、ループバックインターフェイス経由の接続、全てのインターフェイス経由の接続を許可します。デフォルトでは、フォワーディングはトンネルの入り口のマシンからの接続だけに制限されており <tunnel address>localhost に設定されています。ローカルフォワーディングは特に設定が必要ありませんが、リモートフォワーディングはリモートサーバーの SSH デーモンの設定によって制限を受けます。詳しくは sshd_config(5)GatewayPorts オプションを見てください。

踏み台ホスト

場合によっては、接続先の SSH デーモンに直接接続できず、踏み台サーバー (ジャンプサーバー) を使わざるを得ないことがあります。ふたつ以上の SSH トンネルを接続して、それぞれのサーバーに対してローカルの鍵で認証します。SSH エージェントの転送 (-A) と疑似端末の割当 (-t) を使って以下のようにローカルの鍵を転送します:

$ ssh -A -t -l user1 bastion1 \
  ssh -A -t -l user2 intermediate2 \
  ssh -A -t -l user3 target

以下のように -J フラグを使用することもできます:

$ ssh -J user1@bastion1,user2@intermediate2 user3@target

-J ディレクティブで指定するホストはカンマで区切り、指定された順番で接続されます。user...@ の部分は必須ではありません。-J で指定したホストは ssh の設定ファイルを使うため、必要であればホスト毎にオプションを設定することが可能です。

マルチプレクス

SSH デーモンは通常はポート 22 番をリッスンします。しかし、公共のインターネット・ホットスポットでは HTTP/HTTPS のポート(80 と 443)以外のトラフィックをブロックしていることが一般的です。そのため SSH 接続がブロックされてしまいます。すぐできる解決策として、許可されているポートで sshd を起動するという方法があります:

/etc/ssh/sshd_config
Port 22
Port 443

しかしポート 443 番は HTTPS を提供する Web サーバにすでに使われていることが多いです。その場合は sslh のようなマルチプレクサを使います。これは指定ポートをリッスンし、そこに来るパケットを複数のサービスに賢く振り分けることができます。

SSH の高速化

接続をグローバル及び特定のホストに対して高速化させることのできるクライアント設定がいくつかあります。これらのオプションに関する完全な説明は ssh_config(5) を参照してください。

  • より高速な暗号を使う: AESNI 命令セットを持つ最近の CPU では、aes128-gcm@openssh.comaes256-gcm@openssh.com を使うことで openssh のデフォルトの優先暗号 (通常 chacha20-poly1305@openssh.com) よりも劇的に優れたパフォーマンスを得られるはずです。暗号は -c フラグで選択できます。永続的に設定するには、~/.ssh/config 内に Ciphers オプションを追加し、暗号を優先順に並べて設定してください (例:
    Ciphers aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
    )。
  • 圧縮を有効化あるいは無効化する: 圧縮は低速な接続において速度を向上させることができます。Compression yes オプションか -C フラグで有効化できます。しかし、使用される圧縮アルゴリズムは比較的低速な gzip(1) であり、高速なネットワークにおいてはボトルネックになってしまいます。接続を高速化させるために、ローカルネットワークや高速なネットワークにおいては Compression no を使うべきでしょう。
  • 接続共有: 以下のオプションを使用することで、同一ホストに対するセッションをすべて単一の接続に共有させることができます:
    ControlMaster auto
    ControlPersist yes
    ControlPath ~/.ssh/sockets/socket-%r@%h:%p
    
~/.ssh/sockets の部分は、他のユーザによって書き込むことができないのであれば、どのディレクトリでも構いません。
  • ControlPersist は、初回のクライアント接続が閉じられてから、新しいクライアントのためにマスターがどれくらいバックグラウンドで待機すべきかを指定します。利用可能な値は:
    • no: 最後のクライアントが切断されたらすぐに接続を閉じます。
    • 秒単位の時間
    • yes: 永遠に待ちます。接続は自動的に閉じられなくなります。
  • AddressFamily inet オプションか -4 フラグを使用して IPv6 ルックアップをバイパスすることで、ログインに要する時間を短くすることができます。
  • 最後に、SSH を SFTP や SCP のために使用するつもりであれば、High Performance SSH/SCP は、SSH バッファサイズを動的に大きくすることで、スループットを劇的に増やすことができます。この改善のパッチが施されたバージョンの OpenSSH である openssh-hpn-gitAUR パッケージをインストールしてください。

SSHFS でリモートファイルシステムをマウントする

sshfs を使って (SSH でアクセスした) リモートのファイルシステムをローカルフォルダにマウントする方法は Sshfs の記事を参照してください。マウントしたファイルは様々なツールであらゆる操作することができます (コピー、名前の変更、vim で編集など)。基本的に shfs よりも sshfs を使用することを推奨します。sshfs は shfs の新しいバージョンであり、元の shfs は2004年から更新されていません。

Keep alive

一定時間操作がないと ssh セッションは自動的にログアウトします。接続を維持するには以下をクライアントの ~/.ssh/config/etc/ssh/ssh_config に追加してください:

ServerAliveInterval 120

これで120秒ごとに "keep alive" シグナルがサーバーに送信されます。ServerAliveCountMaxTCPKeepAlive オプションも参照してください。

反対に、外部からの接続を維持するには、次をサーバーの /etc/ssh/sshd_config に設定します (数字は0より大きく):

ClientAliveInterval 120

systemd で SSH トンネルを自動的に再起動

systemd を使ってブート時/ログイン時に SSH 接続を自動的に開始して、接続が失敗した時に再起動させることができます。SSH トンネルの管理に役立つツールとなります。

以下のサービスでは、ssh の設定に保存された接続設定を使って、ログイン時に SSH トンネルを開始します。接続が何らかの理由で閉じられた場合、10秒待機してから再起動します:

~/.config/systemd/user/tunnel.service
[Unit]
Description=SSH tunnel to myserver

[Service]
Type=simple
Restart=always
RestartSec=10
ExecStart=/usr/bin/ssh -F %h/.ssh/config -N myserver

上記のユーザーサービスを有効化して起動してください。トンネルがタイムアウトするのを防ぐ方法は #Keep alive を見て下さい。起動時にトンネルを開始したい場合、ユニットをシステムサービスとして書きなおして下さい。

Autossh - SSH セッションとトンネルの自動再起動

ネットワークの状態が悪かったりしてクライアントが切断してしまい、セッションやトンネルの接続を維持できない場合、autossh を使って自動的にセッションとトンネルを再起動できます。

使用例:

$ autossh -M 0 -o "ServerAliveInterval 45" -o "ServerAliveCountMax 2" username@example.com

sshfs を組み合わせる:

$ sshfs -o reconnect,compression=yes,transform_symlinks,ServerAliveInterval=45,ServerAliveCountMax=2,ssh_command='autossh -M 0' username@example.com: /mnt/example 

プロキシ設定で設定した SOCKS プロクシを使って接続:

$ autossh -M 0 -o "ServerAliveInterval 45" -o "ServerAliveCountMax 2" -NCD 8080 username@example.com 

-f オプションで autossh をバックグラウンドプロセスとして実行することができます。ただし対話式でパスフレーズを入力することができなくなります。

セッション中に exit と入力したり autossh プロセスに SIGTERM, SIGINT, SIGKILL 信号が送られるとセッションは終了します。

systemd を使ってブート時に自動的に autossh を起動する

autossh を自動的に起動したい場合、以下の systemd ユニットファイルを作成します:

/etc/systemd/system/autossh.service
[Unit]
Description=AutoSSH service for port 2222
After=network.target

[Service]
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M 0 -NL 2222:localhost:2222 -o TCPKeepAlive=yes foo@bar.com

[Install]
WantedBy=multi-user.target

AUTOSSH_GATETIME=0 は接続が成功して ssh が立ち上がったと autossh が認識する秒数です。0に設定すると autossh は ssh の最初の起動失敗を無視します。起動時に autossh を実行する場合は設定するべきです。他の環境変数は man ページを見てください。必要であればもっと複雑に設定することもできますが、AUTOSSH_GATETIME=0 を含む -f は systemd では機能しません。

設定後はサービスを起動有効化してください。

以下のように ControlMaster を無効化する必要もあるかもしれません:

ExecStart=/usr/bin/autossh -M 0 -o ControlMaster=no -NL 2222:localhost:2222 -o TCPKeepAlive=yes foo@bar.com
ヒント: 複数のautosshプロセスを維持し、複数のトンネルを存続させることも簡単です。名前の異なる複数のサービスファイルを作成するだけです。

トラブルシューティング

チェックリスト

以下は最初に行うべきトラブルシューティングのチェックリストです。何かする前に以下の問題をチェックすることを推奨します。

  1. 設定ディレクトリ ~/.ssh の中身がユーザーからアクセスできることを確認する (クライアントとサーバーの両方で確認してください):
    $ chmod 700 ~/.ssh
    $ chmod 600 ~/.ssh/*
    $ chown -R $USER ~/.ssh
    
  2. クライアントの公開鍵 (例: id_rsa.pub) がサーバーの ~/.ssh/authorized_keys に存在することを確認する。
  3. サーバーの設定AllowUsersAllowGroups によって SSH によるアクセスが制限されていることを確認する。
  4. ユーザーにパスワードが設定されていることを確認する。新しいユーザーにはパスワードが設定されていない可能性があります。
  5. sshd を再起動してクライアントとサーバーの両方で一度ログアウトをしてみる。

接続が拒否されるまたはタイムアウトする

ルーターがポートフォワーディングをしていないか?

NAT モードやルーターを使っている場合、ルーターが ssh 接続を転送していないか確認してください。サーバーの内部 IP アドレスは $ ip addr で確認することができるので、SSH ポートの TCP をその IP に転送するようにルーターを設定してください。portforward.com も役に立ちます。

SSH が動作しているか?

$ ss -tnlp

上記のコマンドで SSH ポートが開いていると表示されない場合、SSH は動作していません。/var/log/messages にエラーがないか確認してください。

接続をブロックするようなファイアウォールのルールが存在しないか?

iptables によってポート 22 の接続がブロックされている可能性があります。次のコマンドで確認してください:

# iptables -nvL

INPUT チェインのパケットを拒否するようなルールがないか見て下さい。そして、必要であれば、次のようなコマンドでポートのブロックを解除します:

# iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT

ファイアウォールの設定に関する詳細はファイアウォールを見て下さい。

トラフィックがコンピュータにまで到達しているか?

以下のように問題のコンピュータのトラフィックを収集してみてください:

# tcpdump -lnn -i any port ssh and tcp-syn

上記は基本的な情報を表示します。トラフィックが表示されるまで待ってください。その後、接続を試行してみてください。何も出力がされない場合、コンピュータの外側にある何かがトラフィックを妨害しています (例: ハードウェアファイアウォールや NAT ルーターなど)。

ISP またはサードパーティによってデフォルトのポートがブロックされてないか?

ノート: このステップは次のことを確認した後で実行してください。ファイアーウォールを何も起動していないこと。DMZ へのルーターを正しく設定している、またはコンピュータへポートを転送していること。それでもまだ動かない場合、ここで診断のステップと解決法が見つかるでしょう。

ときどき ISP (インターネット・サービス・プロバイダ) が SSH のデフォルトポート (22番) をブロックしている場合があります。この場合はあなたが何をしても (ポートを開ける、スタックを強化する、フラッドアタックを防御する、など) 無意味になります。ブロックされているかどうか確認するために、全てのインターフェイス (0.0.0.0) をリッスンする sshd を立ち上げ、リモートから接続してみます。

このようなエラーメッセージが出る場合:

ssh: connect to host www.inet.hr port 22: Connection refused

これはそのポートが ISP にブロックされていないが、そのポートでサーバーの SSH が起動していないことを意味します (security through obscurity を参照)。

しかし、次のようなエラーメッセージが出る場合:

ssh: connect to host 111.222.333.444 port 22: Operation timed out 

これは何かがポート 22 での TCP トラフィックを拒否 (reject) していることを意味します。そのポートはあなたのサーバー上のファイアーウォールか第三者 (ISP など) のどちらかによってステルスされています。自分のサーバーでファイアーウォールが起動していないことが確かなら、また、ルーターやスイッチの中でグレムリンが育っていないことが確かなら、ISP がトラフィックをブロックしています。

ダブルチェックのために、サーバ上で Wireshark を起動してポート 22 でのトラフィックをリッスンしてみましょう。Wireshark はレイヤ 2 のパケット・スニファリング・ユーティリティであり、TCP/UDP はレイヤ 3 以上なので (IP ネットワークスタックを参照)、もしリモートから接続するときに何も受け取っていなければ、十中八九、第三者がブロックしています。

問題診断

tcpdump または wireshark-cli パッケージの Wireshark をインストールしてください。

tcpdump の場合:

# tcpdump -ni interface "port 22"

Wireshark の場合:

$ tshark -f "tcp port 22" -i interface

interface は WAN 接続に使っているネットワークインターフェイスに置き換えてください (確認したいときは ip a を実行)。リモートで接続を試行してもパケットが全く受け取れない場合、ISP によってポート 22 のトラフィックがブロックされている可能性があります。

解決方法

解決方法は、単に ISP がブロックしていない他のポートを使うことです。/etc/ssh/sshd_config を編集して他のポートを使うようにしましょう。例えば次を追加します:

Port 22
Port 1234

そしてこのファイル中の他の Port 設定をコメントアウトします。「Port 22」をコメントにして「Port 1234」を追加するだけでは、sshd がポート 1234 しかリッスンしなくなるので、この問題は解決しません。この 2 行どちらも使用し、sshd が両方のポートをリッスンするようにします。

あとは systemctl restart sshd.service で sshd を起動するだけです。そして ssh クライアントでも同じポートに変更します。

Read from socket failed: connection reset by peer

最近の openssh のバージョンでは、楕円曲線暗号関連のバグのせいで、上記のエラーメッセージで接続が失敗することがあります。その場合 ~/.ssh/config に次の行を追加してください:

HostKeyAlgorithms ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,ssh-dss

openssh 5.9 では、上記の修正方法は働きません。代わりに、~/.ssh/config に以下の行を記述してください:

Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc 
MACs hmac-md5,hmac-sha1,hmac-ripemd160

openssh バグフォーラムの 議論 も参照。

"[your shell]: No such file or directory" / ssh_exchange_identification 問題

シェルのバイナリに $PATH が通っている場合でも、特定の SSH クライアントは $SHELL に絶対パスを設定する必要があります (パスは whereis -b [your shell] で確認できます)。

"Terminal unknown" や "Error opening terminal" エラーメッセージ

ssh でログイン時に "Terminal unknown" のようなエラーが表示されることがあります。これはサーバーがターミナルを認識できていないことを意味します。また、nano などの ncurses アプリケーションを実行すると "Error opening terminal" というメッセージが表示されます。

クライアントで使用しているターミナルの terminfo ファイルをサーバーにインストールするのが正しい解決方法です。これによってサーバーのコンソールプログラムがターミナルを正しく扱えるようになります。infocmp を実行してからパッケージを確認することで terminfo に関する情報を取得できます。

通常の方法でファイルをインストールできない場合、サーバーのホームディレクトリに terminfo をコピーしてください:

$ ssh myserver mkdir -p  ~/.terminfo/${TERM:0:1}
$ scp /usr/share/terminfo/${TERM:0:1}/$TERM myserver:~/.terminfo/${TERM:0:1}/

サーバーから一度ログアウトしてからログインしなおすと問題が解決しているはずです。

$TERM 変数を設定する解決策

警告: この方法はあくまで次善策であり、たまにしか接続しない ssh サーバーで使うようにしてください。

.bash_profile などで TERM=xterm と設定することでもエラーが表示されなくなり、ncurses アプリケーションが動作するようになります。ただし副作用があり、ターミナルの制御シーケンスが xterm と異なっている場合グラフィックがおかしくなります。

Connection closed by x.x.x.x [preauth]

sshd のログでこのエラーが確認できる場合、HostKey が正しく設定されているか確認してください:

HostKey /etc/ssh/ssh_host_rsa_key

サブシステム要求の失敗

OpenSSH 8.8 以降、scp はデータ転送のデフォルトプロトコルとして SFTP を使用し、sftp というサブシステムを要求するようになりました。もし scp を冗長モード scp -v で実行すれば、クライアントがどのサブシステムを使っているかがわかります (例: Sending subsystem: <subsystem-name>)。subsystem request failed on channel 0 のようなエラーは、サーバのサブシステムを設定することで修正できるかもしれません。{man|5|sshd_config|Subsystem}} のように設定します。サーバの設定は、以下の例のようにする必要があります。

/etc/ssh/sshd_config
...
Subsystem subsystem-name /path/to/subsystem-executable
...

OpenSSH 7.0 によって id_dsa が拒否される

OpenSSH 7.0 ではセキュリティ上の理由から ssh-dss が無効になっています。どうしても有効にする必要がある場合、クライアントの設定オプションを使用してください ([2] には書かれていない方法です):

PubkeyAcceptedKeyTypes +ssh-dss

OpenSSH 7.0 で No matching key exchange method found

OpenSSH 7.0 では Logjam 攻撃からの(理論上の)脆弱性を理由に diffie-hellman-group1-sha1 鍵アルゴリズムが無効になっています (http://www.openssh.com/legacy.html を参照)。特定のホストで鍵アルゴリズムが必要な場合、ssh は以下のようなエラーメッセージを吐きます:

Unable to negotiate with 127.0.0.1: no matching key exchange method found.
Their offer: diffie-hellman-group1-sha1

古いアルゴリズムを使用しないようにサーバーをアップグレード・設定することで上記のエラーは解決します。サーバー側の設定を変更できない場合、クライアント設定で KexAlgorithms +diffie-hellman-group1-sha1 オプションを使うことでアルゴリズムを有効化できます。

SSH から切断したときに tmux/screen セッションが終了する

セッションの最後にプロセスが終了する場合、ソケットアクティベーションを使っているために SSH セッションプロセスが終了したときに systemd によって終了されている可能性があります。ssh.socket の代わりに ssh.service を使用してソケットアクティベーションを使わないことで解決できます。もしくは ssh@.service の Service セクションで KillMode=process を設定してください。

KillMode=process は古典的な ssh.service でも役に立つことがあります。サーバーが停止したり再起動したときに SSH セッションプロセスや screentmux のプロセスが終了されることを防ぐことができます。

SSH セッションが応答しなくなる

SSH は Software flow control XONXOFF に反応します。Ctrl+s を押すとフリーズ/ハングアップ/応答停止します。セッションを再開するには Ctrl+q を使ってください。

Broken pipe

接続を作ろうとして packet_write_wait のレスポンスが Broken pipe になった場合、デバッグモードで接続を再試行し、出力がエラーで終わるかどうか確認する必要があります。

debug3: send packet: type 1
packet_write_wait: Connection to A.B.C.D port 22: Broken pipe

上記の send packet の行は、応答パケットが受信されなかったことを示しています。つまり、これは QoS の問題であることがわかります。パケットを落とす可能性を減らすには、IPQoS を設定してください。

/etc/ssh/ssh_config
Host *
    IPQoS reliability

サービスタイプは reliability (0x04) で、0x00throughput (0x08) と同様に問題を解決できるはずです。

再起動後デーモンの起動が遅い

特にヘッドレスサーバや仮想化サーバにおいて、再起動後のデーモン起動時間が過度に長くなる場合(例:デーモンが接続を受け付け始めるまでに数分かかる)、エントロピー不足が原因かもしれません [3] これは、あなたのシステムに適した Rng-toolsHaveged をインストールすれば改善することが可能です。ただし、それぞれのパッケージの wiki ページで説明されている、関連するセキュリティ上の影響に注意してください。

応答のない SSH 接続を終了する

クライアントセッションが応答しなくなり、実行中のプログラム (例えば シェル) に終了を指示しても終了しない場合、 Enter, ~, . をこの順番で次々に押すと、セッションを終了させることが可能です。

この ~ は疑似端末エスケープ文字で (ssh(1) § ESCAPE CHARACTERS 参照) 終了させるクライアントセッションに応じて複数回付加することが可能です。例えば、A から B へ接続し、B から C へ接続したときに B から C へのセッションがフリーズした場合、 Enter を押して ~. と入力すれば、B の作業セッションを残して終了させることができます。

WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

クライアントが ssh サーバの鍵が変更されたことを警告した場合、新しく提供された鍵が 本当にサーバオペレータのものであるかどうかを確認する必要があります。そして known_hosts ファイルから古い鍵を ssh-keygen -R $SSH_HOST で削除し、新しい鍵を新しいサーバであるかのように受け入れてください。

適切な terminfo エントリがないリモートに接続する場合

端末の terminfo エントリがないホストに接続する場合、例えば、terminfo エントリが ncurses に同梱されていない端末エミュレータを使用する場合などです。(例えば kittyrxvt-unicode) terminfo データベースが制限されているホスト (例えば OpenWrt が動いているシステム) に接続する場合、terminfo(5) に依存しているソフトウェアで様々な問題が発生する可能性があります。

適切な解決策は、適切な terminfo エントリをホストに設置することです。それが不可能な場合は、リモートホストがサポートし、かつ端末と互換性のある値を TERM に設定することで解決できます。

OpenSSH 8.7 以降、カスタムの TERM 環境変数をリモートホストに渡すには、 簡単な設定スニペットを使います。

~/.ssh/config
Host example.com
  SendEnv TERM=xterm-256color

参照