「OpenSSH」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(1版 をインポートしました)
(同期)
 
(10人の利用者による、間の64版が非表示)
1行目: 1行目:
[[Category:Secure Shell (日本語)]]
+
[[Category:Secure Shell]]
  +
[[Category:サーバー]]
[[ar:Ssh]]
 
  +
[[Category:OpenBSD]]
 
[[de:SSH]]
 
[[de:SSH]]
[[en:Secure Shell]]
+
[[en:OpenSSH]]
[[es:Secure Shell]]
+
[[es:OpenSSH]]
[[fr:ssh]]
+
[[fa:SSH]]
[[it:Secure Shell]]
+
[[fr:OpenSSH]]
[[ko:Secure Shell]]
 
[[pl:Secure Shell]]
 
 
[[pt:Secure Shell]]
 
[[pt:Secure Shell]]
[[ru:Secure Shell]]
+
[[ru:OpenSSH]]
[[sr:Secure Shell]]
+
[[zh-hans:OpenSSH]]
  +
{{Related articles start}}
[[zh-CN:Secure Shell]]
 
{{Related articles start (日本語)}}
+
{{Related|SSH }}
{{Related|SSH keys}}
 
 
{{Related|Pam abl}}
 
{{Related|Pam abl}}
{{Related2|fail2ban (日本語)|fail2ban}}
+
{{Related|fail2ban}}
{{Related2|sshguard (日本語)|sshguard}}
+
{{Related|sshguard}}
 
{{Related|Sshfs}}
 
{{Related|Sshfs}}
{{Related2|Syslog-ng (日本語)|syslog-ng}}
+
{{Related|Syslog-ng}}
 
{{Related|SFTP chroot}}
 
{{Related|SFTP chroot}}
  +
{{Related|SCP と SFTP}}
  +
{{Related|VPN over SSH}}
 
{{Related articles end}}
 
{{Related articles end}}
  +
[[Wikipedia:ja:OpenSSH|OpenSSH]] (OpenBSD Secure Shell) は、[[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'' デーモンの接続を確立してリモート接続を承認します。Mac OS X, GNU/Linux, Solaris, OpenVMS など近代的なオペレーティングシステムのほとんどでサーバーとクライアントの両方が備わってします。複雑なもの・完全なものまで様々なレベルのバージョンがプロプライエタリ・フリーウェア・オープンソースを問わずに存在します。
 
   
  +
{{Pkg|openssh}} パッケージを[[インストール]]してください。
(ソース: [[Wikipedia:ja:Secure Shell]])
 
   
  +
== クライアントの使用 ==
== OpenSSH ==
 
OpenSSH (OpenBSD Secure Shell) は ssh プロトコルを使ってコンピューターネットワークを介して暗号化通信セッションを提供するコンピュータープログラムのセットです。SSH Communications Security によるプロプライエタリの Secure Shell ソフトウェアスイートに代わるオープンのプログラムとして作成されました。OpenSSH は Theo de Raadt に率いられている OpenBSD プロジェクトの一環として開発されています。
 
   
  +
サーバに接続するには、以下を実行してください:
同じような名前の OpenSSL と OpenSSH が混同されることがときどきありますが、プロジェクトの目的・開発チームは異なります。
 
   
  +
$ ssh -p ''ポート'' ''ユーザ''@''サーバアドレス''
=== OpenSSH のインストール ===
 
[[official Repositories (日本語)|公式リポジトリ]]から {{Pkg|openssh}} を[[pacman (日本語)|インストール]]してください。
 
   
  +
サーバが公開鍵認証のみを許可している場合、[[SSH 鍵]] の記事に従ってください。
=== SSH の設定 ===
 
====クライアント====
 
SSH クライアントの設定ファイルは {{ic|/etc/ssh/ssh_config}} もしくは {{ic|~/.ssh/config}} です。
 
   
  +
=== 設定 ===
{{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''
AllowUsers user1 user2
 
   
  +
# 特定のホストのオプション
特定のグループにだけアクセスを許可するには:
 
  +
Host ''myserver''
AllowGroups group1 group2
 
  +
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''
  +
  +
一部のグループにのみアクセスを許可するには:
  +
  +
AllowGroups ''group1 group2''
   
  +
素晴らしいウェルカムメッセージを ({{ic|/etc/issue}} ファイルなどから) 追加するには、{{ic|Banner}} オプションを設定してください:
SSH による root ログインを無効にするには、PermitRootLogin 行を次のように変更してください:
 
PermitRootLogin no
 
   
ウェルカムメッセージを追加するには {{ic|/etc/issue}} ファイルを編集して Banner 行を次のように変更してください:
 
 
Banner /etc/issue
 
Banner /etc/issue
  +
  +
公開ホスト鍵と秘密ホスト鍵は、''sshdgenkeys'' [[#デーモンの管理|サービス]]によって {{ic|/etc/ssh}} 内に自動で生成されます。{{ic|sshd_config}} 内の {{ic|HostKeyAlgorithms}} オプションによって一部の署名アルゴリズムしか許可されていない場合でも、鍵が存在しない場合、再生成されます。[[SSH 鍵#認証鍵の種類を選択|dsa、rsa、ecdsa、そして ed25519]] アルゴリズムに基づく4組の鍵のペアが提供されます。sshd に特定の鍵を使用させるには、以下のオプションを指定してください:
  +
  +
HostKey /etc/ssh/ssh_host_rsa_key
  +
  +
サーバを WAN に公開するつもりであるならば、以下のようにデフォルトのポートを 22 から別のランダムで大きい値に変更することが推奨されます:
  +
  +
Port 39901
   
 
{{Tip|
 
{{Tip|
  +
* 一般的なサービスにまだ割り当てられていない代替ポートを探すには、[[Wikipedia:List of TCP and UDP port numbers|TCP と UDP のポート番号一覧]]を見てください。また、{{ic|/etc/services}} にあるローカルのポート番号情報を見ることもできます。デフォルトのポート 22 番からポートを変更すると、自動化された認証試行によるログエントリ数が減るでしょう。しかし、そのような攻撃を排除することはできません。関連する情報は [[ポートノッキング]] を参照してください。
* You may want to change the default port from 22 to any higher port (see [[wikipedia:Security_through_obscurity|security through obscurity]]). Even though the port ssh is running on could be detected by using a port-scanner like {{Pkg|nmap}}, changing it will reduce the number of log entries caused by automated authentication attempts. To help select a port review the [[Wikipedia:List of TCP and UDP port numbers|list of TCP and UDP port numbers]]. You can also find port information locally in {{ic|/etc/services}}. Select an alternative port that is '''not''' already assigned to a common service to prevent conflicts.
 
* パスワードによるログインを使わないようにすれセキュリティは大幅に向上します。詳しくは [[SSH keys]] をさい。
+
* パスワードログインを完全無効化ることが推奨さます。そうすることで、セキュリティが格段に向上します。詳細は [[#公開鍵認証を強制する]] を参照ださい。他の推奨されるセキュリティ手法については [[#保護]] を参照しください。
  +
* 設定ファイル内に複数の {{ic|Port ''port_number''}} 行を記述することにより、OpenSSH に複数のポートをリッスンさせることができます。
  +
* 新しい (或いは存在しない) ホスト鍵ペアは、置き換えたいペアを {{ic|/etc/ssh}} から削除し {{ic|ssh-keygen -A}} を root として実行することで、生成することができます。
 
}}
 
}}
   
=== sshd デーモンの管理 ===
+
=== デーモンの管理 ===
次のコマンドで sshd デーモンを起動することができます:
 
# systemctl start sshd.service
 
   
  +
{{ic|sshd.service}} を[[起動/有効化]]してください。これは、SSH デーモンを永続的にアクティブ状態に保ち、各着信接続に対してフォークします。[https://github.com/archlinux/svntogit-packages/blob/packages/openssh/trunk/sshd.service]
次のコマンドで ssdh デーモンを起動時に有効にすることができます:
 
# systemctl enable 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}} に移行することが推奨されます。}}
詳しくは [[systemd (日本語)#ユニットを使う|systemd#ユニットを使う]] を見て下さい。
 
   
  +
{{Warning|{{ic|sshd.socket}} の使用を継続するならば、このユニットの問題に注意してください:
{{Warning|Systemd は非同期にプロセスを実行します。SSH デーモンを特定の IP アドレス {{ic|ListenAddress 192.168.1.100}} に結びつけている場合、デフォルトの sshd.service ユニットファイルはネットワークインターフェイスが有効にされることに依存していないため、ブート中にロードが失敗する可能性があります。IP アドレスをバインドする時は、カスタムした sshd.service ユニットファイルに {{ic|1=After=network.target}} を追加してください。[[Systemd (日本語)#ユニットファイルの編集|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}} を指定した時と同じ欠点が生じます: ネットワークが時間内に立ち上がっていない場合、ソケットは起動に失敗します。}}
また SSH デーモンソケットを有効にすることで初めて接続があったときにデーモンが起動するようにすることもできます:
 
# systemctl start sshd.socket
 
# systemctl enable sshd.socket
 
デフォルトの22番以外のポートを使う場合、ユニットファイルの "ListenStream" を設定する必要があります。{{ic|/lib/systemd/system/sshd.socket}} を {{ic|/etc/systemd/system/sshd.socket}} にコピーして、アップグレードでユニットファイルが上書きされないようにしてください。{{ic|/etc/systemd/system/sshd.socket}} を編集して "ListenStream" を適当なポートに変更します。
 
   
  +
{{Tip|ソケットアクティベーションを使用すると、各接続に対して {{ic|sshd@.service}} の一時的なインスタンスが (異なるインスタンス名で) 開始されます。ゆえに、{{ic|sshd.socket}} もデーモンの通常の {{ic|sshd.service}} も、接続試行をログでモニタできません。ソケットアクティベートされた SSH インスタンスのログは、{{ic|journalctl -u "sshd@*"}} を root として実行するか、{{ic|journalctl /usr/bin/sshd}} を root
{{Warning|Using {{ic|sshd.socket}} effectively negates the {{ic|ListenAddress}} setting, so using the default sshd.socket will allow connections over any address. To achieve the effect of setting {{ic|ListenAddress}}, you must create a custom unit file and modify ListenStream (i.e. {{ic|1=ListenStream=192.168.1.100:22}} is equivalent to {{ic|ListenAddress 192.168.1.100}}). You must also add {{ic|1=FreeBind=true}} under {{ic|[Socket]}} or else setting the IP address will have the same drawback as setting {{ic|ListenAddress}}: the socket will fail to start if the network is not up in time.}}
 
  +
として実行することで、確認することができます。}}
   
  +
=== 保護 ===
{{Tip|When using socket activation neither {{ic|sshd.socket}} nor the daemon's regular {{ic|sshd.service}} allow to monitor connection attempts in the log, but executing {{ic|# journalctl /usr/bin/sshd}} does.}}
 
   
  +
SSH によるリモートログインを許可することは管理業務においては良いことですが、サーバーのセキュリティに脅威を及ぼすことにもなりえます。総当り攻撃の標的になりやすいので、SSH のアクセスは制限して、第三者がサーバーにアクセスできないようにする必要があります。
=== サーバーに接続する ===
 
サーバーに接続するには、次を実行してください:
 
$ ssh -p port user@server-address
 
   
  +
{{Pkg|ssh-audit}} は、サーバとクライアントの設定の自動化された解析を提供します。このトピックに関して、いくつか他のガイドやツールが利用できます。例えば:
=== SSH の保護 ===
 
管理業務のために SSH によるリモートログインを許可することは良いことですが、サーバーのセキュリティに脅威を及ぼすことにもなりえます。総当り攻撃の標的になりやすいので、SSH のアクセスは制限して、第三者がサーバーにアクセスできないようにする必要があります。
 
* わかりにくいアカウント名やパスワードを使う
 
* 信頼できる国からの SSH 接続だけを許可する
 
* [[fail2ban (日本語)|fail2ban]] や [[sshguard (日本語)|sshguard]] をつかってブルートフォース攻撃を監視し、総当りを起こっている IP を閉め出す
 
   
  +
* [[MozillaWiki:Security/Guidelines/OpenSSH|Mozilla Infosec Team による記事]]
===== ブルートフォースアタックからの保護 =====
 
  +
* [https://www.ssh-audit.com/hardening_guides.html SSH 堅牢化ガイド]
ブルートフォースは単純な攻撃方法です: ランダムなユーザー名とパスワードの組み合わせをとにかく沢山作ってウェブページや SSH などのサーバーログインプロンプトにログインを絶えず試行します。ブルートフォース攻撃からは [[fail2ban (日本語)|fail2ban]] や [[sshguard (日本語)|sshguard]] などの自動スクリプトを使うことで攻撃者をブロックすることで身を守ることができます。
 
   
  +
==== 公開鍵認証を強制する ====
もしくは、公開鍵認証を使うことでブルートフォース攻撃を出来なくすることもできます。{{ic|sshd_config}} に次の設定を追加:
 
   
  +
デフォルトでは、クライアントが公開鍵で認証できない場合、SSH サーバはパスワード認証にフォールバックします。なので、悪意のあるユーザがパスワードの[[#ブルートフォース攻撃に対する保護|ブルートフォース]]によるアクセスを試みることができてしまいます。このような攻撃から保護する最も効果的な方法の1つが、パスワードログインを完全に無効化し、[[SSH 鍵]]の使用を強制することです。これは、デーモンの設定ファイルで以下のオプションを設定することで可能です:
PasswordAuthentication no
 
   
  +
{{hc|/etc/ssh/sshd_config|
上の設定を適用する前に、SSH アクセスが必要な全てのアカウントで {{ic|authorized_keys}} ファイルに公開鍵認証の設定をするようにしてください。
 
  +
PasswordAuthentication no
  +
AuthenticationMethods publickey
  +
}}
   
  +
{{Warning|これを設定に追加する前に、SSH アクセスを必要とする全アカウントが、対応する {{ic|authorized_keys}} ファイルで公開鍵認証をセットアップしていることを確認してください。詳細は [[SSH 鍵#リモートサーバーに公開鍵をコピー]] を参照してください。}}
==== root ログインを制限する ====
 
It is generally considered bad practice to allow the root user to log in without restraint over SSH. There are two methods by which SSH root access can be restricted for increased security.
 
   
  +
==== 二要素認証と公開鍵 ====
===== root ログインを拒否する =====
 
Sudo selectively provides root rights for actions requiring these without requiring authenticating against the root account. This allows locking the root account against access via SSH and potentially functions as a security measure agaist brute force attacks, since now an attacker must guess the account name in additition to the password.
 
   
  +
SSH は、認証に複数の方法を要求するようにセットアップすることができます。{{ic|AuthenticationMethods}} オプションを使うことで、どの認証方法を要求するかを指定することができます。これにより、公開鍵と2要素認証を使用することができます。
SSH can be configured to deny remote logins with the root user by editing the "Authentication" section in {{ic|/etc/ssh/sshd_config}}. Simply change {{ic|#PermitRootLogin yes}} to {{ic|no}} and uncomment the line:
 
  +
  +
===== 認証プロバイダ =====
  +
  +
Google Authenticator をセットアップする方法については [[Google Authenticator]] を参照してください。
  +
  +
[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 ドキュメント] を参照してください。
  +
  +
===== PAM セットアップ =====
  +
  +
[[PAM]] を OpenSSH で使用するには、以下のファイルを編集してください:
   
 
{{hc|/etc/ssh/sshd_config|
 
{{hc|/etc/ssh/sshd_config|
  +
KbdInteractiveAuthentication yes
PermitRootLogin no
 
  +
AuthenticationMethods publickey keyboard-interactive:pam
...
 
 
}}
 
}}
   
  +
これで、PAM セットアップによって要求されるユーザ認証か公開鍵の'''どちらか一方'''でログインできます。
次に、SSH デーモンを再起動:
 
# systemctl restart sshd
 
   
  +
一方、PAM セットアップによって要求されるユーザ認証と公開鍵の'''両方'''でユーザを認証したい場合、AuthenticationMethods の分割にスペースではなくコンマを使用してください:
これで root で SSH を使ってログインすることはできなくなります。ただし、通常ユーザーでログインしてから [[su (日本語)|su]] や [[sudo (日本語)|sudo]] を使ってシステム管理を行うことは依然として可能です。
 
   
  +
{{hc|/etc/ssh/sshd_config|
===== root ログインを禁止する =====
 
  +
KbdInteractiveAuthentication yes
Some automated tasks such as remote, full-system backup require full root access. To allow these in a secure way, instead of disabling root login via SSH, it is possible to only allow root logins for selected commands. This can be achieved by editing {{ic|~root/.ssh/authorized_keys}}, by prefixing the desired key, e.g. as follows:
 
  +
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 によるレート制限]] や [[シンプルなステートフルファイアウォール#ブルートフォース攻撃]] を参照してください。
  +
  +
あるいは、[[fail2ban]] や [[sshguard]] などの自動スクリプトを使うことで攻撃者をブロックすることでブルートフォース攻撃から身を守ることができます。
  +
  +
* 信頼された場所からの着信 SSH 接続のみを許可する。
  +
* [[fail2ban]] か [[sshguard]] を使用して、パスワード認証に失敗しすぎた IP アドレスを自動的にブロックする。
  +
* [https://github.com/jtniehof/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|PermitRootLogin no}}
  +
  +
次に、SSH デーモンを[[再起動]]してください。
  +
  +
これで、SSH を使って root でログインすることはできなくなります。ただし、通常ユーザーでログインしてから [[su]] や [[sudo]] を使ってシステム管理を行うことは依然として可能です。
  +
  +
===== 制限 =====
  +
  +
自動的な作業の中にも、リモートによるフルシステムバックアップなど、root 権限を必要とするものがあります。セキュアな方法で root を許可したい場合、SSH による root ログインを無効化する代わりに、特定のコマンドだけ root ログインを許可することができます。{{ic|~root/.ssh/authorized_keys}} を編集して、以下のように特定のキーの前にコマンドを記述します:
   
 
command="/usr/lib/rsync/rrsync -ro /" ssh-rsa …
 
command="/usr/lib/rsync/rrsync -ro /" ssh-rsa …
   
  +
上記の設定で、特定の鍵を使ってログインした場合はクォートで囲ったコマンドを実行できるようになります。
This will allow any login with this specific key only to execute the command specified between the quotes.
 
   
  +
ログイン時に root ユーザーの名前を出すことで攻撃する対象が増えてしまうことに対しては {{ic|sshd_config}} に以下を追加することで埋め合わせができます:
The increased attack surface created by exposing the root user name at login can be compensated by adding the following to {{ic|sshd_config}}:
 
   
 
PermitRootLogin forced-commands-only
 
PermitRootLogin forced-commands-only
   
  +
上記の設定は root が SSH で実行できるコマンドを制限するだけでなく、パスワードの使用も無効化して、root アカウントでは強制的に公開鍵認証を使うようになります。
This setting will not only restrict the commands which root may execute via SSH, but it will also disable the use of passwords, forcing use of public key authentication for the root account.
 
   
  +
root で使えるコマンドは制限しないで公開鍵認証の強制だけをするという手もあり、それでもブルートフォース攻撃はほぼ不可能です。その場合、以下を設定:
A slightly less restrictive alternative will allow any command for root, but makes brute force attacks infeasible by enforcing public key authentication. For this option, set:
 
   
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}} ファイルを読み取り専用にして、他の全パーミッションを禁止してください:
=== SSH 代替: Mobile Shell - responsive, survives disconnects ===
 
Mosh の [http://mosh.mit.edu/ ウェブサイト] より:
 
   
  +
$ chmod 400 ~/.ssh/authorized_keys
Remote terminal application that allows roaming, supports intermittent connectivity, and provides intelligent local echo and line editing of user keystrokes. Mosh is a replacement for SSH. It's more robust and responsive, especially over Wi-Fi, cellular, and long-distance links.
 
   
  +
ユーザがパーミッションを元に戻せないようにするには、{{ic|authorized_keys}} ファイルに[[ファイルのパーミッションと属性#ファイルの属性|変更不可のビットを設定]]してください。ユーザが {{ic|~/.ssh}} ディレクトリをリネームして新しい {{ic|~/.ssh}} ディレクトリと {{ic|authorized_keys}} ファイルを作成できないようにするには、{{ic|~/.ssh}} ディレクトリにも変更不可のビットを設定してください。鍵を追加/削除するには、{{ic|authorized_keys}} から変更不可のビットを削除して一時的に書き込み可能にする必要があります。
[[official Repositories (日本語)|公式リポジトリ]]から {{Pkg|mosh}} を[[pacman (日本語)|インストール]]するか [[Arch User Repository (日本語)|AUR]] にある最新版 {{AUR|mosh-git}} を使って下さい。
 
   
  +
{{Tip|[[Audit フレームワーク#ファイルとディレクトリへのアクセスを監査する|auditd]] などを用いて、{{ic|authorized_keys}} ファイルの変更を記録することが推奨されます。}}
== Tips and tricks ==
 
  +
  +
==== 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|
  +
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 - 認可された鍵のマネージャ]
  +
  +
== ヒントとテクニック ==
   
 
=== 暗号化 SOCKS トンネル ===
 
=== 暗号化 SOCKS トンネル ===
  +
This is highly useful for laptop users connected to various unsafe wireless connections. The only thing you need is an SSH server running at a somewhat secure location, like your home or at work. It might be useful to use a dynamic DNS service like [http://www.dyndns.org/ DynDNS] so you do not have to remember your IP-address.
 
  +
暗号化トンネルは、安全でない様々なワイヤレス接続を使用するノートパソコンユーザにとって非常に有用です。必要なのは SSH サーバーが安全な場所 (家や仕事場など) で動作していることだけです。[https://dyn.com/dns/ DynDNS] などのダイナミック DNS サービスを利用すれば IP アドレスを覚える必要もありません。
   
 
==== 手順 1: 接続の開始 ====
 
==== 手順 1: 接続の開始 ====
  +
You only have to execute this single command to start the connection:
 
  +
以下のコマンドを実行するだけで接続を開始できます:
  +
 
$ ssh -TND 4711 ''user''@''host''
 
$ ssh -TND 4711 ''user''@''host''
where {{Ic|''user''}} is your username at the SSH server running at the {{Ic|''host''}}. It will ask for your password, and then you are connected! The {{Ic|N}} flag disables the interactive prompt, and the {{Ic|D}} flag specifies the local port on which to listen on (you can choose any port number if you want). The {{Ic|T}} flag disables pseudo-tty allocation.
 
   
  +
{{Ic|''user''}} はユーザー名に、{{Ic|''host''}} は SSH サーバーが動作しているホストに置き換えてください。パスワードを入力すると接続が行われます。{{Ic|N}} フラグはインタラクティブプロンプトを無効化し、{{Ic|D}} フラグは listen するローカルポートを指定します (ポート番号は何でもかまいません)。{{Ic|T}} フラグは疑似 tty アロケーションを無効化します。
It is nice to add the verbose ({{Ic|-v}}) flag, because then you can verify that it is actually connected from that output.
 
  +
  +
verbose ({{Ic|-v}}) フラグを追加することで、接続が成功していることを出力から確認することができます。
   
==== 手順 2: ブラウザ (その他のプログラム) の設定 ====
+
==== 手順 2 (やり方 A): ブラウザ (或いはその他のプログラム) の設定 ====
The above step is completely useless if you do not configure your web browser (or other programs) to use this newly created socks tunnel. Since the current version of SSH supports both SOCKS4 and SOCKS5, you can use either of them.
 
   
  +
新しく作成した SOCKS トンネルを使用するようにウェブブラウザ (や他のプログラム) を設定しないと上記の作業は無意味です。SSH は現在 SOCKS v4 と SOCKS v5 の両方をサポートしているため、使用するのはどちらでも構いません。
* For Firefox: ''Edit → Preferences → Advanced → Network → Connection → Setting'':
 
: Check the ''Manual proxy configuration'' radio button, and enter {{ic|localhost}} in the ''SOCKS host'' text field, and then enter your port number in the next text field ({{ic|4711}} in the example above).
 
   
  +
* Firefox の場合: ''設定 > 一般'' を開き、ページ下部に移動し、ネットワーク設定の右にある ''接続設定...'' をクリックしてください。次に、セミウィンドウ内で、''手動でプロキシを設定する'' オプションにチェックを入れ、''SOCKS ホスト'' テキストフィールドに {{ic|localhost}} と入力し、''ポート'' テキストフィールドには SSH のポート番号 (上記の例では {{ic|4711}}) を入力してください。
Firefox does not automatically make DNS requests through the socks tunnel. This potential privacy concern can be mitigated by the following steps:
 
  +
: Firefox は自動的に SOCKS トンネルを介して DNS リクエストを行いません。この潜在的なプライバシーの問題は、インターネット接続の設定画面を更にスクロールし、''SOCKS v5 を使用するときは DNS もプロキシーを使用する'' にチェックを入れることで、軽減することができます。明らかに、この方法は SOCKS v4 ではなく SOCKS v5 を選んだ場合にしか適用できません。
  +
: これらの設定をアクティブ化するために Firefox を再起動してください。
   
  +
* Chromium の場合: SOCKS の設定を環境変数かコマンドラインオプションとして設定できます。以下の関数のうち1つを {{ic|.bashrc}} に追加することをおすすめします:
# Type about:config into the Firefox location bar.
 
# Search for network.proxy.socks_remote_dns
 
# Set the value to true.
 
# Restart the browser.
 
   
* For Chromium: You can set the SOCKS settings as environment variables or as command line options. I recommend to add one of the following functions to your {{ic|.bashrc}}:
 
 
function secure_chromium {
 
function secure_chromium {
 
port=4711
 
port=4711
185行目: 314行目:
 
exit
 
exit
 
}
 
}
  +
OR
 
  +
あるいは
  +
 
function secure_chromium {
 
function secure_chromium {
 
port=4711
 
port=4711
192行目: 323行目:
 
}
 
}
   
  +
そして、ターミナルを開いて、以下を実行してください:
Now open a terminal and just do:
 
  +
 
$ secure_chromium
 
$ secure_chromium
   
  +
セキュアトンネルを楽しみましょう!
Enjoy your secure tunnel!
 
  +
  +
==== 手順 2 (やり方 B): ローカルの TUN インターフェイスをセットアップする ====
  +
  +
このやり方は若干複雑ですが、SOCKS プロキシを使用するためにアプリケーションを1つずつ手動で設定する必要が無くなります。この方法には、ローカル TUN インターフェイスのセットアップと、そのインターフェイスを介したトラフィックのルーティングが含まれます。
  +
  +
[[VPN over SSH#badvpn とトンネルインターフェイスをセットアップする]] を見てください。
   
 
=== 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 forwarding is a mechanism that allows graphical interfaces of X11 programs running on a remote system to be displayed on a local client machine. For X11 forwarding the remote host doesn't need to have a full X11 system installed, however it needs at least to have ''xauth'' installed. ''xauth'' is a utility that maintains {{ic|Xauthority}} configurations used by server and client for authentication of X11 session ([http://xmodulo.com/2012/11/how-to-enable-x11-forwarding-using-ssh.html source]).
 
   
{{Warning|X11 forwarding has important security implications which should be at least acknowledged by reading relevant sections of {{ic|ssh}}, {{ic|sshd_config}} and {{ic|ssh_config}} manual pages. See also [https://security.stackexchange.com/questions/14815/security-concerns-with-x11-forwarding a short writeup]}}
+
{{Warning|X11 フォワーディングにはセキュリティ的に重要な問題があります。{{ic|ssh}}{{ic|sshd_config}}、そして {{ic|ssh_config}} のマニュアルページの該当するセクションを読んで最低限の知識をつけてください。[https://security.stackexchange.com/questions/14815/security-concerns-with-x11-forwarding この StackExchange の質問] も参照。}}
   
 
==== セットアップ ====
 
==== セットアップ ====
   
リモート側:
+
===== リモート側 =====
   
*[[公式リポジトリ]]から {{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'' デーモン]]を再起動してください。
   
  +
===== クライアント側 =====
クライアント側では、接続するたびにコマンドラインで {{ic|-X}} スイッチを指定して {{ic|ForwardX11}} オプションを有効にするか、[[#クライアント|openSSH クライアントの設定ファイル]]で {{ic|ForwardX11}} を ''yes'' に設定してください。
 
   
  +
* {{Pkg|xorg-xauth}} パッケージを[[インストール]]してください。
{{Tip|You can enable the {{ic|ForwardX11Trusted}} option ({{ic|-Y}} switch on the command line) if GUI is drawing badly or you receive errors; this will prevent X11 forwardings from being subjected to the [http://www.x.org/wiki/Development/Documentation/Security/ X11 SECURITY extension] controls. Be sure you have read [[#X11 フォワーディング|the warning]] at the beginning of this section if you do so.}}
 
  +
* コマンドラインで日和見的な接続を行うための {{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 フォワーディング|警告]]を読んでください。}}
   
 
==== 使用方法 ====
 
==== 使用方法 ====
   
通常通り[[#サーバーに接続する|リモートマシンにログ]]ます、クライアントの設定ファイルで ''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 プログラムが起動できるようになったら、出力がローカルセッションに転送されます:
 
  +
{{ic|X11 forwarding request failed}} と出力される場合、リモートマシンでセットアップをやり直してください。X11 フォワーディングのリクエストが成功したら、リモートサーバ上の任意の X プログラムを実行でき、プログラムがローカルセッションにフォワーディングされます:
  +
 
$ xclock
 
$ xclock
   
  +
{{ic|Can't open display}} という内容が含まれるエラーが出力される場合は、{{ic|DISPLAY}} が適切に設定されていないことを意味します。
If you get "Cannot open display" errors try the following command as the non root user:
 
$ xhost +
 
   
  +
一部のアプリケーションは、実行中のインスタンスのチェックをローカルのマシンで行うため、注意してください。[[Firefox]] がその例です: すでに実行中の Firefox を閉じるか、以下の起動パラメータを使用してリモートインスタンスをローカルマシン上で起動してください:
The above command will allow anybody to forward X11 applications. To restrict forwarding to a particular host type:
 
$ xhost +hostname
 
   
  +
$ firefox --no-remote
where hostname is the name of the particular host you want to forward to. See {{ic|man xhost}} for more details.
 
   
  +
接続時に "X11 forwarding request failed on channel 0" と表示される場合 (サーバーの {{ic|/var/log/errors.log}} に "Failed to allocate internet-domain X11 display socket" と出力される場合)、{{Pkg|xorg-xauth}} パッケージがインストールされていることを確認してください。上手く機能しない場合、以下の設定を試してみてください:
Be careful with some applications as they check for a running instance on the local machine. [[Firefox (日本語)|Firefox]] is an example: either close the running Firefox instance or use the following start parameter to start a remote instance on the local machine:
 
$ firefox -no-remote
 
   
  +
* ''サーバ''の {{ic|ssh'''d'''_config}} で {{ic|AddressFamily any}} オプションを有効にする。
If you get "X11 forwarding request failed on channel 0" when you connect (and the server {{ic|/var/log/errors.log}} shows "Failed to allocate internet-domain X11 display socket"), make sure package {{Pkg|xorg-xauth}} is installed. If its installation is not working, try to either:
 
  +
* 或いは、''サーバ''の {{ic|ssh'''d'''_config}} で {{ic|AddressFamily}} オプションを inet に設定する。
  +
IPv4 で Ubuntu クライアントを使っている場合は inet に設定することで問題が解決する場合があります。
   
  +
SSH サーバーの他のユーザーで X アプリケーションを実行するには SSH でログインしているユーザーの {{Ic|xauth list}} の認証行を {{Ic|xauth add}} する必要があります。
* enable the {{ic|AddressFamily any}} option in {{ic|ssh'''d'''_config}} on the ''server'', or
 
* set the {{ic|AddressFamily}} option in {{ic|ssh'''d'''_config}} on the ''server'' to inet.
 
Setting it to inet may fix problems with Ubuntu clients on IPv4.
 
   
  +
{{Tip|{{ic|X11 Forwarding}} の問題をトラブルシューティングする有用なリンクをいくつか挙げます: [https://unix.stackexchange.com/a/12772]、[https://unix.stackexchange.com/a/46748]、[https://superuser.com/a/805060]。}}
For running X applications as other user on the SSH server you need to {{Ic|xauth add}} the authentication line taken from {{Ic|xauth list}} of the SSH logged in user.
 
   
 
=== 他のポートのフォワーディング ===
 
=== 他のポートのフォワーディング ===
In addition to SSH's built-in support for X11, it can also be used to securely tunnel any TCP connection, by use of local forwarding or remote forwarding.
 
   
  +
SSH の X11 の組み込みサポートに加えて、SSH には任意の TCP 接続をセキュアにトンネル化することもできます。ローカルフォワーディングとリモートフォワーディングの両方が使えます。
Local forwarding opens a port on the local machine, connections to which will be forwarded to the remote host and from there on to a given destination. Very often, the forwarding destination will be the same as the remote host, thus providing a secure shell and, e.g. a secure VNC connection, to the same machine. Local forwarding is accomplished by means of the {{Ic|-L}} switch and it's accompanying forwarding specification in the form of {{Ic|<tunnel port>:<destination address>:<destination port>}}.
 
   
  +
ローカルフォワーディングはローカルマシンのポートを開き、ローカルマシンに対する接続はリモートホストにフォワーディングされ、リモートホストから指定された宛先に転送されます。転送先をリモートホストと同じにすることで、同一マシンに対してセキュアシェルやセキュアな [[VNC]] 接続を提供します。ローカルフォワーディングは {{Ic|-L}} スイッチで利用することができ {{Ic|<トンネルポート>:<宛先アドレス>:<宛先ポート>}} という形式で転送先を指定します。
Thus:
 
  +
  +
ゆえに:
   
 
$ ssh -L 1000:mail.google.com:25 192.168.0.100
 
$ ssh -L 1000:mail.google.com:25 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 との間はセキュアではありません (他の方法を取らない限り)。
will use SSH to login to and open a shell on 192.168.0.100, and will also create a tunnel from the local machine's TCP port 1000 to mail.google.com on port 25. Once established, connections to localhost:1000 will connect to the Gmail SMTP port. To Google, it will appear that any such connection (though not necessarily the data conveyed over the connection) originated from 192.168.0.100, and such data will be secure as between the local machine and 192.168.0.100, but not between 192.168.0.100, unless other measures are taken.
 
   
  +
似たように:
Similarly:
 
   
 
$ 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 接続を行う際に便利です。便利とはいえ、セキュリティの問題があります。
will allow connections to localhost:2000 which will be transparently sent to the remote host on port 6001. The preceding example is useful for VNC connections using the vncserver utility--part of the tightvnc package--which, though very useful, is explicit about its lack of security.
 
  +
  +
リモートフォワーディングは SSH トンネルとローカルマシンを通してリモートホストから任意のホストに接続できるようにします。ローカルフォワーディングとは逆の機能であり、ファイアウォールによってリモートホストの接続が限られている場合などに有用です。リモートフォワーディングは {{Ic|-R}} スイッチで使うことができ {{Ic|<トンネルポート>:<宛先アドレス>:<宛先ポート>}} という形式で転送先を指定します。
  +
  +
ゆえに:
  +
  +
$ ssh -R 3000:irc.libera.chat:6667 192.168.0.200
  +
  +
上記のコマンドは {{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}} オプションを見てください。
  +
  +
=== 踏み台ホスト ===
  +
  +
場合によっては、接続先の SSH デーモンに直接接続できず、踏み台サーバー (ジャンプサーバー) を使わざるを得ないことがあります。2つ以上の SSH トンネルを接続して、それぞれのサーバーに対してローカルの鍵で認証します。SSH エージェントの転送 ({{ic|-A}}) と疑似端末の割当 ({{ic|-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
  +
  +
{{ic|-J}} フラグで ProxyJump オプションを使用すれば、これをより簡単かつセキュアに行うことができます:
  +
  +
$ ssh -J user1@bastion1,user2@intermediate2 user3@target
  +
  +
{{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 接続に対しても認可されている必要があります。
  +
  +
以下の設定例では、user1 が client 上で使用されているユーザアカウントであり、user2 は relay 上のアカウント、user3 が server 上のアカウントであるとします。まず、以下のコマンドでサーバとリバーストンネルとの接続が確立している必要があります:
  +
  +
ssh -R 2222:localhost:22 -N user2@relay
  +
  +
これは、スタートアップスクリプトや systemd サービス、[[#Autossh - SSH セッションとトンネルの自動再起動|autossh]] を使って自動化することもできます。
  +
  +
クライアント側では、以下のコマンドで接続を確立させます:
  +
  +
ssh -t user2@relay ssh user3@localhost -p 2222
   
  +
リバーストンネルとの接続を確立させるためのリモートのコマンドは、relay の {{ic|~/.ssh/authorized_keys}} に以下のような {{ic|command}} フィールドを含めることで、定義できます:
Remote forwarding allows the remote host to connect to an arbitrary host via the SSH tunnel and the local machine, providing a functional reversal of local forwarding, and is useful for situations where, e.g., the remote host has limited connectivity due to firewalling. It is enabled with the {{Ic|-R}} switch and a forwarding specification in the form of {{Ic|<tunnel port>:<destination address>:<destination port>}}.
 
   
  +
command="ssh user3@localhost -p 2222" ssh-rsa KEY2 user1@client
Thus:
 
   
  +
この場合、接続は以下のコマンドで確立できます:
$ ssh -R 3000:irc.freenode.net:6667 192.168.0.200
 
   
  +
ssh user2@relay
will bring up a shell on 192.168.0.200, and connections from 192.168.0.200 to itself on port 3000 (remotely speaking, localhost:3000) will be sent over the tunnel to the local machine and then on to irc.freenode.net on port 6667, thus, in this example, allowing the use of IRC programs on the remote host to be used, even if port 6667 would normally be blocked to it.
 
   
  +
注意点として、client の SCP の自動補完関数は機能せず、SCP 転送自体も特定の構成においては機能しません。
Both local and remote forwarding can be used to provide a secure "gateway," allowing other computers to take advantage of an SSH tunnel, without actually running SSH or the SSH daemon by providing a bind-address for the start of the tunnel as part of the forwarding specification, e.g. {{Ic|<tunnel address>:<tunnel port>:<destination address>:<destination port>}}. The {{Ic|<tunnel address>}} can be any address on the machine at the start of the tunnel, {{Ic|localhost}}, {{Ic|*}} (or blank), which, respectively, allow connections via the given address, via the loopback interface, or via any interface. By default, forwarding is limited to connections from the machine at the "beginning" of the tunnel, i.e. the {{Ic|<tunnel address>}} is set to {{Ic|localhost}}. Local forwarding requires no additional configuration, however remote forwarding is limited by the remote server's SSH daemon configuration. See the {{Ic|GatewayPorts}} option in {{Ic|sshd_config(5)}} for more information.
 
   
 
=== マルチプレクス ===
 
=== マルチプレクス ===
   
  +
SSH デーモンは通常はポート 22 番をリッスンします。しかし、公共のインターネット・ホットスポットでは通常の HTTP/HTTPS のポート(80 と 443)以外のトラフィックをブロックしていることが一般的です。そのため SSH 接続がブロックされてしまいます。すぐできる解決策として、{{ic|sshd}} に許可されているポートをリッスンさせるという方法があります:
The SSH daemon usually listens on port 22. However, it is common practice for many public internet hotspots to block all traffic that is not on the regular HTTP/S ports (80 and 443, respectively), thus effectively blocking SSH connections. The immediate solution for this is to have {{ic|sshd}} listen additionally on one of the whitelisted ports:
 
   
 
{{hc|/etc/ssh/sshd_config|
 
{{hc|/etc/ssh/sshd_config|
281行目: 471行目:
 
}}
 
}}
   
  +
しかしポート 443 番は HTTPS コンテンツを提供する Web サーバによってすでに使われていることが多いです。その場合は {{Pkg|sslh}} のようなマルチプレクサを使います。これは複数のポートをリッスンし、そこに来るパケットを複数のサービスに賢く振り分けることができます。
However, it is likely that port 443 is already in use by a web server serving HTTPS content, in which case it is possible to use a multiplexer, such as {{Pkg|sslh}}, which listens on the multiplexed port and can intelligently forward packets to many services.
 
   
 
=== SSH の高速化 ===
 
=== SSH の高速化 ===
   
  +
接続をグローバル及び特定のホストに対して高速化させることのできる[[#設定|クライアント設定]]がいくつかあります。これらのオプションに関する完全な説明は {{man|5|ssh_config}} を参照してください。
You can make all sessions to the same host use a single connection, which will greatly speed up subsequent logins, by adding these lines under the proper host in {{ic|/etc/ssh/ssh_config}}:
 
Host examplehost.com
 
ControlMaster auto
 
ControlPersist yes
 
ControlPath ~/.ssh/socket-%r@%h:%p
 
   
  +
* ''より高速な暗号を使う'': 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}})。
See the {{ic|ssh_config(5)}} manual page for full description of these options.
 
   
  +
* ''圧縮を有効化あるいは無効化する'': 圧縮は低速な接続において速度を向上させることができます。{{ic|Compression yes}} オプションか {{ic|-C}} フラグで有効化できます。しかし、使用される圧縮アルゴリズムは比較的低速な {{man|1|gzip}} であり、高速なネットワークにおいてはボトルネックになってしまいます。接続を高速化させるために、ローカルネットワークや高速なネットワークにおいては {{ic|Compression no}} を使うべきでしょう。
Another option to improve speed is to enable compression with the {{ic|-C}} flag. A permanent solution is to add this line under the proper host in {{ic|/etc/ssh/ssh_config}}:
 
Compression yes
 
{{Warning|{{ic|man ssh}} states that "''Compression is desirable on modem lines and other slow connections, but will only slow down things on fast networks''". This tip might be counterproductive depending on your network configuration.}}
 
   
  +
* ''接続共有'': 以下のオプションを使用することで、同一ホストに対するセッションをすべて単一の接続に共有させることができます:{{bc|<nowiki>
Login time can be shortened by using the {{ic|-4}} flag, which bypasses IPv6 lookup. This can be made permanent by adding this line under the proper host in {{ic|/etc/ssh/ssh_config}}:
 
  +
ControlMaster auto
AddressFamily inet
 
  +
ControlPersist yes
  +
ControlPath ~/.ssh/sockets/socket-%r@%h:%p
  +
</nowiki>}}
  +
: {{ic|~/.ssh/sockets}} の部分は、他のユーザによって書き込むことができないのであれば、どのディレクトリでも構いません。
   
  +
* {{ic|ControlPersist}} は、初回のクライアント接続が閉じられてから、新しいクライアントのためにマスターがどれくらいバックグラウンドで待機すべきかを指定します。利用可能な値は:
Changing the ciphers used by SSH to less cpu-demanding ones can improve speed. In this respect, the best choices are arcfour and blowfish-cbc.
 
  +
** {{ic|no}}: 最後のクライアントが切断されたらすぐに接続を閉じます。
  +
** 秒単位の時間
  +
** {{ic|yes}}: 永遠に待ちます。接続は自動的に閉じられなくなります。
   
  +
* {{ic|AddressFamily inet}} オプションか {{ic|-4}} フラグを使用して IPv6 ルックアップをバイパスすることで、ログインに要する時間を短くすることができます。
{{Warning|Please do not do this unless you know what you are doing; arcfour has a number of known weaknesses.}}
 
   
  +
* 最後に、SSH を SFTP や SCP のために使用するつもりであれば、[https://www.psc.edu/index.php/hpn-ssh High Performance SSH/SCP] は、SSH バッファサイズを動的に大きくすることで、スループットを劇的に増やすことができます。この改善のパッチが施されたバージョンの OpenSSH である {{AUR|openssh-hpn-git}} パッケージをインストールしてください。
To use alternative ciphers, run SSH with the {{ic|-c}} flag:
 
$ ssh -c arcfour,blowfish-cbc user@server-address
 
 
To use them permanently, add this line under the proper host in {{ic|/etc/ssh/ssh_config}}:
 
Ciphers arcfour,blowfish-cbc
 
   
 
=== SSHFS でリモートファイルシステムをマウントする ===
 
=== SSHFS でリモートファイルシステムをマウントする ===
Please refer to the [[Sshfs]] article to use sshfs to mount a remote system - accessible via SSH - to a local folder, so you will be able to do any operation on the mounted files with any tool (copy, rename, edit with vim, etc.). Using sshfs instead of shfs is generally preferred as a new version of shfs hasn't been released since 2004.
 
   
  +
sshfs を使って (SSH でアクセスした) リモートのファイルシステムをローカルフォルダにマウントする方法は [[SSHFS]] の記事を参照してください。マウントしたファイルは様々なツールであらゆる操作することができます (コピー、名前の変更、vim で編集など)。基本的に ''shfs'' よりも ''sshfs'' を使用することを推奨します。''sshfs'' は ''shfs'' の新しいバージョンであり、元の ''shfs'' は2004年から更新されていません。
=== Keep alive ===
 
一定時間操作がないと ssh セッションは自動的にログアウトします。接続を維持するには以下をクライアントの {{ic|~/.ssh/config}} か {{ic|/etc/ssh/ssh_config}} に追加してください:
 
   
  +
=== キープアライブ ===
ServerAliveInterval 120
 
   
  +
デフォルトでは、SSH セッションが一定時間アイドルであった場合、自動的にログアウトします。一定時間データが受信されなかった場合にサーバにキープアライブシグナルを送信することで、セッションを開いたままにすることができます。あるいは対照的に、クライアントからデータが送られてこない場合にサーバが定期的にメッセージを送信することもできます。
これで120秒ごとに "keep alive" シグナルがサーバーに送信されます。
 
   
  +
* '''サーバ'''側: {{ic|ClientAliveInterval}} はタイムアウトを秒単位で設定します。クライアントからデータが受信されずにその時間経過すると、''sshd'' が応答を促すリクエストを送信します。デフォルトは0であり、メッセージは送信されません。例えば、60秒毎にクライアントに対して応答を要求するには、[[#設定_2|サーバ側の設定]]で {{ic|ClientAliveInterval 60}} オプションを設定してください。{{ic|ClientAliveCountMax}} と {{ic|TCPKeepAlive}} オプションも参照してください。
反対に、外部からの接続を維持するには、次をサーバーの {{ic|/etc/ssh/sshd_config}} に設定します (数字は0より大きく):
 
  +
* '''クライアント'''側: {{ic|ServerAliveInterval}} は、クライアントからサーバに向けて送信されるリクエストの時間間隔を設定します。例えば、120秒毎にサーバに対して応答を要求するには、[[#設定|クライアント側の設定]]で {{ic|ServerAliveInterval 120}} オプションを追加してください。{{ic|ServerAliveCountMax}} と {{ic|TCPKeepAlive}} オプションも参照してください。
 
ClientAliveInterval 120
 
   
  +
{{Note|セッションを開いたままにするためにキープアライブリクエストを送信する必要があるのは、クライアントかサーバの一方のみです。サーバとクライアントの両方を制御できるならば、セッションを永続的にする必要のあるクライアントに対してのみ {{ic|ServerAliveInterval}} を正の値に設定し、その他のクライアントやサーバはデフォルトの設定するのが妥当な選択です。}}
=== ssh の設定で接続データを保存する ===
 
Whenever you want to connect to a ssh server, you usually have to type at least its address and the username. To save that typing work for servers you regularly connect to, you can use the personal {{ic|~/.ssh/config}} or the global {{ic|/etc/ssh/ssh_config}} files as shown in the following example:
 
   
  +
=== systemd で SSH トンネルを自動的に再起動 ===
{{hc|~/.ssh/config|
 
Host myserver
 
HostName 123.123.123.123
 
Port 12345
 
User bob
 
Host other_server
 
HostName test.something.org
 
User alice
 
CheckHostIP no
 
Cipher blowfish
 
}}
 
   
  +
[[systemd]] を使ってブート時/ログイン時に SSH 接続を自動的に開始して、''さらに''接続が失敗した時に再起動させることができます。SSH トンネルの管理に役立つツールとなります。
Now you can simply connect to the server by using the name you specified:
 
   
  +
以下のサービスでは、[[#設定|ssh の設定]]に保存された接続設定を使って、ログイン時に SSH トンネルを開始します。接続が何らかの理由で閉じられた場合、10秒待機してから再起動します:
$ ssh myserver
 
   
  +
{{hc|~/.config/systemd/user/tunnel.service|<nowiki>
To see a complete list of the possible options, check out ssh_config's manpage on your system or the [http://www.openbsd.org/cgi-bin/man.cgi?query=ssh_config ssh_config documentation] on the official website.
 
  +
[Unit]
  +
Description=SSH tunnel to myserver
  +
  +
[Service]
  +
Type=simple
  +
Restart=always
  +
RestartSec=10
  +
ExecStart=/usr/bin/ssh -F %h/.ssh/config -N myserver
  +
</nowiki>}}
  +
  +
上記の [[systemd/ユーザー]]サービスを[[有効化]]して[[起動]]してください。トンネルがタイムアウトするのを防ぐ方法は [[#キープアライブ]] を見て下さい。起動時にトンネルを開始したい場合、[[systemd#ユニットファイル|ユニットをシステムサービスとして書きなおして下さい]]。
   
 
=== Autossh - SSH セッションとトンネルの自動再起動 ===
 
=== Autossh - SSH セッションとトンネルの自動再起動 ===
  +
ネットワークの状態が悪かったりしてクライアントが切断してしまい、セッションやトンネルの接続を維持できない場合、[http://www.harding.motd.ca/autossh/ Autossh] を使って自動的にセッションとトンネルを再起動できます。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
  +
[[Proxy settings (日本語)|プロキシ設定]]で設定した 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
With the {{ic|-f}} option autossh can be made to run as a background process. Running it this way however means the passprase cannot be entered interactively.
 
   
  +
{{ic|-f}} オプションで autossh をバックグラウンドプロセスとして実行することができます。ただし対話式でパスフレーズを入力することができなくなります。
The session will end once you type {{ic|exit}} in the session, or the autossh process receives a SIGTERM, SIGINT of SIGKILL signal.
 
   
  +
セッション中に {{ic|exit}} と入力したり autossh プロセスに SIGTERM、SIGINT、SIGKILL シグナルが送られるとセッションは終了します。
==== systemd を使ってブート時に自動的に Autossh を起動する ====
 
If you want to automatically start autossh, it is now easy to get systemd to manage this for you. For example, you could create a systemd unit file like this:
 
   
  +
==== systemd を使ってブート時に自動的に autossh を起動する ====
[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 を自動的に起動したい場合、以下の systemd ユニットファイルを作成します:
Here {{ic|1=AUTOSSH_GATETIME=0}} is an environment variable specifying how long ssh must be up before autossh considers it a successful connection, setting it to 0 autossh also ignores the first run failure of ssh. This may be useful when running autossh at boot. Other environment variables are available on the manpage. Of course, you can make this unit more complex if necessary (see the systemd documentation for details), and obviously you can use your own options for autossh, but note that the {{ic|-f}} implying {{ic|1=AUTOSSH_GATETIME=0}} does not work with systemd.
 
   
Then place this in, for example, /etc/systemd/system/autossh.service. Afterwards, you can then enable your autossh tunnels with, e.g.:
+
{{hc|/etc/systemd/system/autossh.service|2=
  +
[Unit]
  +
Description=AutoSSH service for port 2222
  +
After=network.target
   
  +
[Service]
$ systemctl start autossh
 
  +
Environment="AUTOSSH_GATETIME=0"
(or whatever you called the service file)
 
  +
ExecStart=/usr/bin/autossh -M 0 -NL 2222:localhost:2222 -o TCPKeepAlive=yes foo@bar.com
   
  +
[Install]
If this works OK for you, you can make this permanent by running
 
  +
WantedBy=multi-user.target
  +
}}
   
  +
{{ic|1=AUTOSSH_GATETIME=0}} は接続が成功して ssh が立ち上がったと autossh が認識する秒数です。0に設定すると autossh は ssh の最初の起動失敗を無視します。起動時に autossh を実行する場合は設定するべきです。他の環境変数は man ページを見てください。必要であればもっと複雑に設定することもできますが、{{ic|1=AUTOSSH_GATETIME=0}} を含む {{ic|-f}} は systemd では機能しません。
$ systemctl enable autossh
 
   
  +
設定後はサービスを[[起動]]・[[有効化]]してください。
That way autossh will start automatically at boot.
 
   
  +
以下のように ControlMaster を無効化する必要もあるかもしれません:
It is also easy to maintain several autossh processes, to keep several tunnels alive. Just create multiple .service files with different names.
 
   
  +
ExecStart=/usr/bin/autossh -M 0 -o ControlMaster=no -NL 2222:localhost:2222 -o TCPKeepAlive=yes foo@bar.com
== ソケットアクティベーションで SSH ポート番号を変更する (sshd.socket) ==
 
   
  +
{{Tip|複数のautosshプロセスを維持し、複数のトンネルを存続させることも簡単です。名前の異なる複数のサービスファイルを作成するだけです。}}
次の内容で {{ic|/etc/systemd/system/sshd.socket.d/port.conf}} ファイルを作成:
 
   
  +
=== SSH デーモンが失敗した場合の代替サービス ===
[Socket]
 
# Disable default port
 
ListenStream=
 
# Set new port
 
ListenStream=12345
 
   
  +
SSH のみに依存するリモート或いはヘッドレスのサーバにおいて、(システムアップグレード後などに) SSH デーモンの起動に失敗すると、管理アクセスできなくなってしまう場合があります。[[systemd]] は、{{ic|OnFailure}} によるシンプルなソリューションを提供しています。
リロードすれば systemd は自動的に新しいポートを開きます:
 
   
  +
サーバ上で {{ic|sshd}} が実行されていて、[[telnet]] がフェイルセーフであるとしてます。以下のようにファイルを作成してください。ただし、{{ic|telnet.socket}} は[[有効化]]'''しないでください'''!
systemctl daemon-reload
 
   
  +
{{hc|/etc/systemd/system/sshd.service.d/override.conf|2=
== トラブルシューティング ==
 
  +
[Unit]
=== チェックリスト ===
 
  +
OnFailure=telnet.socket
  +
}}
   
  +
これだけです。{{ic|sshd}} が実行中である場合、Telnet は実行されません。{{ic|sshd}} が起動に失敗した場合、telnet セッションがリカバリとして開かれます。
This is a first-steps troubleshooting checklist. It is recommended to check these issues before you look any further:
 
   
  +
=== ホストに基づいてターミナル背景色を設定する ===
1. The client and server {{ic|~/.ssh}} folder and its content should be accessible by its user:
 
   
  +
異なるホストに接続していることを簡単に判別できるようにするために、[https://bryangilbert.com/post/etc/term/dynamic-ssh-terminal-background-colors/ ホストの種類に応じて異なる背景色]を設定することができます。
$ chmod 700 /home/USER/.ssh
 
$ chmod 600 /home/USER/.ssh/*
 
   
  +
このソリューションは一般には適用できません (ZSH 限定)。
2. Check that all files within client's and server's {{ic|~/.ssh}} folder are owned by its user:
 
   
  +
=== ネットワーク固有の設定 ===
$ chown -R USER: ~/.ssh
 
   
  +
{{ic|Match exec}} を使うことで、接続先のネットワークに固有のホスト設定を使用することができます。
3. Check that the client's public e.g. {{ic|id_rsa.pub}} key row is in the server's {{ic|authorized_keys}} file.
 
   
  +
例えば、{{man|1|nmcli}} を使用していて、接続が検索ドメインを使用するように (手動、あるいは DHCP で) 設定されている場合:
4. Check you did not limit SSH access via {{ic|AllowUsers}} in {{ic|/etc/ssh/sshd_config}} (space separated).
 
   
  +
{{bc|1=
==== 期限切れのキーを削除 (任意) ====
 
  +
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] で議論されています。
5. Delete old/invalid key rows in server's {{ic|~/.ssh/authorized_keys}} file.
 
   
  +
{{bc|1=
6. Delete old/invalid private and public keys within the clients {{ic|~/.ssh}} folder.
 
  +
Match host internal.example.com !exec "host internal.example.com"
  +
ProxyJump bastion.example.com
  +
Host internal.example.com
  +
User foobar
  +
}}
   
  +
=== プライベートネットワークのホスト鍵検証 ===
==== 推奨事項 ====
 
   
  +
あるネットワーク上のサーバとそれとは別のネットワーク上のサーバは、互いに同じプライベート IP アドレスを持つ可能性があるため、それらのサーバは異なる方法で処理する必要があるかもしれません。
7. Keep as less keys as possible in user's {{ic|~/.ssh/authorized_keys}} file on the server.
 
   
  +
{{Accuracy|「最適な」ソリューションに、本番環境では別のものを使うべきという警告があるはずがない。}}
=== 電源オフ/再起動した後も SSH 接続が残ってしまう ===
 
systemd が sshd の前に network を停止してしまうと電源を切った後も SSH 接続が繋がったままになります。この問題を修正するには、{{ic|After}} ステートメントを修正してください:
 
{{hc|/usr/lib/systemd/system/systemd-user-sessions.service|2=
 
#After=remote-fs.target
 
After=network.target}}
 
   
  +
最適なソリューションは、[[#ネットワーク固有の設定]] を使用し、接続しているネットワークに応じて異なる {{ic|UserKnownHostsFile}} を使うことです。2つめのソリューションは、プライベートネットワークのホスト鍵を単に無視することです (新しい/プロトタイプのネットワークで作業する際にデフォルトで使用するのが最適です):
=== 接続が拒否されるまたはタイムアウトする ===
 
   
  +
{{bc|1=
==== Is your router doing port forwarding? ====
 
  +
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 アドレスを記録します。}}
SKIP THIS STEP IF YOU ARE NOT BEHIND A NAT MODEM/ROUTER (eg, a VPS or otherwise publicly addressed host). Most home and small businesses will have a NAT modem/router.
 
   
  +
{{Warning|本番環境では、ホスト名を使用してホストにアクセスしたり、ネットワーク固有の known_hosts ファイルを使用するようにしてください。}}
The first thing is to make sure that your router knows to forward any incoming ssh connection to your machine. Your external IP is given to you by your ISP, and it is associated with any requests coming out of your router. So your router needs to know that any incoming ssh connection to your external IP needs to be forwarded to your machine running sshd.
 
   
  +
=== ログイン時にコマンドを実行 ===
Find your internal network address.
 
   
  +
インタラクティブセッションを使用している場合、ログイン時にコマンドを実行する方法は複数存在します:
ip a
 
   
  +
* リモートホスト上の {{ic|authorized_keys}} ファイルを使用する ({{man|8|sshd}} の {{ic|AUTHORIZED_KEYS FILE FORMAT}} セクションを参照)
Find your interface device and look for the inet field. Then access your router's configuration web interface, using your router's IP (find this on the web). Tell your router to forward it to your inet IP. Go to [http://portforward.com/] for more instructions on how to do so for your particular router.
 
  +
* サーバで {{ic|PermitUserRC}} オプションが有効化されている場合、リモートホスト上の {{ic|~/.ssh/rc}} を使用する
  +
* リモートホスト上のシェル設定ファイルを使用する (例: {{ic|.bashrc}})
   
  +
=== エージェントフォワーディング ===
==== Is SSH running and listening? ====
 
$ ss -tnlp
 
   
  +
SSH エージェントのフォワーディングにより、サーバに接続している状態でローカルの鍵を使用することができます。選択したホストのみに対してエージェントフォワーディングを許可することが[https://security.stackexchange.com/questions/7480/risks-of-ssh-to-an-untrusted-host#7504 推奨]されます。
If the above command do not show SSH port is open, SSH is NOT running. Check {{ic|/var/log/messages}} for errors etc.
 
  +
  +
{{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>
  +
$ chmod go-w ~
  +
$ chmod 700 ~/.ssh
  +
$ chmod 600 ~/.ssh/*
  +
$ chown -R $USER ~/.ssh
  +
</nowiki>}}
  +
# クライアントの公開鍵 (例: {{ic|id_rsa.pub}}) がサーバ上の {{ic|~/.ssh/authorized_keys}} 内に記述されていることを確認する。
  +
# [[#設定_2|サーバの設定]]の {{ic|AllowUsers}} や {{ic|AllowGroups}} によって SSH のアクセスが制限されていないことを確認する。
  +
# ユーザがパスワードを設定しているかを確認する。サーバにログインしたことのない新しいユーザは、パスワードを持っていないことがあります。
  +
# {{ic|/etc/ssh/sshd_config}} に {{ic|LogLevel DEBUG}} を[[追加]]してみる。
  +
# {{ic|journalctl -xe}} を root として実行して、(エラー) メッセージの取得を試みる。
  +
# {{ic|sshd}} を[[再起動]]し、クライアントとサーバの両方でログアウト/ログインする。
  +
  +
=== 接続の拒否やタイムアウトの問題 ===
  +
  +
==== ポートフォワーディング ====
  +
  +
NAT モードやルータを使っている場合 (VPS を使っていたりパブリックにアドレッシングされたホストを使用していない限り、あり得ます)、ルータが ssh の着信接続をマシンにフォワーディングしていることを確認してください。{{ic|$ ip addr}} を使ってサーバの内部 IP アドレスを見つけ、SSH ポートの TCP 接続をその IP にフォワーディングするようにルータを設定してください。[https://portforward.com portforward.com] が役に立ちます。
  +
  +
==== SSH が動作していて、リッスンしているか? ====
  +
  +
[[ss]] ユーティリティは、以下のコマンドラインを使うことで、TCP ポートをリッスンしている全プロセスを表示します:
  +
  +
$ ss --tcp --listening
  +
  +
このコマンドの出力を見て、システムが {{ic|ssh}} ポートをリッスンしていないことが判明した場合、SSH が実行されていないことを意味します。[[Journal]] でエラーなどが出力されていないか確認してください。
   
 
==== 接続をブロックするようなファイアウォールのルールが存在しないか? ====
 
==== 接続をブロックするようなファイアウォールのルールが存在しないか? ====
   
[[iptables (日本語)|Iptables]] によってポート {{ic|22}} の接続がブロックされている可能性があります。次のコマンドで確認してください:
+
[[iptables]] によってポート {{ic|22}} の接続がブロックされている可能性があります。次のコマンドで確認してください:
 
{{bc|# iptables -nvL}}
 
{{bc|# iptables -nvL}}
 
{{ic|INPUT}} チェインのパケットを拒否するようなルールがないか見て下さい。そして、必要であれば、次のようなコマンドでポートのブロックを解除します:
 
{{ic|INPUT}} チェインのパケットを拒否するようなルールがないか見て下さい。そして、必要であれば、次のようなコマンドでポートのブロックを解除します:
462行目: 735行目:
 
# iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT
 
# iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT
 
}}
 
}}
ファイアウォールの設定に関する詳細は[[firewalls (日本語)|ファイアウォール]]を見て下さい。
+
ファイアウォールの設定に関する詳細は[[ファイアウォール]]を見て下さい。
   
  +
==== トラフィックがコンピュータにまで到達しているか? ====
==== Is the traffic even getting to your computer? ====
 
  +
Start a traffic dump on the computer you're having problems with:
 
  +
以下のように問題のコンピュータのトラフィックを収集してみてください:
   
 
# tcpdump -lnn -i any port ssh and tcp-syn
 
# tcpdump -lnn -i any port ssh and tcp-syn
   
  +
上記は基本的な情報を表示します。トラフィックが表示されるまで待ってください。その後、接続を試行してみてください。何も出力がされない場合、コンピュータの外側にある何かがトラフィックを妨害しています (例: ハードウェアファイアウォールや NAT ルーターなど)。
This should show some basic information, then wait for any matching traffic to happen before displaying it. Try your connection now. If you do not see any output when you attempt to connect, then something outside of your computer is blocking the traffic (e. g., hardware firewall, NAT router etc.).
 
   
 
==== ISP またはサードパーティによってデフォルトのポートがブロックされてないか? ====
 
==== ISP またはサードパーティによってデフォルトのポートがブロックされてないか? ====
{{Note|Try this step if you '''KNOW''' you aren't running any firewalls and you know you have configured the router for DMZ or have forwarded the port to your computer and it still doesn't work. Here you will find diagnostic steps and a possible solution.}}
 
   
  +
{{Note|このステップは次のことを確認した後で実行してください。ファイアーウォールを何も起動していないこと。DMZ へのルーターを正しく設定している、またはコンピュータへポートを転送していること。それでもまだ動かない場合、ここで診断のステップと解決法が見つかるでしょう。}}
In some cases, your ISP might block the default port (SSH port 22) so whatever you try (opening ports, hardening the stack, defending against flood attacks, et al) ends up useless. To confirm this, create a server on all interfaces (0.0.0.0) and connect remotely.
 
  +
  +
ときどき ISP が SSH のデフォルトポート (22番) をブロックしている場合があります。この場合はあなたが何をしても (ポートを開ける、スタックを強化する、フラッドアタックを防御する、など) 無意味になります。ブロックされているかどうか確認するために、全てのインターフェイス (0.0.0.0) をリッスンするサーバを立ち上げ、リモートから接続してみてください。
  +
  +
このようなエラーメッセージが出る場合:
   
If you get an error message comparable to this:
 
 
ssh: connect to host www.inet.hr port 22: Connection refused
 
ssh: connect to host www.inet.hr port 22: Connection refused
   
That means the port is '''not''' being blocked by the ISP, but the server does not run SSH on that port (See [[wikipedia:Security_through_obscurity|security through obscurity]]).
+
これはそのポートが ISP にブロックされて'''いない'''が、そのポートでサーバーの SSH が起動していないことを意味します ([[wikipedia:Security through obscurity|security through obscurity]] を参照)
  +
  +
しかし、次のようなエラーメッセージが出る場合:
   
However, if you get an error message comparable to this:
 
 
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 トラフィックを拒否していることを意味します。そのポートはあなたのサーバー上のファイアーウォールか第三者 (ISP など) のどちらかによってステルスされています。自分のサーバーでファイアーウォールが起動していないことが確かなら、また、ルーターやスイッチの中でグレムリンが育っていないことが確かなら、ISP がトラフィックをブロックしています。
That means that something is rejecting your TCP traffic on port 22. Basically that port is stealth, either by your firewall or 3rd party intervention (like an ISP blocking and/or rejecting incoming traffic on port 22). If you know you are not running any firewall on your computer, and you know that Gremlins are not growing in your routers and switches, then your ISP is blocking the traffic.
 
   
  +
ダブルチェックのために、サーバ上で Wireshark を起動してポート 22 でのトラフィックをリッスンしてみましょう。Wireshark はレイヤ 2 のパケット・スニファリング・ユーティリティであり、TCP/UDP はレイヤ 3 以上なので ([[wikipedia:ja:インターネット・プロトコル・スイート|IP ネットワークスタック]]を参照)、もしリモートから接続するときに何も受け取っていなければ、十中八九、第三者がブロックしています。
To double check, you can run Wireshark on your server and listen to traffic on port 22. Since Wireshark is a Layer 2 Packet Sniffing utility, and TCP/UDP are Layer 3 and above (see [[wikipedia:Internet protocol suite|IP Network stack]]), if you do not receive anything while connecting remotely, a third party is most likely to be blocking the traffic on that port to your server.
 
   
===== Wireshark による問題診断 =====
+
===== 問題診断 =====
[[公式リポジトリ]]にある {{Pkg|wireshark-cli}} パッケージで Wireshark を[[インストール]]してください。
 
   
  +
{{Pkg|tcpdump}} または {{Pkg|wireshark-cli}} パッケージで Wireshark を[[インストール]]してください。
And then run it using,
 
tshark -f "tcp port 22" -i NET_IF
 
   
  +
tcpdump の場合:
where NET_IF is the network interface for a WAN connection (see {{ic|ip a}} to check). If you aren't receiving any packets while trying to connect remotely, you can be very sure that your ISP is blocking the incoming traffic on port 22.
 
  +
  +
# tcpdump -ni ''interface'' "port 22"
  +
  +
Wireshark の場合:
  +
  +
$ tshark -f "tcp port 22" -i ''interface''
  +
  +
{{ic|''interface''}} は WAN 接続に使っているネットワークインターフェイスに置き換えてください (確認したいときは {{ic|ip a}} を実行)。リモートで接続を試行してもパケットが全く受け取れない場合、ISP によってポート 22 のトラフィックがブロックされている可能性があります。
   
 
===== 解決方法 =====
 
===== 解決方法 =====
  +
The solution is just to use some other port that the ISP isn't blocking. Open the {{ic|/etc/ssh/sshd_config}} and configure the file to use different ports. For example, add:
 
  +
解決方法は、単に ISP がブロックしていない他のポートを使うことです。{{ic|/etc/ssh/sshd_config}} を編集して他のポートを使うようにしましょう。例えば次を追加します:
   
 
Port 22
 
Port 22
 
Port 1234
 
Port 1234
   
  +
そしてこのファイル中の他の Port 設定をコメントアウトします。「Port 22」をコメントにして「Port 1234」を追加するだけでは、sshd がポート 1234 しかリッスンしなくなるので、この問題は解決しません。この 2 行どちらも使用し、sshd が両方のポートをリッスンするようにします。
Also make sure that other "Port" configuration lines in the file are commented out. Just commenting "Port 22" and putting "Port 1234" won't solve the issue because then sshd will only listen on port 1234. Use both lines to run the SSH server on both ports.
 
   
  +
{{ic|sshd.service}} サーバを[[再起動]]すれば、あともう少しです。次に、デフォルトのポートではなくもう一つのポートを使用するようにクライアントを設定しなければなりません。その問題に対するソリューションは数多く存在しますが、ここではそれらのうち2つを扱っています。
Restart the server {{ic|systemctl restart sshd.service}} and you're almost done. You still have to configure your client(s) to use the other port instead of the default port. There are numerous solutions to that problem, but let's cover two of them here.
 
   
 
==== 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}} にそれらのアルゴリズムを除いたリストを設定することにより、無効化できます。
openssh 5.9 では、上記の修正方法は働きません。代わりに、{{ic|~/.ssh/config}} に以下の行を記述してください:
 
   
  +
これでうまく行かない場合、暗号のリストが長過ぎる可能性があります。{{ic|Ciphers}} オプションのリストを短くしてください (80 文字未満であれば十分でしょう)。同じように、{{ic|MACs}} のリストも短くしてみてください。
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
 
MACs hmac-md5,hmac-sha1,hmac-ripemd160
 
   
openssh バグフォーラム[http://www.gossamer-threads.com/lists/openssh/dev/51339 議論] も参照。
+
openssh バグフォーラムにおける[https://www.gossamer-threads.com/lists/openssh/dev/51339 議論]も参照してください
   
=== "[your shell]: No such file or directory" / ssh_exchange_identification problem ===
+
=== "[シェル]: No such file or directory" / ssh_exchange_identification problem ===
One possible cause for this is the need of certain SSH clients to find an absolute path (one returned by {{Ic|whereis -b [your shell]}}, for instance) in {{Ic|$SHELL}}, even if the shell's binary is located in one of the {{Ic|$PATH}} entries.
 
   
  +
シェルのバイナリが {{Ic|$PATH}} に登録されているディレクトリ内にあったとしても、特定の SSH クライアントは {{Ic|$SHELL}} に絶対パスを設定する必要があります (パスは {{Ic|whereis -b [あなたのシェル]}} で確認できます)。
==="Terminal unknown" や "Error opening terminal" エラーメッセージ===
 
With ssh it is possible to receive errors like "Terminal unknown" upon logging in. Starting ncurses applications like nano fails with the message "Error opening terminal". There are two methods to this problem, a quick one using the $TERM variable and a profound one using the terminfo file.
 
   
  +
=== "Terminal unknown" や "Error opening terminal" エラーメッセージ ===
====$TERM 変数を設定する解決策====
 
After connecting to the remote server set the $TERM variable to "xterm" with the following command.
 
   
  +
ログイン時に上記のようなエラーが表示される場合、サーバがターミナルを認識できていないことを意味します。また、nano などの ncurses アプリケーションを実行すると "Error opening terminal" というメッセージが表示されることがあります。
{{ic|TERM&#61;xterm}}
 
   
  +
クライアントで使用しているターミナルの terminfo ファイルをサーバーにインストールするのが正しい解決方法です。これによってサーバーのコンソールプログラムがターミナルを正しく扱えるようになります。{{ic|infocmp}} を実行してから[[Pacman#パッケージ・データベースに問い合わせる|パッケージを確認]]することで terminfo に関する情報を取得できます。
This method is a workaround and should be used on ssh servers you do seldomly connect to, because it can have unwanted side effects. Also you have to repeat the command after every connection, or alternatively set it in ~.bashrc .
 
====terminfo ファイルを使う解決策====
 
A profound solution is transferring the terminfo file of the terminal on your client computer to the ssh server. In this example we cover how to setup the terminfo file for the "rxvt-unicode-256color" terminal.
 
Create the directory containing the terminfo files on the ssh server, while you are logged in to the server issue this command:
 
   
  +
通常の方法で[[インストール]]できない場合、サーバーのホームディレクトリに terminfo をコピーしてください:
{{ic| mkdir -p ~/.terminfo/r/}}
 
   
  +
$ ssh myserver mkdir -p ~/.terminfo/${TERM:0:1}
Now copy the terminfo file of your terminal to the new directory. Replace {{ic|rxvt-unicode-256color}} with your client's terminal in the following command and {{ic|ssh-server}} with the relevant user and server adress.
 
  +
$ scp /usr/share/terminfo/${TERM:0:1}/$TERM myserver:~/.terminfo/${TERM:0:1}/
   
  +
サーバーから一度ログアウトしてからログインしなおすと問題が解決しているはずです。
{{ic|$ scp /usr/share/terminfo/r/''rxvt-unicode-256color'' ssh-server:~/.terminfo/r/}}
 
   
  +
==== TERM ハック ====
After logging in and out from the ssh server the problem should be fixed.
 
  +
  +
{{Note|これは最後の手段にするべきです。}}
  +
  +
あるいは、{{ic|1=TERM=xterm}} 環境変数をサーバ側で (例えば {{ic|.bash_profile}} で) 設定してしまうという方法もあります。これでエラーは出なくなり、ncurses アプリケーションを実行できるようになります。しかし、ターミナルの制御シーケンスが xterm のそれと正確に一致しない限り、奇妙な挙動やグラフィックのバグが発生する場合があります。
  +
  +
=== Connection closed by x.x.x.x [preauth] ===
  +
  +
sshd のログでこのエラーが確認できる場合、HostKey が正しく設定されているか確認してください:
  +
  +
HostKey /etc/ssh/ssh_host_rsa_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}} のように設定します。サーバの設定は、以下の例のようにする必要があります:
  +
  +
{{hc|/etc/ssh/sshd_config|
  +
...
  +
Subsystem subsystem-name /path/to/subsystem-executable
  +
...
  +
}}
  +
  +
=== OpenSSH 7.0 によって id_dsa が拒否される ===
  +
  +
OpenSSH 7.0 ではセキュリティ上の理由から DSA 公開鍵が非推奨になっています。どうしても有効にする必要がある場合、[[#設定|設定]]オプション {{ic|PubkeyAcceptedKeyTypes +ssh-dss}} を設定してください (https://www.openssh.com/legacy.html はこれには言及していません)。
  +
  +
=== 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
  +
  +
古いアルゴリズムを使用しないようにサーバーをアップグレード/設定することで上記のエラーは解決します。サーバー側の設定を変更できない場合、[[#設定|クライアント設定]]で {{ic|KexAlgorithms +diffie-hellman-group1-sha1}} オプションを使うことでアルゴリズムを有効化できます。
  +
  +
=== SSH から切断したときに tmux/screen セッションがキルされる ===
  +
  +
セッションの終了時にプロセスがキルされる場合、ソケットアクティベーションを使っているために 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}} のプロセスが終了されることを防ぐことができます。
  +
  +
=== SSH セッションが応答しなくなる ===
  +
  +
SSH は [[Wikipedia:Software flow control|Software flow control]] {{ic|XON}} と {{ic|XOFF}} に反応します。{{ic|Ctrl+s}} を押すとフリーズ/ハングアップ/応答停止します。セッションを再開するには {{ic|Ctrl+q}} を使ってください。
  +
  +
=== Broken pipe ===
  +
  +
接続を作ろうとして {{ic|packet_write_wait}} のレスポンスが {{ic|Broken pipe}} になる場合、デバッグモードで接続を再試行し、出力がエラーで終わるかどうか確認する必要があります:
  +
{{bc|debug3: send packet: type 1
  +
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}}) と同様に、このコマンドを解決するはずです。
  +
  +
=== 再起動後デーモンの起動が遅い ===
  +
  +
特にヘッドレスサーバや仮想化サーバにおいて、再起動後のデーモン起動時間が過度に長くなる場合 (例: デーモンが接続を受け付け始めるまでに数分かかる)、エントロピー不足が原因かもしれません。[https://bbs.archlinux.org/viewtopic.php?id=241954] これは、あなたのシステムに適した [[Rng-tools]] や [[Haveged]] をインストールすれば改善することが可能です。ただし、それぞれのパッケージの wiki ページで説明されている、関連するセキュリティ上の影響に注意してください。
  +
  +
=== 応答のない SSH 接続を終了する ===
  +
  +
クライアントセッションが応答しなくなり、実行中のプログラム (例えば [[シェル]]) に終了を指示しても終了しない場合、{{ic|Enter}}、{{ic|~}}、そして {{ic|.}} をこの順番で次々に押すと、セッションを終了させることが可能です。
  +
  +
この {{ic|~}} は疑似端末エスケープ文字 ({{man|1|ssh|ESCAPE CHARACTERS}} 参照) であり、終了させるクライアントセッションに応じて複数回付加することが可能です。例えば、A から B へ接続し、B から C へ接続したときに B から C へのセッションがフリーズした場合、{{ic|Enter}} を押して {{ic|~~.}} と入力すれば、B の作業セッションを残して B から C へのセッションを終了させることができます。
  +
  +
=== WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! ===
  +
  +
ssh サーバの鍵が変更されたことをクライアントが警告した場合、新しく提供された鍵が本当にサーバオペレータのものであるかどうかを確認する必要があります。確認したら、{{ic|known_hosts}} ファイルから古い鍵を {{ic|ssh-keygen -R $SSH_HOST}} で削除し、まるで新しく追加されたサーバであるかのように新しい鍵を追加してください。
  +
  +
=== 適切な terminfo エントリがないリモートに接続する場合 ===
  +
  +
あなたのターミナルの terminfo エントリが無いホストに接続する場合 (例えば、{{Pkg|ncurses}} に同梱されていない terminfo エントリのターミナルを使用している場合) や、terminfo データベースが限られているホストに接続する場合 (例えば、[[Wikipedia:ja:OpenWrt|OpenWrt]] を実行しているシステム)、{{man|5|terminfo}} に依存しているソフトウェアで様々な問題が発生します。
  +
  +
適切な解決策は、適切な terminfo エントリをホストに設置することです。それが不可能な場合は、リモートホストがサポートし、かつ端末と互換性のある値を {{ic|TERM}} に設定することで解決できます。
  +
  +
OpenSSH 8.7 以降、カスタムの {{ic|TERM}} 環境変数をリモートホストに渡すには、簡単な設定スニペットを使用してください:
  +
  +
{{hc|~/.ssh/config|2=
  +
Host example.com
  +
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}} を設定することで、この問題を解決できます。
   
 
== 参照 ==
 
== 参照 ==
  +
*[http://www.soloport.com/iptables.html A Cure for the Common SSH Login Attack]
 
  +
* [[Wikibooks:ja:OpenSSH]]
*[http://www.la-samhna.de/library/brutessh.html Defending against brute force ssh attacks]
 
  +
* [https://www.la-samhna.de/library/brutessh.html Defending against brute force ssh attacks]
*IBM developerWorks の [http://www.ibm.com/developerworks/jp/linux/library/l-keyc/ OpenSSH キー (鍵) の管理: 第 1 回] と [http://www.ibm.com/developerworks/jp/linux/library/l-keyc2/ 第 2 回]
 
  +
* OpenSSH 鍵管理: IBM developerWorks の [https://www.ibm.com/developerworks/library/l-keyc/index.html Part 1]、funtoo.org の [[Funtoo:OpenSSH Key Management, Part 2|Part 2]]、[[Funtoo:OpenSSH Key Management, Part 3|Part 3]]
  +
* [https://stribika.github.io/2015/01/04/secure-secure-shell.html Secure Secure Shell]
  +
  +
{{TranslationStatus|OpenSSH|2023-06-24|781777}}

2023年6月24日 (土) 17:14時点における最新版

関連記事

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

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

目次

インストール

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

クライアントの使用

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

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

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

設定

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

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

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

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

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

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

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

サーバの使用

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

# sshd -t

設定

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

AllowUsers    user1 user2

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

AllowGroups   group1 group2

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

Banner /etc/issue

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

HostKey /etc/ssh/ssh_host_rsa_key

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

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

デーモンの管理

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

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

保護

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

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

公開鍵認証を強制する

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

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

二要素認証と公開鍵

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

認証プロバイダ

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

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

PAM セットアップ

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

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

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

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

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

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

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

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

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

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

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

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

root ログインの制限

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

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

拒否

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

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

/etc/ssh/sshd_config
PermitRootLogin no

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

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

制限

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

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

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

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

PermitRootLogin forced-commands-only

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

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

PermitRootLogin prohibit-password

authorized_keys ファイルのロック

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

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

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

$ chmod 400 ~/.ssh/authorized_keys

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

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

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
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 証明書のデプロイを自動化する方法が提供されています。人気なものとしては例えば以下があります:

ヒントとテクニック

暗号化 SOCKS トンネル

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

手順 1: 接続の開始

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

$ ssh -TND 4711 user@host

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

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

手順 2 (やり方 A): ブラウザ (或いはその他のプログラム) の設定

新しく作成した SOCKS トンネルを使用するようにウェブブラウザ (や他のプログラム) を設定しないと上記の作業は無意味です。SSH は現在 SOCKS v4 と SOCKS v5 の両方をサポートしているため、使用するのはどちらでも構いません。

  • Firefox の場合: 設定 > 一般 を開き、ページ下部に移動し、ネットワーク設定の右にある 接続設定... をクリックしてください。次に、セミウィンドウ内で、手動でプロキシを設定する オプションにチェックを入れ、SOCKS ホスト テキストフィールドに localhost と入力し、ポート テキストフィールドには SSH のポート番号 (上記の例では 4711) を入力してください。
Firefox は自動的に SOCKS トンネルを介して DNS リクエストを行いません。この潜在的なプライバシーの問題は、インターネット接続の設定画面を更にスクロールし、SOCKS v5 を使用するときは DNS もプロキシーを使用する にチェックを入れることで、軽減することができます。明らかに、この方法は SOCKS v4 ではなく SOCKS v5 を選んだ場合にしか適用できません。
これらの設定をアクティブ化するために Firefox を再起動してください。
  • Chromium の場合: SOCKS の設定を環境変数かコマンドラインオプションとして設定できます。以下の関数のうち1つを .bashrc に追加することをおすすめします:
function secure_chromium {
    port=4711
    export SOCKS_SERVER=localhost:$port
    export SOCKS_VERSION=5
    chromium &
    exit
}

あるいは

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

そして、ターミナルを開いて、以下を実行してください:

$ secure_chromium

セキュアトンネルを楽しみましょう!

手順 2 (やり方 B): ローカルの TUN インターフェイスをセットアップする

このやり方は若干複雑ですが、SOCKS プロキシを使用するためにアプリケーションを1つずつ手動で設定する必要が無くなります。この方法には、ローカル 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 が client 上で使用されているユーザアカウントであり、user2 は relay 上のアカウント、user3 が server 上のアカウントであるとします。まず、以下のコマンドでサーバとリバーストンネルとの接続が確立している必要があります:

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

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

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

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

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

command="ssh user3@localhost -p 2222" ssh-rsa KEY2 user1@client

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

ssh user2@relay

注意点として、client の 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-hpn-gitAUR パッケージをインストールしてください。

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 で) 設定されている場合:

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] で議論されています。

Match host internal.example.com !exec "host internal.example.com"
  ProxyJump bastion.example.com
Host internal.example.com
  User foobar

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

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

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

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

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_rsa.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 にそれらのアルゴリズムを除いたリストを設定することにより、無効化できます。

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

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

"[シェル]: No such file or directory" / ssh_exchange_identification problem

シェルのバイナリが $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 が正しく設定されているか確認してください:

HostKey /etc/ssh/ssh_host_rsa_key

サブシステム要求の失敗

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

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

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

OpenSSH 7.0 ではセキュリティ上の理由から DSA 公開鍵が非推奨になっています。どうしても有効にする必要がある場合、設定オプション PubkeyAcceptedKeyTypes +ssh-dss を設定してください (https://www.openssh.com/legacy.html はこれには言及していません)。

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
Host *
    IPQoS reliability

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

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

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

応答のない 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 を設定することで、この問題を解決できます。

参照

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