コンテンツにスキップ

「OpenSSH」の版間の差分

提供: ArchWiki
削除された内容 追加された内容
AshMyzk (トーク | 投稿記録)
同期
 
(2人の利用者による、間の26版が非表示)
1行目: 1行目:
[[Category:セキュアシェル]]
{{Translateme|飜訳および編集が必要です。英語版を参照してください。}}
[[Category:Secure Shell]]
[[Category:サーバー]]
[[Category:サーバー]]
[[Category:OpenBSD]]
[[Category:OpenBSD]]
6行目: 5行目:
[[en:OpenSSH]]
[[en:OpenSSH]]
[[es:OpenSSH]]
[[es:OpenSSH]]
[[fa:SSH]]
[[fr:OpenSSH]]
[[fr:OpenSSH]]
[[pt:Secure Shell]]
[[ru:OpenSSH]]
[[ru:OpenSSH]]
[[zh-hans:OpenSSH]]
[[zh-hans:OpenSSH]]
17行目: 14行目:
{{Related|sshguard}}
{{Related|sshguard}}
{{Related|Sshfs}}
{{Related|Sshfs}}
{{Related|syslog-ng}}
{{Related|Syslog-ng}}
{{Related|SFTP chroot}}
{{Related|SFTP chroot}}
{{Related|SCP と SFTP}}
{{Related|SCP と SFTP}}
{{Related|乱数生成}}
{{Related|VPN over SSH}}
{{Related articles end}}
{{Related articles end}}
[[Wikipedia:ja:OpenSSH|OpenSSH]] (OpenBSD Secure Shell) は、[[セキュアシェル]] (SSH) プロトコルを用いてコンピュータネットワーク経由の暗号化された通信セッションを提供するコンピュータプログラム群です。OpenSSH は、SSH Communications Security によって提供されているプロプライエタリな Secure Shell ソフトウェアスイートのオープンソースな代替として作成されました。OpenSSH は OpenBSD プロジェクトの一部として開発されており、Theo de Raadt によって率いられています。
Secure Shell (SSH) は暗号技術を利用して、安全にリモートコンピュータと通信するためのネットワークプロトコルです。暗号によってデータの機密性と完全性が保証されます。SSH は公開鍵暗号を使ってリモートコンピュータを認証し、リモートコンピュータは必要に応じてユーザーを認証します。


OpenSSH は、似た名前の OpenSSL と混同されることがあります。しかし、これらのプロジェクトの目的は異なり、開発チームも異なります。この似たような名前は、ただ単にゴールが似ているからです。
基本的に SSH はリモートマシンにログインしてコマンドを実行するために使われますが、トンネリングや TCP ポートや X11 接続の任意のフォワーディングをサポートしており、SFTP や SCP プロトコルを使うことでファイル転送をすることも可能です。


== インストール ==
デフォルトでは、SSH サーバーは標準の TCP 22番ポートを使います。通常は SSH クライアントプロトコルを使って ''sshd'' デーモンの接続を確立してリモート接続を承認します。macOS, GNU/Linux, Solaris, OpenVMS など近代的なオペレーティングシステムのほとんどでサーバーとクライアントの両方が備わってします。複雑なもの・完全なものまで様々なレベルのバージョンがプロプライエタリ・フリーウェア・オープンソースを問わずに存在します。


{{Pkg|openssh}} パッケージを[[インストール]]してください。
== OpenSSH ==
OpenSSH (OpenBSD Secure Shell) は ssh プロトコルを使ってコンピューターネットワークを介して暗号化通信セッションを提供するコンピュータープログラムのセットです。SSH Communications Security によるプロプライエタリの Secure Shell ソフトウェアスイートに代わるオープンのプログラムとして作成されました。OpenSSH は Theo de Raadt に率いられている OpenBSD プロジェクトの一環として開発されています。


== クライアントの使用 ==
同じような名前の OpenSSL と OpenSSH が混同されることがときどきありますが、プロジェクトの目的・開発チームは異なります。


サーバに接続するには、以下を実行してください:
=== OpenSSH のインストール ===
[[公式リポジトリ]]から {{Pkg|openssh}} を[[pacman|インストール]]してください。


$ ssh -p ''ポート'' ''ユーザ''@''サーバアドレス''
=== SSH の設定 ===
====クライアント====
SSH クライアントの設定ファイルは {{ic|/etc/ssh/ssh_config}} もしくは {{ic|~/.ssh/config}} です。


サーバが公開鍵認証のみを許可している場合、[[SSH 鍵]] の記事に従ってください。
{{ic|Protocol 2}} を明示的に設定する必要はありません。デフォルトの設定ファイルではコメントアウトされています。つまり明示的に有効にされない限り {{ic|Protocol 1}} は使われません。 (ソース: http://www.openssh.org/txt/release-5.4)


====デーモン====
=== 設定 ===

SSH デーモンの設定ファイルは {{ic|/etc/ssh/ssh'''d'''_config}} です。
クライアントは、共通のオプションとホストを保存するように設定することができます。全プションは、グローバルに、あるいは特定のホストに制限して宣言することができます。例えば:

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

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

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

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

詳細は {{man|5|ssh_config}} を見てください。

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

== サーバの使用 ==

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

# sshd -t

=== 設定 ===

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


特定のユーザーにだけアクセスを許可するには次の行を追加してください:
AllowUsers ''user1 user2''
AllowUsers ''user1 user2''


特定のグループにだけアクセスを許可するには:
一部のグループにのみアクセスを許可するには:
AllowGroups ''group1 group2''


AllowGroups ''group1 group2''
SSH による root ログインを無効にするには、PermitRootLogin 行を次のように変更してください:
PermitRootLogin no


素晴らしいウェルカムメッセージを ({{ic|/etc/issue}} ファイルなどから) 追加するには、{{ic|Banner}} オプションを設定してください:
{{Note|1=バージョン 7.0p1 からは {{ic|PermitRootLogin prohibit-password}} がデフォルトになっています。{{ic|man sshd_config}} を参照。}}


ウェルカムメッセージを追加するには {{ic|/etc/issue}} ファイルを編集して {{ic|Banner}} 行を次のように変更してください:
Banner /etc/issue
Banner /etc/issue


公開ホスト鍵と秘密ホスト鍵は、''sshdgenkeys'' [[#デーモンの管理|サービス]]によって {{ic|/etc/ssh}} 内に自動で生成されます。{{ic|sshd_config}} 内の {{ic|HostKeyAlgorithms}} オプションによって一部の署名アルゴリズムしか許可されていない場合でも、鍵が存在しない場合、再生成されます。[[SSH 鍵#認証鍵の種類を選択|ed25519、ecdsa、そして rsa]] アルゴリズムに基づく3組の鍵のペアが提供されます。sshd に特定の鍵を使用させるには、以下のオプションを指定してください:
ホスト鍵は sshd の systemd サービスによって自動的に生成されます。sshd に特定の鍵を使用させたい場合、手動で設定します:

HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ed25519_key

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


サーバーに WAN からアクセスできる場合、デフォルトのポートである 22 から別のランダムなポートに変更することが推奨されています:
Port 39901
Port 39901


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


=== デーモンの管理 ===
パスワードによるログインを使わないようにすればセキュリティは大幅に向上します。詳しくは [[SSH 鍵#パスワードログインの無効化]] を見て下さい。


{{ic|sshd.service}} を[[起動/有効化]]してください。これは、SSH デーモンを永続的にアクティブ状態に保ち、各着信接続に対してフォークします。
=== sshd デーモンの管理 ===
次のコマンドで sshd デーモンを起動することができます:
# systemctl start sshd.service


{{Note|Systemd のソケットアクティベーションを使用する {{ic|sshd.socket}} は、DOS (サービス拒否) の影響を受けやすいため、{{Pkg|openssh}} 8.0p1-3 で削除されました。詳細は {{Bug|62248}} を参照してください。{{Pkg|openssh}} 8.0p1-3 に更新する時に {{ic|sshd.socket}} が有効化されていた場合、{{ic|sshd.socket}} と {{ic|sshd@.service}} ユニットは {{ic|/etc/systemd/system/}} にコピーされ、[[ヘルプ:読み方#systemd ユニットのコントロール|再有効化]]されます。これは、既存のセットアップを破壊しないためだけに行われるのであって、ユーザは依然として {{ic|sshd.service}} に移行することが推奨されます。}}
次のコマンドで sshd デーモンを起動時に有効にすることができます:
# systemctl enable sshd.service


{{Warning|{{ic|sshd.socket}} の使用を継続するならば、このユニットの問題に注意してください:
詳しくは [[systemd#ユニットを使う]] を見て下さい。
* {{ic|sshd.socket}} ユニットは (例えばメモリ不足の状況などにより) 失敗する場合があり、{{ic|1=Restart=always}} はソケットユニットに対しては指定できません。[https://github.com/systemd/systemd/issues/11553 systemd issue 11553] を参照。
* ソケットアクティベーションの使用は、接続が多すぎるとサービスのアクティブ化が拒否される可能性があるため、サービス拒否を引き起こす可能性があります。{{Bug|62248}} を参照。
}}


{{Note|{{ic|sshd.socket}} を使用すると {{ic|ListenAddress}} の設定が無効化され、任意のアドレスを介して接続できるようになってしまいます。{{ic|ListenAddress}} の設定に効力を持たせるには、{{ic|sshd.socket}} を[[編集]]して、ポートと IP の''両方''を {{ic|ListenStream}} で設定しなければなりません (例: {{ic|1=ListenStream=192.168.1.100:22}})。また、{{ic|[Socket]}} セクションに {{ic|1=FreeBind=true}} も追加しなければなりません。さもないと、IP アドレスを設定した時に {{ic|ListenAddress}} を指定した時と同じ欠点が生じます: ネットワークが時間内に立ち上がっていない場合、ソケットは起動に失敗します。}}
{{Warning|Systemd は非同期にプロセスを実行します。SSH デーモンを特定の IP アドレス {{ic|ListenAddress 192.168.1.100}} に結びつけている場合、デフォルトの sshd.service ユニットファイルはネットワークインターフェイスが有効にされることに依存していないため、ブート中にロードが失敗する可能性があります。IP アドレスをバインドする時は、カスタムした sshd.service ユニットファイルに {{ic|1=After=network.target}} を追加してください。[[systemd#ユニットファイルの編集]] を参照。}}


{{Tip|ソケットアクティベーションを使用すると、各接続に対して {{ic|sshd@.service}} の一時的なインスタンスが (異なるインスタンス名で) 開始されます。ゆえに、{{ic|sshd.socket}} もデーモンの通常の {{ic|sshd.service}} も、接続試行をログでモニタできません。ソケットアクティベートされた SSH インスタンスのログは、{{ic|journalctl -u "sshd@*"}} を root として実行するか、{{ic|journalctl /usr/bin/sshd}} を root
また SSH デーモンソケットを有効にすることで初めて接続があったときにデーモンが起動するようにすることもできます:
として実行することで、確認することができます。}}
# systemctl start sshd.socket
# systemctl enable sshd.socket
デフォルトの22番以外のポートを使う場合、ユニットファイルを[[systemd#ユニットファイルの編集|編集]]する必要があります:
{{hc|# systemctl edit sshd.socket|<nowiki>
[Socket]
ListenStream=
ListenStream=12345
</nowiki>}}


=== 保護 ===
{{Warning|{{ic|sshd.socket}} を使用すると {{ic|ListenAddress}} の設定が打ち消されて、どのアドレスからでも接続できるようになってしまいます。{{ic|ListenAddress}} の設定を適用するには、{{ic|ListenStream}} でポートと IP を指定する必要があります (例: {{ic|1=ListenStream=192.168.1.100:22}})。また、{{ic|[Socket]}} の下に {{ic|1=FreeBind=true}} を追加するようにしてください。そうしないと IP アドレスの設定が {{ic|ListenAddress}} の設定と同じように無効になってしまいます: ネットワークが立ち上がっていない場合にソケットの起動が失敗します。}}


SSH によるリモートログインを許可することは管理業務においては良いことですが、サーバーのセキュリティに脅威を及ぼすことにもなりえます。総当り攻撃の標的になりやすいので、SSH のアクセスは制限して、第三者がサーバーにアクセスできないようにする必要があります。
{{Tip|ソケットアクティベーションを使う場合、{{ic|sshd.socket}} でもデーモンの標準の {{ic|sshd.service}} でもログの接続試行を監視することはできません。ただし {{ic|# journalctl /usr/bin/sshd}} を実行することで監視できます。}}


{{Pkg|ssh-audit}} は、サーバとクライアントの設定の自動化された解析を提供します。このトピックに関して、いくつか他のガイドやツールが利用できます。例えば:
=== サーバーに接続する ===
サーバーに接続するには、次を実行してください:
$ ssh -p ''port'' ''user''@''server-address''


* [[MozillaWiki:Security/Guidelines/OpenSSH|Mozilla Infosec Team による記事]]
=== SSH の保護 ===
* [https://www.ssh-audit.com/hardening_guides.html SSH 堅牢化ガイド]
管理業務のために SSH によるリモートログインを許可することは良いことですが、サーバーのセキュリティに脅威を及ぼすことにもなりえます。総当り攻撃の標的になりやすいので、SSH のアクセスは制限して、第三者がサーバーにアクセスできないようにする必要があります。
* わかりにくいアカウント名やパスワードを使う
* 信頼できる国からの SSH 接続だけを許可する
* [[fail2ban]] や [[sshguard]] をつかってブルートフォース攻撃を監視し、総当りを起こっている IP を閉め出す


==== 公開鍵認証を強制する ====
==== ブルートフォースアタックからの保護 ====
ブルートフォースは単純な攻撃方法です: ランダムなユーザー名とパスワードの組み合わせをとにかく沢山作ってウェブページや SSH などのサーバーログインプロンプトにログインを絶えず試行します。ブルートフォース攻撃からは [[fail2ban]] や [[sshguard]] などの自動スクリプトを使うことで攻撃者をブロックすることで身を守ることができます。[[Uncomplicated Firewall#ufw によるレート制限]]も参照。


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


{{hc|/etc/ssh/sshd_config.d/20-force_publickey_auth.conf|
PasswordAuthentication no
PasswordAuthentication no
ChallengeResponseAuthentication no
AuthenticationMethods publickey
}}


上の設定を適用する前に、SSH アクセス必要てのアカウント {{ic|authorized_keys}} ファイル公開鍵認証の設定ようにしてください。詳しくは [[SSH 鍵#リモートサーバーに公開鍵をコピー]] を参照。
{{Warning|これを設定に追加する前に、SSH アクセス必要とする全アカウントが、対応する {{ic|authorized_keys}} ファイル公開鍵認証をセットアップしていことを確認してください。詳は [[SSH 鍵#リモートサーバーに公開鍵をコピー]] を参照してください}}


==== 2段階認証 ====
==== 二要素認証と公開鍵 ====


SSH は、認証に複数の方法を要求するようにセットアップすることができます。{{ic|AuthenticationMethods}} オプションを使うことで、どの認証方法を要求するかを指定することができます。これにより、公開鍵と二要素認証を使用することができます。
SSH 鍵のペアによる認証を使用していてパスワードによろうログインを無効化している場合に、2段階認証を使いたいときは [[Google Authenticator]] や [[SSH 鍵#2段階認証と公開鍵]] を見て下さい。


==== root ンを制限する ====
===== 認証プ =====
一般的に、SSH で無制限に root ログインを許可することは推奨されません。セキュリティの向上のために、SSH での root ログインを制限する方法は2つ存在します。


Google Authenticator をセットアップする方法については [[Google Authenticator]] を参照してください。
===== root ログインを拒否する =====


[https://duo.com/ Duo] の場合、{{ic|pam_duo.so}} モジュールを提供する {{AUR|duo_unix}} を[[インストール]]してください。必須の Duo 認証情報 (Integration Key、Secret Key、API Hostname) をセットアップする方法に関するインストラクションは [https://duo.com/docs/duounix Duo Unix ドキュメント] を参照してください。
Sudo を使うことで、root アカウントの認証を行うことなく、必要に応じて root 権限を選択的に付与することができます。このため SSH による root ログインを拒否して、攻撃者にパスワードに加えて (root でない) ユーザー名も推測させる必要を生じさせることで、ブルートフォース攻撃を困難にすることが可能です。


===== PAM セットアップ =====
{{ic|/etc/ssh/sshd_config}} の "Authentication" セクションを編集することで SSH からの root ログインを拒否するように設定できます。{{ic|#PermitRootLogin prohibit-password}} を {{ic|no}} に変更して行をアンコメントしてください:


{{Accuracy|1=The distribution defaults to {{ic|KbdInteractiveAuthentication no}} since [https://gitlab.archlinux.org/archlinux/packaging/packages/openssh/-/commit/1d834b1fb688e148797c39cffd95eac3404ef894]. Later, the lexical order of the defaults was adjusted due to {{Bug|79285}} to allow for higher priority user snippets, which would match below {{ic|20-pam.conf}}. However, a [https://bbs.archlinux.org/viewtopic.php?id=300451 BBS thread] appears to be resolved by ordering custom after {{ic|99-archlinux.conf}} defaults only.}}
{{hc|/etc/ssh/sshd_config|

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

{{hc|/etc/ssh/sshd_config.d/20-pam.conf|
KbdInteractiveAuthentication yes
AuthenticationMethods publickey keyboard-interactive:pam
}}
}}


これで、PAM セットアップによって要求されるユーザ認証か公開鍵の'''どちらか一方'''でログインできます。
そして、SSH デーモンを[[再起動]]してください。

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

{{hc|/etc/ssh/sshd_config.d/20-pam.conf|
KbdInteractiveAuthentication yes
AuthenticationMethods publickey''','''keyboard-interactive:pam
}}

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

{{hc|/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 によるレート制限]] や [[シンプルなステートフルファイアウォール#ブルートフォース攻撃]] を参照してください。

バージョン 9.8 以降、[[fail2ban]] に似た基本的な保護機能が実装されました。デフォルトでは {{ic|PerSourcePenalties}} オプションに合理的なデフォルト値が設定されています。様々な条件でソースアドレスによってクライアントにペナルティが掛けられ、接続を一定期間拒否します。

あるいは、ブルートフォースを試みている者を自動でブロックするスクリプトを使うことでブルートフォースから保護することができます。

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

==== root ログインの制限 ====

{{Out of date|現在のバージョンでは、root ログインは上流でデフォルトで無効化されています。}}

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

===== 拒否 =====

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

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

{{hc|/etc/ssh/sshd_config.d/20-deny_root.conf|PermitRootLogin no}}

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


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


===== root ログインを定する =====
===== 限 =====

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


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


上記の設定で、特定の鍵を使ってログインした場合はクォートで囲ったコマンドを実行できるようになります。
上記の設定で、特定の鍵を使ってログインした場合はクォートで囲ったコマンドを実行できるようになります。
151行目: 219行目:
root で使えるコマンドは制限しないで公開鍵認証の強制だけをするという手もあり、それでもブルートフォース攻撃はほぼ不可能です。その場合、以下を設定:
root で使えるコマンドは制限しないで公開鍵認証の強制だけをするという手もあり、それでもブルートフォース攻撃はほぼ不可能です。その場合、以下を設定:


PermitRootLogin without-password
PermitRootLogin prohibit-password


==== authorized_keys ファイルのロック ====
== 他の SSH クライアントとサーバー ==
OpenSSH の他にも、多数の SSH [[Wikipedia:Comparison of SSH clients|クライアント]] と[[Wikipedia:Comparison of SSH servers|サーバー]]が存在します。


{{Warning|このファイルをロックしても、ユーザの間違いや特定の単純な対人攻撃からの保護しかできません。この方法は、悪意のあるプログラムや侵入に対するあらゆる保護も提供'''しません'''。多要素認証、ファイアウォール、そして縦深防御を用いて、侵入を未然に防いでください。}}
=== Dropbear ===
[[Wikipedia:Dropbear (software)|Dropbear]] は SSH-2 クライアント・サーバーです。{{Pkg|dropbear}} は[[公式リポジトリ]]から利用可能です。


何らかの理由により、疑いのあるユーザに既存の鍵を追加/変更させるべきではないと思われる場合、そのファイルを操作できないようにできます。
コマンドラインの ssh クライアントは dbclient という名前が付けられています。


サーバでは、ユーザの {{ic|authorized_keys}} ファイルを読み取り専用にして、他の全パーミッションを禁止してください:
=== Mosh ===
Mosh の [http://mosh.mit.edu/ ウェブサイト] より:


$ chmod 400 ~/.ssh/authorized_keys
ローミングが可能で、断続的な接続もサポートしているリモート端末アプリケーションです。ユーザーのキーストロークのローカルエコーと行編集を提供します。Mosh は SSH の代替です。SSH よりも強固でレスポンスが早く、特に Wi-Fi や携帯端末からの接続、長距離通信など通信速度が遅い場合に役に立ちます。


ユーザがパーミッションを元に戻せないようにするには、{{ic|authorized_keys}} ファイルに[[ファイルのパーミッションと属性#ファイルの属性|変更不可のビットを設定]]してください。ユーザが {{ic|~/.ssh}} ディレクトリをリネームして新しい {{ic|~/.ssh}} ディレクトリと {{ic|authorized_keys}} ファイルを作成できないようにするには、{{ic|~/.ssh}} ディレクトリにも変更不可のビットを設定してください。鍵を追加/削除するには、{{ic|authorized_keys}} から変更不可のビットを削除して一時的に書き込み可能にする必要があります。
[[公式リポジトリ]]から {{Pkg|mosh}} を[[pacman|インストール]]するか [[Arch User Repository|AUR]] にある最新版 {{AUR|mosh-git}} を使って下さい。


{{Tip|[[Audit フレームワーク#ファイルとディレクトリへのアクセスを監査する|auditd]] などを用いて、{{ic|authorized_keys}} ファイルの変更を記録することが推奨されます。}}
Mosh にはドキュメントに記載されていないコマンドラインオプション {{ic|1=--predict=experimental}} が存在し、よりアグレッシブにローカルのキーストロークのエコーを生成します。キーボード入力が遅延なく確認できるのに興味があるのであればこの prediction モードを使ってみて下さい。

==== SSH 証明書 ====

一般的な SSH 鍵と手動でのフィンガープリントの検証は、一人の管理者によって管理されている少数のホストにおいては簡単でしょうが、この認証方法は拡張性が全くありません。一定数のサーバをいくつかのユーザが SSH を通してアクセスする必要がある場合、全てのホストの SSH 公開鍵フィンガープリントを手動でセキュアかつ確実に検証するのは、ほぼ不可能です。

これに対する解決策は、SSH 証明書を使うことです。SSH 証明書を使えば、SSH のデフォルトの Trust On First Use アプローチよりも拡張性の高い信用の鎖によって、公開鍵の正当性を自動で検証できます。SSH 証明書は、基本的には通常の SSH 公開鍵ですが、信頼されている認証局からの署名が付け加えられおり、これにより鍵の正当性を検証します。

===== インフラストラクチャ用のホスト認証局の鍵を作成する =====

$ ssh-keygen -t ed25519 -f ~/.ssh/ca_host_key -C 'Host certificate authority for *.example.com'

認証局の秘密鍵はセキュアに保存されているべきです。鍵の抽出を防止する機構が備わっている [[Nitrokey]] や [[YubiKey]] といったスマートカードやハードウェアトークン上に保存するのが理想です。

===== サーバの SSH ホスト公開鍵を署名する =====

サーバの公開鍵を、認証局の秘密鍵が保存されているローカルのシステムにコピーし、サーバの公開鍵を署名してください:

$ ssh-keygen -h -s ~/.ssh/ca_key -I certLabel -n server01.example.com ./ssh_host_ed25519_key.pub

===== 新しい証明書を移動し、sshd にそれを使わせる =====

生成された証明書 {{ic|ssh_host_ed25519_key-cert.pub}} は、サーバの {{ic|/etc/ssh/}} にコピーする必要があります。

{{hc|/etc/ssh/sshd_config.d/20-ed25519_key.conf|
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
}}

===== 認証局を信頼するように全てのクライアントを設定する =====

{{hc|~/.ssh/known_hosts|
@cert-authority *.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKL8gB/pjuff005YNazwMCqJpgsXAbQ3r4VStd/CRKwU Host certificate authority for *.example.com
}}

{{Warning|サーバが識別用の証明書を提供しないと、デフォルトで公開鍵認証がフォールバックとして使用されてしまいます。}}

===== SSH ユーザ証明書 =====

ユーザの数やデプロイ方法にもよりますが、SSH ユーザ鍵を証明書と共に使用することもできます。多くの ssh ユーザが存在する組織では、この方法でユーザ鍵のデプロイをセキュアに管理することが強く推奨されます。

ユーザ証明書のデプロイは、基本的にはサーバの ID と同じように機能します。詳細と方法については [[Wikibooks:OpenSSH/Cookbook/Certificate-based Authentication]] で見られます。

===== 証明書のデプロイを自動化する =====

多くのオープンソースなツールによって、SSH 証明書のデプロイを自動化する方法が提供されています。人気なものとしては例えば以下があります:

* [https://docs.ansible.com/ansible/latest/collections/community/crypto/openssh_cert_module.html Ansible - openssh_cert module]
* [https://www.privacyidea.org/ privacyIDEA - 認証サーバ]
* [https://theoapp.readthedocs.io/en/latest/ Theo App - 認可された鍵のマネージャ]

==== SSHFP レコード ====

[[Wikipedia:SSHFP record|Secure Shell fingerprint record (SSHFP)]] は、DNS におけるオプションのリソースレコードで、SSH 鍵をホスト名と関連付けます。信用された CA 証明書をサーバー上にアップロードする代わりに DNSSEC を使用することで、公開サーバー上の SSH フィンガープリントを検証することができます。これにより、管理されていないクライアントも鍵のフィンガープリントの有効性を検証することができます。

===== レコードエントリを生成する =====

16進数の鍵フィンガープリントを生成して、DNS レコードに記録するには、対象サーバー上でハッシュ値を作成してください。

$ ssh-keygen -r host.example.com

このコマンドで、指定したドメインの利用可能な全 SSH 鍵を読み出し、有効な SSHFP レコードを出力します。この出力されたレコードを、影響するドメインの DNS エントリに記録することができます。

===== クライアントの設定 =====

SSHFP レコードとして保存されている SSH 鍵フィンガープリントを自動的に取得して信用するには、以下の設定を ssh クライアント側の設定ファイルに追加してください:

{{hc|~/.ssh/config|
# global options
Match all
VerifyHostKeyDNS yes
}}

対象ホストに有効な SSHFP レコードがあり、そのレコードが有効な DNSSEC 署名で検証されると、ホストが本物であるかどうかを尋ねるプロンプトが表示されずに、フィンガープリントが自動的に受理されます。DNS レコードが DNSSEC によって検証されない場合は、フィンガープリントが正しいかどうかを尋ねるプロンプトが代わりに表示されます。

===== SSHFP レコードを生成する =====

ドメインの SSH フィンガープリントを知りたい場合は、''ssh-keyscan'' を使うことで有効な DNS レコードの形式で SSH フィンガープリントを取得できます。(注: デフォルトでは、利用可能な鍵タイプすべてのフィンガープリントが SHA1 と SHA256 の両方で出力されます。)

{{hc|$ ssh-keyscan -D github.com|
; github.com:22 SSH-2.0-babeld-57ca1323
; github.com:22 SSH-2.0-babeld-57ca1323
github.com IN SSHFP 1 1 6f4c60375018bae0918e37d9162bc15ba40e6365
github.com IN SSHFP 1 2 b8d895ced92c0ac0e171cd2ef5ef01ba3417554a4a6480d331ccc2be3ded0f6b
; github.com:22 SSH-2.0-babeld-57ca1323
github.com IN SSHFP 3 1 3358ab5dd3e306c461c840f7487e93b697e30600
github.com IN SSHFP 3 2 a764003173480b54c96167883adb6b55cf7cfd1d415055aedff2e2c8a8147d03
; github.com:22 SSH-2.0-babeld-57ca1323
github.com IN SSHFP 4 1 e9619e2ed56c2f2a71729db80bacc2ce9ccce8d4
github.com IN SSHFP 4 2 f83898df0bef57a4ee24985ba598ac17fccb0c0d333cc4af1dd92be14bc23aa5
; github.com:22 SSH-2.0-babeld-57ca1323
}}

SSH フィンガープリントは一般的には公開鍵の SHA256 ハッシュ値を base64 エンコードしたものですが、SSHFP レコードは鍵のフィンガープリントを16進数で保存します。そのため、通常 SHA256 でフィンガープリントを記録している known_hosts ファイルやその他の文書にある値と比べるために、レコードを base64 の形式に変換する必要があります。

$ echo "SSHFP-fingerprint" | xxd -r -p | base64

鍵タイプ ed25519 の SHA256 フィンガープリントに16進数を使用している github.com の例です。

{{hc|$ echo "f83898df0bef57a4ee24985ba598ac17fccb0c0d333cc4af1dd92be14bc23aa5" {{!}} xxd -r -p {{!}} base64|2=
+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU=
}}

known_hosts エントリと比べるには:

$ ssh-keygen -l -f ~/.ssh/known_hosts

===== DNS から手動で SSHFP レコードを取得する =====

$ dig SSHFP targetdomain.tld +short


== ヒントとテクニック ==
== ヒントとテクニック ==


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


暗号化トンネルは、安全でない様々なワイヤレス接続を使用するノートパソコンユーザにとって有用です。必要なのは SSH サーバーが安全な場所 (家や仕事場など) で動作していることだけです。[https://dyn.com/dns/ DynDNS] などのダイナミック DNS サービスを利用すれば IP アドレスを覚える必要もありません。
==== 手順 1: 接続の開始 ====

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

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


パスワードを入力すると接続が行われます。{{Ic|N}} フラグはインタラクティブプロンプトを無効化し、{{Ic|D}} フラグは listen するローカルポートを指定します (ポート番号は何でもかまいません)。{{Ic|T}} フラグは疑似 tty アロケーションを無効化します。
verbose ({{Ic|-v}}) フラグを追加することで、接続が成功していることを出力から確認することができます。


verbose ({{Ic|-v}}) フラグを追加することで、接続が成功しているか確認することができます。
==== 手順 2: ブラウザ (やその他のプログラム) の設定 ====
新しく作成した socks トンネルを使用するようにウェブブラウザ (や他のプログラム) を設定しないと上記の作業は無意味です。最新バージョンの SSH は SOCKS4 と SOCKS5 に対応しているため、どちらかを使うことができます。


==== ブラウザ (或いはその他のプログラム) の設定 ====
* Firefox の場合: ''編集 &rarr; 設定 &rarr; 詳細 &rarr; ネットワーク &rarr; 接続 &rarr; 接続設定'':
: ラジオボタンの''手動でプロキシを設定する''にチェックを入れて、''SOCKS ホスト''テキストフィールドに {{ic|localhost}} と、次のテキストフィールドにポート番号を入力してください (上の例では {{ic|4711}})。


上記の手順はウェブブラウザや他のプログラムと組み合わせた場合にのみ有用です。SSH は SOCKS v4 と SOCKS v5 の両方をサポートしているので、どちらかを使用できます。
Firefox はデフォルトでは DNS リクエストの作成に socks トンネルを使用しません。以下の手順で設定することでプライバシーを守ることができます:

* Firefox の場合:
# ''設定 > 一般 > ネットワーク設定'' を開き、''接続設定...'' をクリックします。
# 新しくウィンドウが開くので、''手動でプロキシーを設定する'' オプションにチェックを入れ、''SOCKS ホスト'' 欄には {{ic|localhost}} と、''ポート'' 欄にはポート番号 (上記の例では {{ic|4711}}) を入力します。
# Firefox を再起動します。
:{{Note|Firefox は自動的に SOCKS トンネル経由で DNS リクエストを発行しません。''SOCKS vN を使用するときは DNS もプロキシーを使用する'' (v4 か v5) にチェックを入れることでこの問題を回避できます。}}
* Chromium の場合:
# SOCKS の設定は環境変数かコマンドラインオプションで設定できます。例えば、以下の関数のどちらかを {{ic|.bashrc}} に追加することで可能です:
: {{bc|<nowiki>
secure_chromium() {
local port=4711
export SOCKS_SERVER=localhost:$port
export SOCKS_VERSION=5
(chromium > /dev/null 2>&1 &)
}

secure_chromium() {
local port=4711
(chromium --proxy-server="socks://localhost:$port" > /dev/null 2>&1 &)
}
</nowiki>}}
# ターミナルを開き {{bc|$ secure_chromium}} と実行します。


==== ローカルの TUN インターフェイスをセットアップする ====
# Firefox のロケーションバーに about:config と入力。
# network.proxy.socks_remote_dns を検索。
# 値を true に設定。
# ブラウザを再起動。


これは最初はより複雑ですが、SOCKS プロキシを使わせたいアプリケーション全てを手動で設定する必要はありません。ローカルの TUN インターフェイスをセットアップし、このインターフェイス経由でトラフィックをルーティングさせる必要があります。
* Chromium の場合: 環境変数やコマンドラインオプションで SOCKS の設定ができます。以下の関数を {{ic|.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
}


[[VPN over SSH#badvpn とトンネルインターフェイスをセットアップする]] を見てください。
ターミナルから以下のように実行してください:
$ secure_chromium


=== X11 フォワーディング ===
=== X11 フォワーディング ===


X11 フォワーディングはリモートシステムで X11 プログラムを動作させて、グラフィカルインターフェイスをローカルのクライアントマシンで表示させるメカニズムです。X11 フォワーディングではリモートホストに X11 システムを完全にインストールさせる必要はなく、''xauth'' をインストールするだけで十分です。''xauth'' は、X11 セッションの認証を行うために必要なサーバーとクライアントによって使用される {{ic|Xauthority}} の設定を管理するユーティリティです ([http://xmodulo.com/2012/11/how-to-enable-x11-forwarding-using-ssh.html ソース])。
X11 フォワーディングはリモートシステムで X11 プログラムを動作させて、グラフィカルインターフェイスをローカルのクライアントマシンで表示させるメカニズムです。X11 フォワーディングではリモートホストに X11 システムを完全にインストールさせる必要はなく、''xauth'' をインストールするだけで十分です。''xauth'' は、X11 セッションの認証を行うために必要なサーバーとクライアントによって使用される {{ic|Xauthority}} の設定を管理するユーティリティです ([http://xmodulo.com/2012/11/how-to-enable-x11-forwarding-using-ssh.html ソース])。


{{Warning|X11 フォワーディングにはセキュリティ的に重要な問題があります。{{ic|ssh}}, {{ic|sshd_config}}, {{ic|ssh_config}} のマニュアルページの該当するセクションを読んで最低限の知識をつけてください。[https://security.stackexchange.com/questions/14815/security-concerns-with-x11-forwarding こちら記事] も参照。}}
{{Warning|X11 フォワーディングにはセキュリティ的に重要な問題があります。{{ic|ssh}}{{ic|sshd_config}}、そして {{ic|ssh_config}} のマニュアルページの該当するセクションを読んで最低限の知識をつけてください。[https://security.stackexchange.com/questions/14815/security-concerns-with-x11-forwarding この StackExchange の質問] も参照。}}


==== セットアップ ====
==== セットアップ ====
223行目: 399行目:
===== リモート側 =====
===== リモート側 =====


*[[公式リポジトリ]]から {{Pkg|xorg-xauth}} と {{Pkg|xorg-xhost}} を[[インストール]]
* {{Pkg|xorg-xauth}} パッケージを[[インストール]]してください
*{{ic|/etc/ssh/ssh'''d'''_config}} 内:
* {{ic|/etc/ssh/ssh'''d'''_config}} 内:
** {{ic|X11Forwarding}} を ''yes'' に設定してください
**{{ic|AllowTcpForwarding}} と {{ic|X11UseLocalhost}} オプションを ''yes'' に設定し、{{ic|X11DisplayOffset}} を ''10'' に設定 (何も変更を加えてなければこの値がデフォルトになっています、{{ic|man sshd_config}} を参照)
** {{ic|AllowTcpForwarding}} と {{ic|X11UseLocalhost}} オプションが ''yes'' に設定されおり、{{ic|X11DisplayOffset}} が ''10'' に設定されていることを確認してください (これらの設定は、何も変更していなければ、デフォルト値です。{{man|5|sshd_config}} を参照)。
**{{ic|X11Forwarding}} を ''yes'' に設定
* [[#sshd デーモンの管理|''sshd'' デーモン]]を[[Systemd#ユニットを使う|再起動]]
* そして、[[#デーモンの管理|''sshd'' デーモン]]を再起動してください。


===== クライアント側 =====
===== クライアント側 =====


* {{Pkg|xorg-xauth}} パッケージを[[インストール]]してください。
クライアント側では、接続するたびにコマンドラインで {{ic|-X}} スイッチを指定して {{ic|ForwardX11}} オプションを有効にするか、[[#クライアント|openSSH クライアントの設定ファイル]]で {{ic|ForwardX11}} を ''yes'' に設定してください。
* コマンドラインで日和見的な接続を行うための {{ic|-X}} スイッチを指定するか、或いは[[#設定|クライアントの設定]]で {{ic|ForwardX11}} を ''yes'' に設定して、{{ic|ForwardX11}} オプションを有効化してください。


{{Tip|GUI の描画がおかしい場合やエラーが表示されるときは {{ic|ForwardX11Trusted}} オプションを有効にできます (コマンドラインでは {{ic|-Y}} スイッチ)。X11 フォワーディングが [https://www.x.org/wiki/Development/Documentation/Security/ X11 SECURITY 拡張] の制御から外れるようになります。使用するときはセクション冒頭の[[#X11 フォワーディング|警告]]を読んでください。}}
{{Tip|GUI の描画がおかしい場合やエラーが表示されるときは {{ic|ForwardX11Trusted}} オプションを有効にできます (コマンドラインでは {{ic|-Y}} スイッチ)。X11 フォワーディングが [https://www.x.org/wiki/Development/Documentation/Security/ X11 SECURITY 拡張] の制御から外れるようになります。使用するときはセクション冒頭の[[#X11 フォワーディング|警告]]を読んでください。}}
237行目: 414行目:
==== 使用方法 ====
==== 使用方法 ====


通常通り[[#サーバーに接続する|リモートマシンにログ]]ます、クライアントの設定ファイルで ''ForwardX11'' 有効にしていない場合は {{ic|-X}} スイッチを指定します:
通常通りリモートマシンにログンしてください。クライアントの設定ファイルで ''ForwardX11'' 有効化されていない場合は {{ic|-X}} スイッチを指定してください:

$ ssh -X ''user@host''
$ ssh -X ''user@host''

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

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


{{ic|X11 forwarding request failed}} と出力される場合、リモートマシンでセットアップをやり直してください。X11 フォワーディングのリクエストが成功したら、リモートサーバ上の任意の X プログラムを実行でき、プログラムがローカルセッションにフォワーディングされます:
"Cannot open display" エラーが表示される場合、root 以外のユーザーで以下のコマンドを実行してみてください:
$ xhost +


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

$ xhost +hostname
{{ic|Can't open display}} という内容が含まれるエラーが出力される場合は、{{ic|DISPLAY}} が適切に設定されていないことを意味します。


一部のアプリケーションは、実行中のインスタンスのチェックをローカルのマシンで行うため、注意してください。[[Firefox]] がその例です: すでに実行中の Firefox を閉じるか、以下の起動パラメータを使用してリモートインスタンスをローカルマシン上で起動してください:
hostname は転送先のホストの名前に置き換えてください。詳しくは {{ic|man xhost}} を参照。


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


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


* サーバの {{ic|ssh'''d'''_config}} で {{ic|AddressFamily any}} オプションを有効にする。
* ''サーバ''の {{ic|ssh'''d'''_config}} で {{ic|AddressFamily any}} オプションを有効にする。
* サーバの {{ic|ssh'''d'''_config}} で {{ic|AddressFamily}} オプションを inet に設定する。
* 或いは、''サーバ''の {{ic|ssh'''d'''_config}} で {{ic|AddressFamily}} オプションを inet に設定する。
IPv4 で Ubuntu クライアントを使っている場合は inet に設定することで問題が解決ます。
IPv4 で Ubuntu クライアントを使っている場合は inet に設定することで問題が解決する場合があります。


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

{{Tip|{{ic|X11 Forwarding}} の問題をトラブルシューティングする有用なリンクをいくつか挙げます: [https://unix.stackexchange.com/a/12772]、[https://unix.stackexchange.com/a/46748]、[https://superuser.com/a/805060]。}}


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


SSH の X11 の組み込みサポートに加えて、SSH には任意の TCP 接続をセキュアにトンネル化することもできます。ローカルフォワーディングとリモートフォワーディングの両方が使えます。
ローカルフォワーディングはローカルマシンのポートを開いて、リモートホストに接続が転送されます。転送先をリモートホストと同じにすることで、同一マシンでセキュアな VNC 接続などができます。ローカルフォワーディングは {{Ic|-L}} スイッチで利用することができ {{Ic|<tunnel port>:<destination address>:<destination port>}} という形式で転送先を指定します:

ローカルフォワーディングはローカルマシンのポートを開き、ローカルマシンに対する接続はリモートホストにフォワーディングされ、リモートホストから指定された宛先に転送されます。転送先をリモートホストと同じにすることで、同一マシンに対してセキュアシェルやセキュアな [[VNC]] 接続を提供します。ローカルフォワーディングは {{Ic|-L}} スイッチで利用することができ {{Ic|<トンネルポート>:<宛先アドレス>:<宛先ポート>}} という形式で転送先を指定します。

ゆえに:


$ ssh -L 1000:mail.google.com:25 192.168.0.100
$ 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 の間は安全に運ばれます。
上記のコマンドは SSH で {{ic|192.168.0.100}} にログインしてシェルを開きローカルマシンの TCP ポート 1000 から mail.google.com のポート 25 へのトンネルが作成されます。接続が確立すると {{ic|localhost:1000}} への通信は Gmail の SMTP ポートに接続されます。Google から見ると、{{ic|192.168.0.100}} から接続が来ているように見えます (必ずしも接続と一緒にデータが運ばれるとは限りません)。データはローカルマシンと {{ic|192.168.0.100}} の間でセキュアに運ばれますが、{{ic|192.168.0.100}} と Google との間はセキュアではありません (他の方法を取らない限り)


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


$ ssh -L 2000:192.168.0.100:6001 192.168.0.100
$ ssh -L 2000:192.168.0.100:6001 192.168.0.100


このコマンドは、{{ic|localhost:2000}} に接続することができ、リモートホストのポート 6001 へ透過的に送信されます。前者の例は、vncserver ユーティリティ ([[tightvnc]] パッケージの一部) を使用して VNC 接続を行う際に便利です。便利とはいえ、セキュリティの問題があります。
前者の例はセキュリティ上問題がある ({{AUR|tightvnc}} パッケージに含まれている) vncserver ユーティリティによる VNC 接続などで有用です。


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


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


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

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


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


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


$ ssh -A -t -l user1 bastion1 \
$ ssh -A -t -l user1 bastion1 \
294行目: 478行目:
ssh -A -t -l user3 target
ssh -A -t -l user3 target


以下のように {{ic|-J}} フラグを使することできます:
ProxyCommand オプションを使えばこれを自動化することできます:

$ ssh -o ProxyCommand="ssh -W %h:%p bastion.example.org" targetserver.example.org

{{ic|-J}} フラグで ProxyJump オプションを使用すれば、これをより簡単かつセキュアに行うことができます:


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


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

ProxyCommand オプションと ProxyJump オプションの主な違いは、後者は踏み台ホスト上のシェルを必要としないところにあります。その結果、ユーザのログイン認証情報への踏み台サーバでのアクセスや SSH エージェントフォワーディングが必要なくなります。ProxyJump オプションでは、ssh クライアントは踏み台サーバを通して直接ターゲットのサーバへ接続し、エンドツーエンドの暗号化されたチャネルをクライアントとターゲットサーバとの間で確立します。

設定ファイルにも、{{ic|-J}} フラグと等価なものとして {{ic|ProxyJump}} オプションがあります。詳細は {{man|5|ssh_config}} を見てください。

=== リレーを介したリバース SSH ===

アイデアとしては、クライアントは別のリレーを使ってサーバに接続し、サーバはリバース SSH トンネルを使って同じリレーに接続します。これは、サーバが NAT 内にあり、リレーが、ユーザがアクセス可能なプロキシとして使用されている、パブリックにアクセス可能な SSH サーバである場合に便利です。ゆえに、クライアントの鍵がリレーとサーバの両方に対して認可されていることが前提条件であり、サーバはリレーに対してもリバース SSH 接続に対しても認可されている必要があります。

以下の設定例では、{{ic|''user1''}} がクライアント上で使用されているユーザアカウントであり、{{ic|''user2''}} は relay 上のアカウント、{{ic|''user3''}} がサーバー上のアカウントであるとします。まず、以下のコマンドでサーバとリバーストンネルとの接続が確立している必要があります (2222番ポートを使うものとします):

$ ssh -R 2222:localhost:22 -N ''user2''@''relay''

これは、スタートアップスクリプトや systemd サービス、[[#Autossh - SSH セッションとトンネルの自動再起動|autossh]]、{{AUR|sidedoor}} を使って自動化することもできます。

クライアント側では、以下のコマンドで接続を確立させます:

$ ssh -t ''user2''@''relay'' ssh ''user3''@localhost -p 2222

{{Note|{{ic|ssh ''user3''@''relay'' -p 2222}} では、リレーサーバーのファイアウォールで対象のポートを開いておくとともに、他のアドレスからこのポートへの接続を許可しておく必要があります。}}

リバーストンネルとの接続を確立させるためのリモートのコマンドは、relay の {{ic|authorized_keys}} に以下のような {{ic|command}} フィールドを含めることで、定義できます:

{{hc|~/.ssh/authorized_keys|2=command="ssh ''user3''@localhost -p 2222" ''ssh-ed25519'' ''KEY2'' ''user1''@''client''}}

この場合、接続は以下のコマンドで確立できます:

$ ssh ''user2''@''relay''

または、{{ic|RemoteCommand}} と {{ic|RequestTTY}} を指定するエントリを ssh の設定に追加することもできます:

{{hc|~/.ssh/config|
Host ''jump-destination''
Hostname ''relay''
User ''user2''
RemoteCommand ssh ''user3''@localhost -p 2222
RequestTTY yes
}}

この場合、以下のように簡単にできます:

$ ssh ''jump-destination''

{{Note|クライアント側のターミナルでの SCP の自動補完機能は機能しません。一部の構成では、SCP の転送機能自体も機能しません。}}


=== マルチプレクス ===
=== マルチプレクス ===


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


{{hc|/etc/ssh/sshd_config|
{{hc|/etc/ssh/sshd_config|
309行目: 541行目:
}}
}}


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


=== SSH の高速化 ===
=== SSH の高速化 ===


接続をグローバル及び特定のホストに対して高速化させることのできる[[#設定|クライアント設定]]がいくつかあります。これらのオプションに関する完全な説明は {{man|5|ssh_config}} を参照してください。
{{Tip|SSH を SFTP や SCP で使用する場合、{{AUR|openssh-hpn-git}} をインストールすることで転送速度を劇的に上げることができます [https://www.psc.edu/index.php/hpn-ssh]。}}


* ''より高速な暗号を使う'': AESNI 命令セットを持つ最近の CPU では、{{ic|aes128-gcm@openssh.com}} や {{ic|aes256-gcm@openssh.com}} を使うことで openssh のデフォルトの優先暗号 (通常 {{ic|chacha20-poly1305@openssh.com}}) よりも劇的に優れたパフォーマンスを得られるはずです。暗号は {{ic|-c}} フラグで選択できます。永続的に設定するには、{{ic|~/.ssh/config}} 内に {{ic|Ciphers}} オプションを追加し、暗号を優先順に並べて設定してください (例: {{bc|Ciphers aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr}})。
同一のホストのセッションは全て単一の接続を使うようにすることで、後のログインを劇的に高速化することができます。{{ic|/etc/ssh/ssh_config}} や {{ic|$HOME/.ssh/config}} の適当なホストの下に以下の行を追加してください:
ControlMaster auto
ControlPersist yes
ControlPath ~/.ssh/sockets/socket-%r@%h:%p


* ''圧縮を有効化あるいは無効化する'': 圧縮は低速な接続において速度を向上させることができます。{{ic|Compression yes}} オプションか {{ic|-C}} フラグで有効化できます。しかし、使用される圧縮アルゴリズムは比較的低速な {{man|1|gzip}} であり、高速なネットワークにおいてはボトルネックになってしまいます。接続を高速化させるために、ローカルネットワークや高速なネットワークにおいては {{ic|Compression no}} を使うべきでしょう。
{{ic|~/.ssh/sockets}} は他のユーザーが書き込めないディレクトリなら何でもかまいません。


* ''接続共有'': 以下のオプションを使用することで、同一ホストに対するセッションをすべて単一の接続に共有させることができます:{{bc|<nowiki>
{{ic|ControlPersist}} はクライアントとの接続を閉じるまでにどれくらい待機するか指定します。{{ic|yes}} で永遠に待ち続け、{{ic|no}} で接続を即座に終了します。秒数で指定することもできます。
ControlMaster auto
ControlPersist yes
ControlPath ~/.ssh/sockets/socket-%r@%h:%p
</nowiki>}}
: {{ic|~/.ssh/sockets}} の部分は、他のユーザによって書き込むことができないのであれば、どのディレクトリでも構いません。


* {{ic|ControlPersist}} は、初回のクライアント接続が閉じられてから、新しいクライアントのためにマスターがどれくらいバックグラウンドで待機すべきかを指定します。利用可能な値は:
{{Warning|{{ic|ControlPersist}} を {{ic|yes}} に設定すると接続が自動的に終了しなくなるので注意してください。}}
** {{ic|no}}: 最後のクライアントが切断されたらすぐに接続を閉じます。
** 秒単位の時間
** {{ic|yes}}: 永遠に待ちます。接続は自動的に閉じられなくなります。


速度を向上させる別のオプションとして圧縮を有効化する {{ic|-C}} フラグがあります。{{ic|/etc/ssh/ssh_config}} の適切なホストの下に次の行追加することで永続的設定することができます:
* {{ic|AddressFamily inet}} オプション {{ic|-4}} フラグを使用して IPv6 ルックアップバイパスすることで、ログイン要する時間を短くすることができます
Compression yes


* 最後に、SSH を SFTP や SCP のために使用するつもりであれば、[https://www.psc.edu/index.php/hpn-ssh High Performance SSH/SCP] は、SSH バッファサイズを動的に大きくすることで、スループットを劇的に増やすことができます。この改善のパッチが施されたバージョンの OpenSSH である {{AUR|openssh-hpn}} パッケージをインストールしてください。
{{Warning|{{man|1|ssh}} には「モデム接続など接続速度が遅い場合は圧縮の効果がありますが、高速なネットワークではむしろ通信が遅くなります」と書かれています。ネットワーク環境によっては圧縮は逆効果です。}}

ログイン時刻は {{ic|AddressFamily inet}} オプションや {{ic|-4}} フラグを使って IPv6 ルックアップを迂回することで短くできます。


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


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

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


デフォルトでは、SSH セッションが一定時間アイドルであった場合、自動的にログアウトします。一定時間データが受信されなかった場合にサーバにキープアライブシグナルを送信することで、セッションを開いたままにすることができます。あるいは対照的に、クライアントからデータが送られてこない場合にサーバが定期的にメッセージを送信することもできます。
ServerAliveInterval 120


* '''サーバ'''側: {{ic|ClientAliveInterval}} はタイムアウトを秒単位で設定します。クライアントからデータが受信されずにその時間経過すると、''sshd'' が応答を促すリクエストを送信します。デフォルトは0であり、メッセージは送信されません。例えば、60秒毎にクライアントに対して応答を要求するには、[[#設定_2|サーバ側の設定]]で {{ic|ClientAliveInterval 60}} オプションを設定してください。{{ic|ClientAliveCountMax}} と {{ic|TCPKeepAlive}} オプションも参照してください。
これで120秒ごとに "keep alive" シグナルがサーバーに送信されます。{{ic|ServerAliveCountMax}} や {{ic|TCPKeepAlive}} オプションも参照してください。
* '''クライアント'''側: {{ic|ServerAliveInterval}} は、クライアントからサーバに向けて送信されるリクエストの時間間隔を設定します。例えば、120秒毎にサーバに対して応答を要求するには、[[#設定|クライアント側の設定]]で {{ic|ServerAliveInterval 120}} オプションを追加してください。{{ic|ServerAliveCountMax}} と {{ic|TCPKeepAlive}} オプションも参照してください。


{{Note|セッションを開いたままにするためにキープアライブリクエストを送信する必要があるのは、クライアントかサーバの一方のみです。サーバとクライアントの両方を制御できるならば、セッションを永続的にする必要のあるクライアントに対してのみ {{ic|ServerAliveInterval}} を正の値に設定し、その他のクライアントやサーバはデフォルトの設定するのが妥当な選択です。}}
反対に、外部からの接続を維持するには、次をサーバーの {{ic|/etc/ssh/sshd_config}} に設定します (数字は0より大きく):
ClientAliveInterval 120


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


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


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


{{hc|~/.config/systemd/user/tunnel.service|<nowiki>
{{hc|~/.config/systemd/user/tunnel.service|<nowiki>
364行目: 597行目:
</nowiki>}}
</nowiki>}}


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


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

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


使用例:
使用例:

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

[[sshfs]] を組み合わせる:
[[SSHFS]] と組み合わせる:

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

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

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

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


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


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

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


399行目: 640行目:
設定後はサービスを[[起動]]・[[有効化]]してください。
設定後はサービスを[[起動]]・[[有効化]]してください。


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


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


=== SSH デーモンが失敗した場合の代替サービス ===
== ソケットアクティベーションで SSH ポート番号を変更する (sshd.socket) ==


SSH のみに依存するリモート或いはヘッドレスのサーバにおいて、(システムアップグレード後などに) SSH デーモンの起動に失敗すると、管理アクセスできなくなってしまう場合があります。[[systemd]] は、{{ic|OnFailure}} によるシンプルなソリューションを提供しています。
次の内容で {{ic|/etc/systemd/system/sshd.socket.d/port.conf}} ファイルを作成:


サーバ上で {{ic|sshd}} が実行されていて、[[telnet]] がフェイルセーフであるとしてます。以下のようにファイルを作成してください。ただし、{{ic|telnet.socket}} は[[有効化]]'''しないでください'''!
[Socket]
# Disable default port
ListenStream=
# Set new port
ListenStream=12345


{{hc|/etc/systemd/system/sshd.service.d/override.conf|2=
リロードすれば systemd は自動的に新しいポートを開きます:
[Unit]
OnFailure=telnet.socket
}}


これだけです。{{ic|sshd}} が実行中である場合、Telnet は実行されません。{{ic|sshd}} が起動に失敗した場合、telnet セッションがリカバリとして開かれます。
systemctl daemon-reload

=== ホストに基づいてターミナル背景色を設定する ===

異なるホストに接続していることを簡単に判別できるようにするために、[https://bryangilbert.com/post/etc/term/dynamic-ssh-terminal-background-colors/ ホストの種類に応じて異なる背景色]を設定することができます。

このソリューションは一般には適用できません (ZSH 限定)。

=== ネットワーク固有の設定 ===

{{ic|Match exec}} を使うことで、接続先のネットワークに固有のホスト設定を使用することができます。

例えば、{{man|1|nmcli}} を使用していて、接続が検索ドメインを使用するように (手動、あるいは DHCP で) 設定されている場合:

{{hc|head=~/.ssh/config|output=
Match exec "nmcli {{!}} grep domains: {{!}} grep example.com"
CanonicalDomains example.com
# Should you use a different username on this network
#User username
# Use a different known_hosts file (for private network or synchronisation)
#UserKnownHostsFile <network>_known_hosts
}}

{{ic|Match host ... exec "..."}} の例: VPN に接続していない限り、{{ic|internal.example.com}} への接続に ({{ic|ProxyJump}} を用いた) 踏み台/プロキシが必要であるとしましょう。フラグメント {{ic|!exec "host internal.example.com"}} は、{{ic|internal.example.com}} が DNS を介して見つけられない場合にのみ、適用されます。様々な代替案が [https://serverfault.com/q/536043/117525] で議論されています。

{{hc|head=~/.ssh/config|output=
Match host internal.example.com !exec "host internal.example.com"
ProxyJump bastion.example.com
Host internal.example.com
User foobar
}}

=== プライベートネットワークのホスト鍵検証 ===

あるネットワーク上のサーバとそれとは別のネットワーク上のサーバは、互いに同じプライベート IP アドレスを持つ可能性があるため、それらのサーバは異なる方法で処理する必要があるかもしれません。

{{Accuracy|「最適な」ソリューションに、本番環境では別のものを使うべきという警告があるはずがない。}}

最適なソリューションは、[[#ネットワーク固有の設定]] を使用し、接続しているネットワークに応じて異なる {{ic|UserKnownHostsFile}} を使うことです。2つめのソリューションは、プライベートネットワークのホスト鍵を単に無視することです (新しい/プロトタイプのネットワークで作業する際にデフォルトで使用するのが最適です):

{{hc|head=~/.ssh/config|output=
Host 10.* 192.168.*.* 172.31.* 172.30.* 172.2?.* 172.1?.*
# Disable HostKey verification
# Trust HostKey automatically
StrictHostKeyChecking no
# Do not save the HostKey
UserKnownHostsFile=/dev/null
# Do not display: "Warning: Permanently Added ..."
LogLevel Error
}}

{{Accuracy|{{ic|known_hosts}} ファイルは、サーバにアクセスするためにホスト名を使用したとしても、IP アドレスを記録します。}}

{{Warning|本番環境では、ホスト名を使用してホストにアクセスしたり、ネットワーク固有の known_hosts ファイルを使用するようにしてください。}}

=== ログイン時にコマンドを実行 ===

インタラクティブセッションを使用している場合、ログイン時にコマンドを実行する方法は複数存在します:

* リモートホスト上の {{ic|authorized_keys}} ファイルを使用する ({{man|8|sshd|AUTHORIZED_KEYS FILE FORMAT}} を参照)
* サーバで {{ic|PermitUserRC}} オプションが有効化されている場合、リモートホスト上の {{ic|~/.ssh/rc}} を使用する
* リモートホスト上のシェル設定ファイルを使用する (例: {{ic|.bashrc}})

=== エージェントフォワーディング ===

SSH エージェントのフォワーディングにより、サーバに接続している状態でローカルの鍵を使用することができます。選択したホストのみに対してエージェントフォワーディングを許可することが[https://security.stackexchange.com/questions/7480/risks-of-ssh-to-an-untrusted-host#7504 推奨]されます。

{{hc|~/.ssh/config|
Host ''myserver.com''
ForwardAgent yes
}}

次に、[[SSH エージェント]]を構成し、''ssh-add'' を使ってローカル鍵を追加してください。

これで、リモートサーバに接続する場合、あなたのローカル鍵を使用して他のサービスに接続できるようになりました。

=== 新しい鍵の生成 ===

新しいサーバの秘密鍵は以下で生成できます:

# すべての鍵を削除する。例えば: {{bc|# rm /etc/ssh/ssh_host_*_key*}}
# {{ic|sshdgenkeys.service}} を[[再起動]]するか、{{ic|ssh-keygen -A}} を root として実行する。

=== sshd を非特権ユーザとして実行 ===

{{ic|sshd}} をコンテナ内で (或いはテスト目的などで) 非特権ユーザとして実行したい場合もあるでしょう。

非特権ユーザは {{ic|/etc/ssh}} 内のホスト鍵を読むことができないため、新しいホスト鍵を生成しなければなりません:

$ ssh-keygen -q -N "" -t rsa -b 4096 -f ''/path/to/host/keys/ssh_host_rsa_key''
$ ssh-keygen -q -N "" -t ecdsa -f ''/path/to/host/keys/ssh_host_ecdsa_key''
$ ssh-keygen -q -N "" -t ed25519 -f ''/path/to/host/keys/ssh_host_ed25519_key''

{{ic|sshd_config}} を作成してください。以下の例では、1024 より大きい値のポート番号を使用し、ホスト鍵への新しいパスを提供し、PAM を無効化します:

{{hc|''/path/to/sshd_config''|
Port 2022
HostKey ''/path/to/host/keys/ssh_host_rsa_key''
HostKey ''/path/to/host/keys/ssh_host_ecdsa_key''
HostKey ''/path/to/host/keys/ssh/ssh_host_ed25519_key''
UsePAM no
}}

新しく作成した設定で ''sshd'' を実行します。{{ic|-D}} フラグはデーモンモードを無効化し、{{ic|-e}} は出力を標準エラー出力にリダイレクトしてモニタしやすくします:

$ sshd -f ''/path/to/sshd_config'' -D -e


== トラブルシューティング ==
== トラブルシューティング ==

=== チェックリスト ===
=== チェックリスト ===


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


# 設定ディレクトリ {{ic|~/.ssh}} の中身がユーザーからアクセスでことを確認 (クライアントとサーバの両方で確認してください): {{bc|<nowiki>
# 設定ディレクトリ {{ic|~/.ssh}} のコンテンツ対象ユーザによってのみアクセス可能必要があります (クライアントとサーバの両方で確認してください)。かつ、対象ユーザのホームディレクトリがそのユーザによってのみ書き込み可能である必要があります: {{bc|<nowiki>
$ chmod go-w ~
$ chmod 700 ~/.ssh
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/*
$ chmod 600 ~/.ssh/*
$ chown -R $USER ~/.ssh
$ chown -R $USER ~/.ssh
</nowiki>}}
</nowiki>}}
# クライアントの公開鍵 (例: {{ic|id_rsa.pub}}) がサーバの {{ic|~/.ssh/authorized_keys}} に存在することを確認する。
# クライアントの公開鍵 (例: {{ic|id_ed25519.pub}}) がサーバの {{ic|~/.ssh/authorized_keys}} 記述されていることを確認する。
# [[#デーモン|サーバの設定]] {{ic|AllowUsers}} や {{ic|AllowGroups}} によって SSH によるアクセスが制限されていことを確認する。
# [[#設定_2|サーバの設定]] {{ic|AllowUsers}} や {{ic|AllowGroups}} によって SSH アクセスが制限されていないことを確認する。
# ユーザーにパスワード設定されていることを確認する。新しいユーザーにはパスワードが設定されていない可能性があります。
# ユーザパスワード設定ているを確認する。サーバにログインしたことのない新しいユーザはパスワードを持っていないことがあります。
# {{ic|/etc/ssh/sshd_config}} に {{ic|LogLevel DEBUG}} を[[追加]]してみる。
# {{ic|sshd}} を再起動してクライアントとサーバーの両方で一度ログアウトをしてみる。
# {{ic|journalctl -xe}} を root として実行して、(エラー) メッセージの取得を試みる。
# {{ic|sshd}} を[[再起動]]し、クライアントとサーバの両方でログアウト/ログインする。


=== 接続拒否されるまたはタイムアウトする ===
=== 接続拒否タイムアウトの問題 ===


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


NAT モードやルータを使っている場合、ルータが ssh 接続を転送していないか確認してください。サーバの内部 IP アドレスは {{ic|$ ip addr}} で確認することができるので、SSH ポートの TCP をその IP に転送するようにルータを設定してください。[http://portforward.com portforward.com] 役に立ちます。
NAT モードやルータを使っている場合 (VPS を使っていたりパブリックにアドレッシングされたホストを使用していない限り、あり得ます)、ルータが ssh の着信接続をマシンにフォワーディングしていることを確認してください。{{ic|ip addr}} を使ってサーバの内部 IP アドレスを見つけ、SSH ポートの TCP 接続をその IP にフォワーディングするようにルータを設定してください。[https://portforward.com portforward.com] 役に立ちます。


==== SSH が動作しているか? ====
==== SSH が動作していて、リッスンしているか? ====
$ ss -tnlp


[[ss]] ユーティリティは、以下のコマンドラインを使うことで、TCP ポートをリッスンしている全プロセスを表示します:
上記のコマンドで SSH ポートが開いていると表示されない場合、SSH は動作していません。{{ic|/var/log/messages}} にエラーがないか確認してください。

$ ss --tcp --listening

このコマンドの出力を見て、システムが {{ic|ssh}} ポートをリッスンしていないことが判明した場合、SSH が実行されていないことを意味します。[[Journal]] でエラーなどが出力されていないか確認してください。


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


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

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


463行目: 816行目:


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

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


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


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

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


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


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

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


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


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


===== 問題診断 =====
===== 問題診断 =====

{{Pkg|tcpdump}} または {{Pkg|wireshark-cli}} パッケージの Wireshark を[[インストール]]してください。
{{Pkg|tcpdump}} または {{Pkg|wireshark-cli}} パッケージで Wireshark を[[インストール]]してください。


tcpdump の場合:
tcpdump の場合:

# tcpdump -ni ''interface'' "port 22"
# tcpdump -ni ''interface'' "port 22"


Wireshark の場合:
Wireshark の場合:

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


491行目: 850行目:


===== 解決方法 =====
===== 解決方法 =====

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


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


{{ic|sshd.service}} サーバを[[再起動]]すれば、あともう少しです。次に、デフォルトのポートではなくもう一つのポートを使用するようにクライアントを設定しなければなりません。その問題に対するソリューションは数多く存在しますが、ここではそれらのうち2つを扱っています。
あとは {{ic|systemctl restart sshd.service}} で sshd を起動するだけです。そして ssh クライアントでも同じポートに変更します。


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


最近のバージョンの OpenSSH は時々、古い ssh サーバに接続する際に上記のエラーメッセージで失敗することがあります。これは、そのホストに対する様々な[[#設定|クライアントオプション]]を設定することにより、回避可能です。以下のオプションに関する詳細は {{man|5|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


{{ic|ecdsa-sha2-nistp*-cert-v01@openssh}} 楕円曲線ホスト鍵アルゴリズムが原因である可能性があります。このようなアルゴリズムは、{{ic|HostKeyAlgorithms}} にそれらのアルゴリズムを除いたリストを設定することにより、無効化できます。クライアント側では、{{ic|HostKeyAlgorithms}} のリストの前に {{ic|-}} をつけることで、指定したアルゴリズム (ワイルドカードも可) をデフォルトから外すことができます ({{man|5|ssh_config}} を参照)。
openssh 5.9 では、上記の修正方法は働きません。代わりに、{{ic|~/.ssh/config}} に以下の行を記述してください:


実際に使用されているホスト鍵のアルゴリズムは、{{ic|ssh -v ''server_to_connect_to''}} を実行して、{{ic|kex: host key algorithm:}} と書かれてある行を見ればわかります。
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
MACs hmac-md5,hmac-sha1,hmac-ripemd160


これでうまく行かない場合、暗号のリストが長過ぎる可能性があります。{{ic|Ciphers}} オプションのリストを短くしてください (80 文字未満であれば十分でしょう)。同じように、{{ic|MACs}} のリストも短くしてみてください。
openssh バグフォーラムの [http://www.gossamer-threads.com/lists/openssh/dev/51339 議論] も参照。


OpenSSH のバグフォーラムにおける[https://web.archive.org/web/20161201015151/https://www.gossamer-threads.com/lists/openssh/dev/51339 議論]も参照してください。
=== "[your shell]: No such file or directory" / ssh_exchange_identification 問題 ===
シェルのバイナリに {{Ic|$PATH}} が通っている場合でも、特定の SSH クライアントは {{Ic|$SHELL}} に絶対パスを設定する必要があります (パスは {{Ic|whereis -b [your shell]}} で確認できます)。


=== "[シェル]: No such file or directory" / ssh_exchange_identification の問題 ===
==="Terminal unknown" や "Error opening terminal" エラーメッセージ===

ssh でログイン時に "Terminal unknown" のようなエラーが表示されることがあります。これはサーバーがターミナルを認識できていないことを意味します。また、nano などの ncurses アプリケーションを実行すると "Error opening terminal" というメッセージが表示されます。
シェルのバイナリが {{Ic|$PATH}} に登録されているディレクトリ内にあったとしても、特定の SSH クライアントは {{Ic|$SHELL}} に絶対パスを設定する必要があります (パスは {{Ic|whereis -b [あなたのシェル]}} で確認できます)。

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

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


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


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


$ ssh myserver mkdir -p ~/.terminfo/${TERM:0:1}
$ ssh myserver mkdir -p ~/.terminfo/${TERM:0:1}
527行目: 889行目:
サーバーから一度ログアウトしてからログインしなおすと問題が解決しているはずです。
サーバーから一度ログアウトしてからログインしなおすと問題が解決しているはずです。


====$TERM 変数を設定する解決策====
==== TERM ハック ====


{{Note|これは最後の手段にするべきです。}}
{{Warning|この方法はあくまで次善策であり、たまにしか接続しない ssh サーバーで使うようにしてください。}}


{{ic|.bash_profile}} などで {{ic|1=TERM=xterm}} 設定すエラーが表示されなくなり、ncurses アプリケーションが動作するようになります。ただ副作用があり、ターミナルの制御シーケンスが xterm とってる場合グラフィックがおかしくなります。
あるいは、{{ic|1=TERM=xterm}} 環境変数をサーバ側 (例えば {{ic|.bash_profile}} で) 設定してしまうという方法もありまでエラーは出なくなり、ncurses アプリケーションを実行できるようになります。しかし、ターミナルの制御シーケンスが xterm のそれ正確に一致しない限り、奇妙な挙動やグラフィックのバグ発生する場合があります。


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

sshd のログでこのエラーが確認できる場合、HostKey が正しく設定されているか確認してください:
sshd のログでこのエラーが確認できる場合、{{ic|HostKey}} が正しく設定されているか確認してください:
HostKey /etc/ssh/ssh_host_rsa_key

{{hc|/etc/ssh/sshd_config|HostKey /etc/ssh/ssh_host_ed25519_key}}


=== サブシステム要求の失敗 ===
=== サブシステム要求の失敗 ===


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


{{hc|/etc/ssh/sshd_config|
{{hc|/etc/ssh/sshd_config|
547行目: 911行目:
}}
}}


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


OpenSSH 7.0 ではセキュリティ上の理由により DSA 公開鍵が非推奨となっており、OpenSSH 9.8 はデフォルトで DSA 鍵のサポート無しでビルドされています。2025年最初の OpenSSH リリースでは、DSA のサポートが完全になくなる予定です。今のところ、DSA 公開鍵をどうしても使わなくてはならない場合は、{{ic|configure}} に {{ic|--enable-dsa-keys}} フラグを渡して {{Pkg|openssh}} をビルドする必要があります。[https://marc.info/?l=openssh-unix-dev&m=171982945528949&w=2]
OpenSSH 7.0 ではセキュリティ上の理由から ssh-dss が無効になっています。どうしても有効にする必要がある場合、クライアントの設定オプションを使用してください ([http://www.openssh.com/legacy.html] には書かれていない方法です):

PubkeyAcceptedKeyTypes +ssh-dss


=== OpenSSH 7.0 で No matching key exchange method found ===
=== OpenSSH 7.0 で No matching key exchange method found ===


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


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


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


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


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


{{ic|1=KillMode=process}} は古典的な {{ic|ssh.service}} でも役に立つことがあります。サーバーが停止したり再起動したときに SSH セッションプロセスや {{Pkg|screen}} や {{Pkg|tmux}} のプロセスが終了されることを防ぐことができます。
{{ic|1=KillMode=process}} は古典的な {{ic|ssh.service}} でも役に立つことがあります。サーバーが停止したり再起動したときに SSH セッションプロセスや {{Pkg|screen}} や {{Pkg|tmux}} のプロセスが終了されることを防ぐことができます。
574行目: 936行目:
=== Broken pipe ===
=== Broken pipe ===


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

{{bc|debug3: send packet: type 1
{{bc|debug3: send packet: type 1
packet_write_wait: Connection to A.B.C.D port 22: Broken pipe}}
packet_write_wait: Connection to A.B.C.D port 22: Broken pipe
}}
上記の {{ic|send packet}} の行は、応答パケットが受信されなかったことを示しています。つまり、これは ''QoS'' の問題であることがわかります。パケットを落とす可能性を減らすには、{{ic|IPQoS}} を設定してください。
{{hc|/etc/ssh/ssh_config|Host *
IPQoS reliability}}
サービスタイプは {{ic|reliability}} ({{ic|0x04}}) で、{{ic|0x00}} や {{ic|throughput}} ({{ic|0x08}}) と同様に問題を解決できるはずです。


上記の {{ic|send packet}} の行は、応答パケットが受信されなかったことを示しています。つまり、これは ''QoS'' の問題であることがわかります。パケットを落とす可能性を減らすには、{{ic|IPQoS}} を設定してください:
=== 再起動後デーモンの起動が遅い ===


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

サービスタイプ {{ic|reliability}} ({{ic|0x04}}) は、{{ic|0x00}} や {{ic|throughput}} ({{ic|0x08}}) と同様に、このコマンドを解決するはずです。


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


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


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


=== WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! ===
=== WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! ===


クライアントが ssh サーバの鍵が変更された警告た場合、新しく提供された鍵が 本当にサーバオペレータのものであるかどうかを確認する必要があります。{{ic|known_hosts}} ファイルから古い鍵を {{ic|ssh-keygen -R $SSH_HOST}} で削除し、新しい鍵を新しいサーバであかのように受け入れてください。
SSH サーバの鍵が変更されたという警告がクライアントで表示された場合、新しく提供された鍵が本当にサーバオペレータのものであるかどうかを、何らかの信頼された方法 (暗号化されている必要はありません) で確認する必要があります。確認たら、{{ic|known_hosts}} ファイルから古い鍵を {{ic|ssh-keygen -R $SSH_HOST}} で削除し、新しいサーバーに接続すときと同じように鍵を理してください。


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


端末の terminfo エントリがいホストに接続する場合例えば、terminfo エントリが {{Pkg|ncurses}} に同梱されていない端末エミュレータを使用る場合などです。(例えば [[kitty]] [[rxvt-unicode]]) terminfo データベースがれているホスト (例えば OpenWrt が動いているシステム) に接続する場合、{{man|5|terminfo}} に依存しているソフトウェアで様々な問題が発生する可能性があります。
あなたのターミナルの terminfo エントリがいホストに接続する場合 (例えば、{{Pkg|ncurses}} に同梱されていない terminfo ントリのターナルを使用している場合)terminfo データベースが限れているホストに接続する場合 (例えば、[[Wikipedia:ja:OpenWrt|OpenWrt]] を実行しているシステム)、{{man|5|terminfo}} に依存しているソフトウェアで様々な問題が発生ます。


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


OpenSSH 8.7 以降、カスタムの {{ic|TERM}} 環境変数をリモートホストに渡すには、 簡単な設定スニペットを使います。
OpenSSH 8.7 以降、カスタムの {{ic|TERM}} 環境変数をリモートホストに渡すには、簡単な設定スニペットを使用してくださ:


{{hc|~/.ssh/config|2=
{{hc|~/.ssh/config|2=
Host example.com
Host example.com
SendEnv TERM=xterm-256color
SetEnv TERM=xterm-256color
}}
}}

=== 踏み台ホストを介する接続が "bash: No such file or directory" で失敗する ===

(踏み台のサーバで) {{ic|SHELL}} 環境変数に有効な完全パスを設定していない場合、以下に似たエラーメッセージで接続は失敗します:

bash: No such file or directory
kex_exchange_identification: Connection closed by remote host
Connection closed by UNKNOWN port 65535

踏み台サーバにおいて有効なシェルの完全パスを {{ic|SHELL}} に設定するか、{{ic|~/.ssh/config}} で各サーバに対して特定の {{ic|SHELL}} を設定することで、この問題を解決できます。

=== ログインしようとすると接続がハングする ===

MTU/フラグメンテーションの問題により接続確立中にハングすることがあります。ルーターやファイアウォールの設定を間違えていないか調べたり、クライアント側で MTU サイズを少しずつ減らしてみてください (これは良くない回避策です)。
もう一つの方法は、KexAlgorithms、HostKeyAlgorithms、Ciphers、MACs などの設定値を減らして最初の SSH ペイロードを減らすことです。


== 参照 ==
== 参照 ==

*[http://www.la-samhna.de/library/brutessh.html Defending against brute force ssh attacks]
* [[Wikibooks:ja:OpenSSH]]
*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 回]
* [https://www.la-samhna.de/library/brutessh.html Defending against brute force ssh attacks]
* 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]

{{TranslationStatus|OpenSSH|2025-07-12|839725}}

2025年7月12日 (土) 13:11時点における最新版

OpenSSH (OpenBSD 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 オプションによって一部の署名アルゴリズムしか許可されていない場合でも、鍵が存在しない場合、再生成されます。ed25519、ecdsa、そして rsa アルゴリズムに基づく3組の鍵のペアが提供されます。sshd に特定の鍵を使用させるには、以下のオプションを指定してください:

HostKey /etc/ssh/ssh_host_ed25519_key

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

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

デーモンの管理

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

ノート 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.d/20-force_publickey_auth.conf
PasswordAuthentication no
AuthenticationMethods publickey
警告 これを設定に追加する前に、SSH アクセスを必要とする全アカウントが、対応する authorized_keys ファイルで公開鍵認証をセットアップしていることを確認してください。詳細は SSH 鍵#リモートサーバーに公開鍵をコピー を参照してください。

二要素認証と公開鍵

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

認証プロバイダ

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

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

PAM セットアップ
この記事またはセクションの正確性には問題があります。
理由: The distribution defaults to KbdInteractiveAuthentication no since [1]. Later, the lexical order of the defaults was adjusted due to FS#79285 to allow for higher priority user snippets, which would match below 20-pam.conf. However, a BBS thread appears to be resolved by ordering custom after 99-archlinux.conf defaults only. (議論: トーク:OpenSSH#)

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

/etc/ssh/sshd_config.d/20-pam.conf
KbdInteractiveAuthentication yes
AuthenticationMethods publickey keyboard-interactive:pam

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

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

/etc/ssh/sshd_config.d/20-pam.conf
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 によるレート制限シンプルなステートフルファイアウォール#ブルートフォース攻撃 を参照してください。

バージョン 9.8 以降、fail2ban に似た基本的な保護機能が実装されました。デフォルトでは PerSourcePenalties オプションに合理的なデフォルト値が設定されています。様々な条件でソースアドレスによってクライアントにペナルティが掛けられ、接続を一定期間拒否します。

あるいは、ブルートフォースを試みている者を自動でブロックするスクリプトを使うことでブルートフォースから保護することができます。

  • 信頼された場所からの着信 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.d/20-deny_root.conf
PermitRootLogin no

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

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

制限

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

command="rrsync -ro /" ssh-ed25519 ...

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

ログイン時に 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 ファイルの変更を記録することが推奨されます。

SSH 証明書

一般的な SSH 鍵と手動でのフィンガープリントの検証は、一人の管理者によって管理されている少数のホストにおいては簡単でしょうが、この認証方法は拡張性が全くありません。一定数のサーバをいくつかのユーザが SSH を通してアクセスする必要がある場合、全てのホストの SSH 公開鍵フィンガープリントを手動でセキュアかつ確実に検証するのは、ほぼ不可能です。

これに対する解決策は、SSH 証明書を使うことです。SSH 証明書を使えば、SSH のデフォルトの Trust On First Use アプローチよりも拡張性の高い信用の鎖によって、公開鍵の正当性を自動で検証できます。SSH 証明書は、基本的には通常の SSH 公開鍵ですが、信頼されている認証局からの署名が付け加えられおり、これにより鍵の正当性を検証します。

インフラストラクチャ用のホスト認証局の鍵を作成する
$ ssh-keygen -t ed25519 -f ~/.ssh/ca_host_key -C 'Host certificate authority for *.example.com'

認証局の秘密鍵はセキュアに保存されているべきです。鍵の抽出を防止する機構が備わっている NitrokeyYubiKey といったスマートカードやハードウェアトークン上に保存するのが理想です。

サーバの SSH ホスト公開鍵を署名する

サーバの公開鍵を、認証局の秘密鍵が保存されているローカルのシステムにコピーし、サーバの公開鍵を署名してください:

$ ssh-keygen -h -s ~/.ssh/ca_key -I certLabel -n server01.example.com ./ssh_host_ed25519_key.pub
新しい証明書を移動し、sshd にそれを使わせる

生成された証明書 ssh_host_ed25519_key-cert.pub は、サーバの /etc/ssh/ にコピーする必要があります。

/etc/ssh/sshd_config.d/20-ed25519_key.conf
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
認証局を信頼するように全てのクライアントを設定する
~/.ssh/known_hosts
@cert-authority  *.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKL8gB/pjuff005YNazwMCqJpgsXAbQ3r4VStd/CRKwU Host certificate authority for *.example.com
警告 サーバが識別用の証明書を提供しないと、デフォルトで公開鍵認証がフォールバックとして使用されてしまいます。
SSH ユーザ証明書

ユーザの数やデプロイ方法にもよりますが、SSH ユーザ鍵を証明書と共に使用することもできます。多くの ssh ユーザが存在する組織では、この方法でユーザ鍵のデプロイをセキュアに管理することが強く推奨されます。

ユーザ証明書のデプロイは、基本的にはサーバの ID と同じように機能します。詳細と方法については Wikibooks:OpenSSH/Cookbook/Certificate-based Authentication で見られます。

証明書のデプロイを自動化する

多くのオープンソースなツールによって、SSH 証明書のデプロイを自動化する方法が提供されています。人気なものとしては例えば以下があります:

SSHFP レコード

Secure Shell fingerprint record (SSHFP) は、DNS におけるオプションのリソースレコードで、SSH 鍵をホスト名と関連付けます。信用された CA 証明書をサーバー上にアップロードする代わりに DNSSEC を使用することで、公開サーバー上の SSH フィンガープリントを検証することができます。これにより、管理されていないクライアントも鍵のフィンガープリントの有効性を検証することができます。

レコードエントリを生成する

16進数の鍵フィンガープリントを生成して、DNS レコードに記録するには、対象サーバー上でハッシュ値を作成してください。

$ ssh-keygen -r host.example.com

このコマンドで、指定したドメインの利用可能な全 SSH 鍵を読み出し、有効な SSHFP レコードを出力します。この出力されたレコードを、影響するドメインの DNS エントリに記録することができます。

クライアントの設定

SSHFP レコードとして保存されている SSH 鍵フィンガープリントを自動的に取得して信用するには、以下の設定を ssh クライアント側の設定ファイルに追加してください:

~/.ssh/config
# global options
Match all
    VerifyHostKeyDNS yes

対象ホストに有効な SSHFP レコードがあり、そのレコードが有効な DNSSEC 署名で検証されると、ホストが本物であるかどうかを尋ねるプロンプトが表示されずに、フィンガープリントが自動的に受理されます。DNS レコードが DNSSEC によって検証されない場合は、フィンガープリントが正しいかどうかを尋ねるプロンプトが代わりに表示されます。

SSHFP レコードを生成する

ドメインの SSH フィンガープリントを知りたい場合は、ssh-keyscan を使うことで有効な DNS レコードの形式で SSH フィンガープリントを取得できます。(注: デフォルトでは、利用可能な鍵タイプすべてのフィンガープリントが SHA1 と SHA256 の両方で出力されます。)

$ ssh-keyscan -D github.com
; github.com:22 SSH-2.0-babeld-57ca1323
; github.com:22 SSH-2.0-babeld-57ca1323
github.com IN SSHFP 1 1 6f4c60375018bae0918e37d9162bc15ba40e6365
github.com IN SSHFP 1 2 b8d895ced92c0ac0e171cd2ef5ef01ba3417554a4a6480d331ccc2be3ded0f6b
; github.com:22 SSH-2.0-babeld-57ca1323
github.com IN SSHFP 3 1 3358ab5dd3e306c461c840f7487e93b697e30600
github.com IN SSHFP 3 2 a764003173480b54c96167883adb6b55cf7cfd1d415055aedff2e2c8a8147d03
; github.com:22 SSH-2.0-babeld-57ca1323
github.com IN SSHFP 4 1 e9619e2ed56c2f2a71729db80bacc2ce9ccce8d4
github.com IN SSHFP 4 2 f83898df0bef57a4ee24985ba598ac17fccb0c0d333cc4af1dd92be14bc23aa5
; github.com:22 SSH-2.0-babeld-57ca1323

SSH フィンガープリントは一般的には公開鍵の SHA256 ハッシュ値を base64 エンコードしたものですが、SSHFP レコードは鍵のフィンガープリントを16進数で保存します。そのため、通常 SHA256 でフィンガープリントを記録している known_hosts ファイルやその他の文書にある値と比べるために、レコードを base64 の形式に変換する必要があります。

$ echo "SSHFP-fingerprint" | xxd -r -p | base64

鍵タイプ ed25519 の SHA256 フィンガープリントに16進数を使用している github.com の例です。

$ echo "f83898df0bef57a4ee24985ba598ac17fccb0c0d333cc4af1dd92be14bc23aa5" | xxd -r -p | base64
+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU=

known_hosts エントリと比べるには:

$ ssh-keygen -l -f ~/.ssh/known_hosts
DNS から手動で SSHFP レコードを取得する
$ dig SSHFP targetdomain.tld +short

ヒントとテクニック

暗号化 SOCKS トンネル

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

接続の開始

$ ssh -TND 4711 user@host

パスワードを入力すると接続が行われます。N フラグはインタラクティブプロンプトを無効化し、D フラグは listen するローカルポートを指定します (ポート番号は何でもかまいません)。T フラグは疑似 tty アロケーションを無効化します。

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

ブラウザ (或いはその他のプログラム) の設定

上記の手順はウェブブラウザや他のプログラムと組み合わせた場合にのみ有用です。SSH は SOCKS v4 と SOCKS v5 の両方をサポートしているので、どちらかを使用できます。

  • Firefox の場合:
  1. 設定 > 一般 > ネットワーク設定 を開き、接続設定... をクリックします。
  2. 新しくウィンドウが開くので、手動でプロキシーを設定する オプションにチェックを入れ、SOCKS ホスト 欄には localhost と、ポート 欄にはポート番号 (上記の例では 4711) を入力します。
  3. Firefox を再起動します。
ノート Firefox は自動的に SOCKS トンネル経由で DNS リクエストを発行しません。SOCKS vN を使用するときは DNS もプロキシーを使用する (v4 か v5) にチェックを入れることでこの問題を回避できます。
  • Chromium の場合:
  1. SOCKS の設定は環境変数かコマンドラインオプションで設定できます。例えば、以下の関数のどちらかを .bashrc に追加することで可能です:
secure_chromium() {
    local port=4711
    export SOCKS_SERVER=localhost:$port
    export SOCKS_VERSION=5
    (chromium > /dev/null 2>&1 &)
}

secure_chromium() {
    local port=4711
    (chromium --proxy-server="socks://localhost:$port" > /dev/null 2>&1 &)
}
  1. ターミナルを開き
    $ secure_chromium
    と実行します。

ローカルの TUN インターフェイスをセットアップする

これは最初はより複雑ですが、SOCKS プロキシを使わせたいアプリケーション全てを手動で設定する必要はありません。ローカルの TUN インターフェイスをセットアップし、このインターフェイス経由でトラフィックをルーティングさせる必要があります。

VPN over SSH#badvpn とトンネルインターフェイスをセットアップする を見てください。

X11 フォワーディング

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

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

セットアップ

リモート側
  • xorg-xauth パッケージをインストールしてください
  • /etc/ssh/sshd_config 内で:
    • X11Forwardingyes に設定してください
    • AllowTcpForwardingX11UseLocalhost オプションが yes に設定されおり、X11DisplayOffset10 に設定されていることを確認してください (これらの設定は、何も変更していなければ、デフォルト値です。sshd_config(5) を参照)。
  • そして、sshd デーモンを再起動してください。
クライアント側
  • xorg-xauth パッケージをインストールしてください。
  • コマンドラインで日和見的な接続を行うための -X スイッチを指定するか、或いはクライアントの設定ForwardX11yes に設定して、ForwardX11 オプションを有効化してください。
ヒント GUI の描画がおかしい場合やエラーが表示されるときは ForwardX11Trusted オプションを有効にできます (コマンドラインでは -Y スイッチ)。X11 フォワーディングが X11 SECURITY 拡張 の制御から外れるようになります。使用するときはセクション冒頭の警告を読んでください。

使用方法

通常通りリモートマシンにログオンしてください。クライアントの設定ファイルで ForwardX11 が有効化されていない場合は -X スイッチを指定してください:

$ ssh -X user@host

グラフィカルアプリケーションを実行しようとしてエラーが発生する場合は、代わりに ForwardX11Trusted を試してください:

$ ssh -Y user@host

X11 forwarding request failed と出力される場合、リモートマシンでセットアップをやり直してください。X11 フォワーディングのリクエストが成功したら、リモートサーバ上の任意の X プログラムを実行でき、プログラムがローカルセッションにフォワーディングされます:

$ xclock

Can't open display という内容が含まれるエラーが出力される場合は、DISPLAY が適切に設定されていないことを意味します。

一部のアプリケーションは、実行中のインスタンスのチェックをローカルのマシンで行うため、注意してください。Firefox がその例です: すでに実行中の 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 する必要があります。

ヒント X11 Forwarding の問題をトラブルシューティングする有用なリンクをいくつか挙げます: [2][3][4]

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

SSH の X11 の組み込みサポートに加えて、SSH には任意の TCP 接続をセキュアにトンネル化することもできます。ローカルフォワーディングとリモートフォワーディングの両方が使えます。

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

ゆえに:

$ 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 との間でセキュアに運ばれますが、192.168.0.100 と Google との間はセキュアではありません (他の方法を取らない限り)。

似たように:

$ ssh -L 2000:192.168.0.100:6001 192.168.0.100

このコマンドは、localhost:2000 に接続することができ、リモートホストのポート 6001 へ透過的に送信されます。前者の例は、vncserver ユーティリティ (tightvnc パッケージの一部) を使用して VNC 接続を行う際に便利です。便利とはいえ、セキュリティの問題があります。

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

ゆえに:

$ ssh -R 3000:irc.libera.chat: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 デーモンに直接接続できず、踏み台サーバー (要塞サーバーとも) を使わざるを得ないことがあります。よって、2つ以上の SSH トンネルを接続して、それぞれのサーバーに対してローカルの鍵で認証します。SSH エージェントの転送 (-A) と疑似端末の割当 (-t) を使って以下のようにローカルの鍵を転送します:

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

ProxyCommand オプションを使えばこれを自動化することができます:

$ ssh -o ProxyCommand="ssh -W %h:%p bastion.example.org" targetserver.example.org

-J フラグで ProxyJump オプションを使用すれば、これをより簡単かつセキュアに行うことができます:

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

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

ProxyCommand オプションと ProxyJump オプションの主な違いは、後者は踏み台ホスト上のシェルを必要としないところにあります。その結果、ユーザのログイン認証情報への踏み台サーバでのアクセスや SSH エージェントフォワーディングが必要なくなります。ProxyJump オプションでは、ssh クライアントは踏み台サーバを通して直接ターゲットのサーバへ接続し、エンドツーエンドの暗号化されたチャネルをクライアントとターゲットサーバとの間で確立します。

設定ファイルにも、-J フラグと等価なものとして ProxyJump オプションがあります。詳細は ssh_config(5) を見てください。

リレーを介したリバース SSH

アイデアとしては、クライアントは別のリレーを使ってサーバに接続し、サーバはリバース SSH トンネルを使って同じリレーに接続します。これは、サーバが NAT 内にあり、リレーが、ユーザがアクセス可能なプロキシとして使用されている、パブリックにアクセス可能な SSH サーバである場合に便利です。ゆえに、クライアントの鍵がリレーとサーバの両方に対して認可されていることが前提条件であり、サーバはリレーに対してもリバース SSH 接続に対しても認可されている必要があります。

以下の設定例では、user1 がクライアント上で使用されているユーザアカウントであり、user2 は relay 上のアカウント、user3 がサーバー上のアカウントであるとします。まず、以下のコマンドでサーバとリバーストンネルとの接続が確立している必要があります (2222番ポートを使うものとします):

$ ssh -R 2222:localhost:22 -N user2@relay

これは、スタートアップスクリプトや systemd サービス、autosshsidedoorAUR を使って自動化することもできます。

クライアント側では、以下のコマンドで接続を確立させます:

$ ssh -t user2@relay ssh user3@localhost -p 2222
ノート ssh user3@relay -p 2222 では、リレーサーバーのファイアウォールで対象のポートを開いておくとともに、他のアドレスからこのポートへの接続を許可しておく必要があります。

リバーストンネルとの接続を確立させるためのリモートのコマンドは、relay の authorized_keys に以下のような command フィールドを含めることで、定義できます:

~/.ssh/authorized_keys
command="ssh user3@localhost -p 2222" ssh-ed25519 KEY2 user1@client

この場合、接続は以下のコマンドで確立できます:

$ ssh user2@relay

または、RemoteCommandRequestTTY を指定するエントリを ssh の設定に追加することもできます:

~/.ssh/config
Host jump-destination
    Hostname relay
    User user2
    RemoteCommand ssh user3@localhost -p 2222
    RequestTTY yes

この場合、以下のように簡単にできます:

$ ssh jump-destination
ノート クライアント側のターミナルでの SCP の自動補完機能は機能しません。一部の構成では、SCP の転送機能自体も機能しません。

マルチプレクス

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-hpnAUR パッケージをインストールしてください。

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

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

キープアライブ

デフォルトでは、SSH セッションが一定時間アイドルであった場合、自動的にログアウトします。一定時間データが受信されなかった場合にサーバにキープアライブシグナルを送信することで、セッションを開いたままにすることができます。あるいは対照的に、クライアントからデータが送られてこない場合にサーバが定期的にメッセージを送信することもできます。

  • サーバ側: ClientAliveInterval はタイムアウトを秒単位で設定します。クライアントからデータが受信されずにその時間経過すると、sshd が応答を促すリクエストを送信します。デフォルトは0であり、メッセージは送信されません。例えば、60秒毎にクライアントに対して応答を要求するには、サーバ側の設定ClientAliveInterval 60 オプションを設定してください。ClientAliveCountMaxTCPKeepAlive オプションも参照してください。
  • クライアント側: ServerAliveInterval は、クライアントからサーバに向けて送信されるリクエストの時間間隔を設定します。例えば、120秒毎にサーバに対して応答を要求するには、クライアント側の設定ServerAliveInterval 120 オプションを追加してください。ServerAliveCountMaxTCPKeepAlive オプションも参照してください。
ノート セッションを開いたままにするためにキープアライブリクエストを送信する必要があるのは、クライアントかサーバの一方のみです。サーバとクライアントの両方を制御できるならば、セッションを永続的にする必要のあるクライアントに対してのみ ServerAliveInterval を正の値に設定し、その他のクライアントやサーバはデフォルトの設定するのが妥当な選択です。

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

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

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プロセスを維持し、複数のトンネルを存続させることも簡単です。名前の異なる複数のサービスファイルを作成するだけです。

SSH デーモンが失敗した場合の代替サービス

SSH のみに依存するリモート或いはヘッドレスのサーバにおいて、(システムアップグレード後などに) SSH デーモンの起動に失敗すると、管理アクセスできなくなってしまう場合があります。systemd は、OnFailure によるシンプルなソリューションを提供しています。

サーバ上で sshd が実行されていて、telnet がフェイルセーフであるとしてます。以下のようにファイルを作成してください。ただし、telnet.socket有効化しないでください!

/etc/systemd/system/sshd.service.d/override.conf
[Unit]
OnFailure=telnet.socket

これだけです。sshd が実行中である場合、Telnet は実行されません。sshd が起動に失敗した場合、telnet セッションがリカバリとして開かれます。

ホストに基づいてターミナル背景色を設定する

異なるホストに接続していることを簡単に判別できるようにするために、ホストの種類に応じて異なる背景色を設定することができます。

このソリューションは一般には適用できません (ZSH 限定)。

ネットワーク固有の設定

Match exec を使うことで、接続先のネットワークに固有のホスト設定を使用することができます。

例えば、nmcli(1) を使用していて、接続が検索ドメインを使用するように (手動、あるいは DHCP で) 設定されている場合:

~/.ssh/config
Match exec "nmcli | grep domains: | grep example.com"
  CanonicalDomains example.com
  # Should you use a different username on this network
  #User username
  # Use a different known_hosts file (for private network or synchronisation)
  #UserKnownHostsFile <network>_known_hosts

Match host ... exec "..." の例: VPN に接続していない限り、internal.example.com への接続に (ProxyJump を用いた) 踏み台/プロキシが必要であるとしましょう。フラグメント !exec "host internal.example.com" は、internal.example.com が DNS を介して見つけられない場合にのみ、適用されます。様々な代替案が [5] で議論されています。

~/.ssh/config
Match host internal.example.com !exec "host internal.example.com"
  ProxyJump bastion.example.com
Host internal.example.com
  User foobar

プライベートネットワークのホスト鍵検証

あるネットワーク上のサーバとそれとは別のネットワーク上のサーバは、互いに同じプライベート IP アドレスを持つ可能性があるため、それらのサーバは異なる方法で処理する必要があるかもしれません。

この記事またはセクションの正確性には問題があります。
理由: 「最適な」ソリューションに、本番環境では別のものを使うべきという警告があるはずがない。 (議論: トーク:OpenSSH#)

最適なソリューションは、#ネットワーク固有の設定 を使用し、接続しているネットワークに応じて異なる UserKnownHostsFile を使うことです。2つめのソリューションは、プライベートネットワークのホスト鍵を単に無視することです (新しい/プロトタイプのネットワークで作業する際にデフォルトで使用するのが最適です):

~/.ssh/config
Host 10.* 192.168.*.* 172.31.* 172.30.* 172.2?.* 172.1?.*
    # Disable HostKey verification
    # Trust HostKey automatically
    StrictHostKeyChecking no
    # Do not save the HostKey
    UserKnownHostsFile=/dev/null
    # Do not display: "Warning: Permanently Added ..."
    LogLevel Error
この記事またはセクションの正確性には問題があります。
理由: known_hosts ファイルは、サーバにアクセスするためにホスト名を使用したとしても、IP アドレスを記録します。 (議論: トーク:OpenSSH#)
警告 本番環境では、ホスト名を使用してホストにアクセスしたり、ネットワーク固有の known_hosts ファイルを使用するようにしてください。

ログイン時にコマンドを実行

インタラクティブセッションを使用している場合、ログイン時にコマンドを実行する方法は複数存在します:

  • リモートホスト上の authorized_keys ファイルを使用する (sshd(8) § AUTHORIZED_KEYS FILE FORMAT を参照)
  • サーバで PermitUserRC オプションが有効化されている場合、リモートホスト上の ~/.ssh/rc を使用する
  • リモートホスト上のシェル設定ファイルを使用する (例: .bashrc)

エージェントフォワーディング

SSH エージェントのフォワーディングにより、サーバに接続している状態でローカルの鍵を使用することができます。選択したホストのみに対してエージェントフォワーディングを許可することが推奨されます。

~/.ssh/config
Host myserver.com
    ForwardAgent yes

次に、SSH エージェントを構成し、ssh-add を使ってローカル鍵を追加してください。

これで、リモートサーバに接続する場合、あなたのローカル鍵を使用して他のサービスに接続できるようになりました。

新しい鍵の生成

新しいサーバの秘密鍵は以下で生成できます:

  1. すべての鍵を削除する。例えば:
    # rm /etc/ssh/ssh_host_*_key*
  2. sshdgenkeys.service再起動するか、ssh-keygen -A を root として実行する。

sshd を非特権ユーザとして実行

sshd をコンテナ内で (或いはテスト目的などで) 非特権ユーザとして実行したい場合もあるでしょう。

非特権ユーザは /etc/ssh 内のホスト鍵を読むことができないため、新しいホスト鍵を生成しなければなりません:

$ ssh-keygen -q -N "" -t rsa -b 4096 -f /path/to/host/keys/ssh_host_rsa_key
$ ssh-keygen -q -N "" -t ecdsa -f /path/to/host/keys/ssh_host_ecdsa_key
$ ssh-keygen -q -N "" -t ed25519 -f /path/to/host/keys/ssh_host_ed25519_key

sshd_config を作成してください。以下の例では、1024 より大きい値のポート番号を使用し、ホスト鍵への新しいパスを提供し、PAM を無効化します:

/path/to/sshd_config
Port 2022
HostKey /path/to/host/keys/ssh_host_rsa_key
HostKey /path/to/host/keys/ssh_host_ecdsa_key
HostKey /path/to/host/keys/ssh/ssh_host_ed25519_key
UsePAM no

新しく作成した設定で sshd を実行します。-D フラグはデーモンモードを無効化し、-e は出力を標準エラー出力にリダイレクトしてモニタしやすくします:

$ sshd -f /path/to/sshd_config -D -e

トラブルシューティング

チェックリスト

まずは以下の単純な問題をチェックしましょう。

  1. 設定ディレクトリ ~/.ssh のコンテンツが対象ユーザによってのみアクセス可能である必要があります (クライアントとサーバの両方で確認してください)。かつ、対象ユーザのホームディレクトリがそのユーザによってのみ書き込み可能である必要があります:
    $ chmod go-w ~
    $ chmod 700 ~/.ssh
    $ chmod 600 ~/.ssh/*
    $ chown -R $USER ~/.ssh
    
  2. クライアントの公開鍵 (例: id_ed25519.pub) がサーバ上の ~/.ssh/authorized_keys 内に記述されていることを確認する。
  3. サーバの設定AllowUsersAllowGroups によって SSH のアクセスが制限されていないことを確認する。
  4. ユーザがパスワードを設定しているかを確認する。サーバにログインしたことのない新しいユーザは、パスワードを持っていないことがあります。
  5. /etc/ssh/sshd_configLogLevel DEBUG追加してみる。
  6. journalctl -xe を root として実行して、(エラー) メッセージの取得を試みる。
  7. sshd再起動し、クライアントとサーバの両方でログアウト/ログインする。

接続の拒否やタイムアウトの問題

ポートフォワーディング

NAT モードやルータを使っている場合 (VPS を使っていたりパブリックにアドレッシングされたホストを使用していない限り、あり得ます)、ルータが ssh の着信接続をマシンにフォワーディングしていることを確認してください。ip addr を使ってサーバの内部 IP アドレスを見つけ、SSH ポートの TCP 接続をその IP にフォワーディングするようにルータを設定してください。portforward.com が役に立ちます。

SSH が動作していて、リッスンしているか?

ss ユーティリティは、以下のコマンドラインを使うことで、TCP ポートをリッスンしている全プロセスを表示します:

$ ss --tcp --listening

このコマンドの出力を見て、システムが ssh ポートをリッスンしていないことが判明した場合、SSH が実行されていないことを意味します。Journal でエラーなどが出力されていないか確認してください。

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

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) をリッスンするサーバを立ち上げ、リモートから接続してみてください。

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

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 トラフィックを拒否していることを意味します。そのポートはあなたのサーバー上のファイアーウォールか第三者 (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 が両方のポートをリッスンするようにします。

sshd.service サーバを再起動すれば、あともう少しです。次に、デフォルトのポートではなくもう一つのポートを使用するようにクライアントを設定しなければなりません。その問題に対するソリューションは数多く存在しますが、ここではそれらのうち2つを扱っています。

Read from socket failed: connection reset by peer

最近のバージョンの OpenSSH は時々、古い ssh サーバに接続する際に上記のエラーメッセージで失敗することがあります。これは、そのホストに対する様々なクライアントオプションを設定することにより、回避可能です。以下のオプションに関する詳細は ssh_config(5) を見てください。

ecdsa-sha2-nistp*-cert-v01@openssh 楕円曲線ホスト鍵アルゴリズムが原因である可能性があります。このようなアルゴリズムは、HostKeyAlgorithms にそれらのアルゴリズムを除いたリストを設定することにより、無効化できます。クライアント側では、HostKeyAlgorithms のリストの前に - をつけることで、指定したアルゴリズム (ワイルドカードも可) をデフォルトから外すことができます (ssh_config(5) を参照)。

実際に使用されているホスト鍵のアルゴリズムは、ssh -v server_to_connect_to を実行して、kex: host key algorithm: と書かれてある行を見ればわかります。

これでうまく行かない場合、暗号のリストが長過ぎる可能性があります。Ciphers オプションのリストを短くしてください (80 文字未満であれば十分でしょう)。同じように、MACs のリストも短くしてみてください。

OpenSSH のバグフォーラムにおける議論も参照してください。

"[シェル]: No such file or directory" / ssh_exchange_identification の問題

シェルのバイナリが $PATH に登録されているディレクトリ内にあったとしても、特定の SSH クライアントは $SHELL に絶対パスを設定する必要があります (パスは whereis -b [あなたのシェル] で確認できます)。

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

ログイン時に上記のようなエラーが表示される場合、サーバがターミナルを認識できていないことを意味します。また、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 ハック

ノート これは最後の手段にするべきです。

あるいは、TERM=xterm 環境変数をサーバ側で (例えば .bash_profile で) 設定してしまうという方法もあります。これでエラーは出なくなり、ncurses アプリケーションを実行できるようになります。しかし、ターミナルの制御シーケンスが xterm のそれと正確に一致しない限り、奇妙な挙動やグラフィックのバグが発生する場合があります。

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

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

/etc/ssh/sshd_config
HostKey /etc/ssh/ssh_host_ed25519_key

サブシステム要求の失敗

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

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

id_dsa が拒否される

OpenSSH 7.0 ではセキュリティ上の理由により DSA 公開鍵が非推奨となっており、OpenSSH 9.8 はデフォルトで DSA 鍵のサポート無しでビルドされています。2025年最初の OpenSSH リリースでは、DSA のサポートが完全になくなる予定です。今のところ、DSA 公開鍵をどうしても使わなくてはならない場合は、configure--enable-dsa-keys フラグを渡して openssh をビルドする必要があります。[6]

OpenSSH 7.0 で No matching key exchange method found

OpenSSH 7.0 では、Logjam 攻撃からの理論上の脆弱性を理由に diffie-hellman-group1-sha1 鍵アルゴリズムが非推奨になっています (https://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
Match all
    IPQoS reliability

サービスタイプ reliability (0x04) は、0x00throughput (0x08) と同様に、このコマンドを解決するはずです。

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

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

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

WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

SSH サーバの鍵が変更されたという警告がクライアントで表示された場合、新しく提供された鍵が本当にサーバオペレータのものであるかどうかを、何らかの信頼された方法 (暗号化されている必要はありません) で確認する必要があります。確認したら、known_hosts ファイルから古い鍵を ssh-keygen -R $SSH_HOST で削除し、新しいサーバーに接続するときと同じように鍵を受理してください。

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

あなたのターミナルの terminfo エントリが無いホストに接続する場合 (例えば、ncurses に同梱されていない terminfo エントリのターミナルを使用している場合) や、terminfo データベースが限られているホストに接続する場合 (例えば、OpenWrt を実行しているシステム)、terminfo(5) に依存しているソフトウェアで様々な問題が発生します。

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

OpenSSH 8.7 以降、カスタムの TERM 環境変数をリモートホストに渡すには、簡単な設定スニペットを使用してください:

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

踏み台ホストを介する接続が "bash: No such file or directory" で失敗する

(踏み台のサーバで) SHELL 環境変数に有効な完全パスを設定していない場合、以下に似たエラーメッセージで接続は失敗します:

bash: No such file or directory
kex_exchange_identification: Connection closed by remote host
Connection closed by UNKNOWN port 65535

踏み台サーバにおいて有効なシェルの完全パスを SHELL に設定するか、~/.ssh/config で各サーバに対して特定の SHELL を設定することで、この問題を解決できます。

ログインしようとすると接続がハングする

MTU/フラグメンテーションの問題により接続確立中にハングすることがあります。ルーターやファイアウォールの設定を間違えていないか調べたり、クライアント側で MTU サイズを少しずつ減らしてみてください (これは良くない回避策です)。 もう一つの方法は、KexAlgorithms、HostKeyAlgorithms、Ciphers、MACs などの設定値を減らして最初の SSH ペイロードを減らすことです。

参照

翻訳ステータス: このページは en:OpenSSH の翻訳バージョンです。最後の翻訳日は 2025-07-12 です。もし英語版に 変更 があれば、翻訳の同期を手伝うことができます。