Chienomi

OpenSSHの実用 初歩

Live With Linux::basic

本記事は、SSHの話をするたびにOpenSSHの具体的な書き方を説明するのが面倒になったので書いたものである。

SSHの公開鍵認証についてはSSHの公開鍵認証に関する誤謬と実際のほうを参照。

「SSHが何かわからない」というレベルまではカバーしないし、SSHの基礎を知りたいというハイレベルな人もカバーしない。 そういう人は授業やってる(Linux基礎中級 SSH)から、申し込んで。

OpenSSHとは

  • SSHの一番使われている実装
  • クライアント, サーバーのほか、SFTPサーバー/クライアントもある
  • クライアントはかなり高機能、サーバーも先進的
  • Windows (10以降)1, Macでは標準。他のLinux/Unixでもだいたい標準
  • 暗号化基盤としてはOpenSSLを使っている
  • ライブラリとしてもよく使われる
  • 私の最推しソフトウェア

クライアントコマンドの基本

ssh [-p port] [-i indentity_file] [user@]host

userを省略した場合、現在のログインユーザーと同じになる。

-iは秘密鍵ファイル。

ユーザー設定ファイルの場所

~/.ssh

これはWindowsでもこのようになっていて、Windows版OpenSSHではWindowsらしくない(Unix的な)ファイル配置と命名規則を持つ。

公開鍵認証

認証メソッドとしてパスワードではなく公開鍵を使う方法。

まず鍵を作る。

ssh-keygen [-t type] [-f file]

-fはつけなくても対話的に聞かれるけど、-tはつけないとRSAになる。 種類は以下の通り。

type 鍵長
dsa 1024
rsa 1024-3072
ssh-rsa 1024-3072
rsa-sha2-256 1024-3072
rsa-sha2-512 1024-3072
ecdsa 256, 384, 521
ecdsa-sk 256
ed25519 255
ed25519-sk 256

RSAは既に脆弱だと考えられているし、長い鍵長ということもありパフォーマンスも悪いため、RSAを使うのはもう「ちょっと恥ずかしい」レベル。

ECDSAとEd25519に強度の差はない。というよりも、ECDSAは384bit, 512bitならより強度は高い。 ただ、ECDSAは特許上の潜在的な問題があることと、Ed25519のほうが高速なため、最もモダンな選択はEd25519。

EdDSAにはed448という鍵長448bitのものもあるけど、OpenSSH 9.0現在サポートされていない。 PuTTYはed448をサポートしているらしい。

すごく重要なこととして、この鍵は認証に使われるものであって、経路暗号化に使われてるものではないから、暗号強度には関わらない。 また、公開鍵認証は公開鍵を用いた認証であり、チャレンジレスポンス認証ではない。

複数のマシンやユーザーが認証を行う必要があるのであれば、その数だけ鍵ペアを生成すべきで、秘密鍵を共有してはならない。

認証される側は認証ファイル(デフォルトは~/.ssh/authorized_keysおよび~/.ssh/authorized_keys2)に1行1鍵で公開鍵を配置する。 このファイルは/etc/ssh/sshd_configAuthorizedKeyFilesによって定義される。

鍵ファイル名は基本的には<name>_<type>。通常、~/.ssh以下に置かれるけど、特に強制はされない。

鍵コマンドと鍵オプション

鍵の手前側に鍵オプションを書けるようになっている。 オプションの詳細はsshd(8)のmanpageに記載がある。

例えば鍵が

ssh-ed25519 AAAAZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ haruka@example

だとして、athorized_keys

no-X11-forwarding ssh-ed25519 AAAAZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ haruka@example

とすれば、SSH経由でXアプリを転送することを禁止できる。

この中で最も有用であり多用するのがcommandオプション。 これは、認証が成功するとこのコマンドを実行する。これにより、認証後にシェルを与えず、コマンドを実行するだけということができる。鍵単位でできることを制限できて便利。

command="/bin/sl" ssh-ed25519 AAAAZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ haruka@example

特殊なコマンドとしてinternal-sftpがあり、これはSFTPの接続のみを受け付ける。 OpenSSHサーバー組み込みの機能なので、chroot環境下でも動作する。

また、この鍵コマンドやForceCommandでコマンド起動された場合、もともと呼ばれたコマンドは$SSH_ORIGINAL_COMMANDに入っているので、これを使えばコマンドを指定しつつ振る舞いを制御できる。

OpenSSHの認証

サポートされている認証はだいたい

  • PAM / BSDAuth (パスワード)
  • GSSAPI
  • ユーザー公開鍵
  • ホスト公開鍵
  • keyboard-interactive
  • ハードウェアトークン (sk公開鍵)
  • TLS証明書
  • なし

keyboard-interactiveはややこしいので説明略。単にkeyboard-interactiveと書いただけであればpasswordと変わらない。Kerberosとか使う場合によく利用される。

OpenSSHは多要素認証が可能なので、パスワードと公開鍵両方ということもできるし、PAM任せでパスワードとGoogle Authenticatorみたいなこともできる。

設定はAuthenticationMethodsで行うけど、ほとんどの場合passwordpublickeyしか使わない。 というより、publickeyが利便性の面でもセキュリティの面でもあまりに優れていて、一方不特定のマシンから入れるようにするならpasswordくらいしかないため、他が有効なことがあんまりない。

クライアントの設定

クライアント全体の設定は/etc/ssh/ssh_configだけど、これはせいぜいCiphersを書くくらいで、普通はユーザーレベルの設定(~/.ssh/config)のほうに書く。

結構色々書けるけれど、基本はHostから。

Hostはsshの接続先として与えられたhostと一致する場合にそのセクションが適用される。 例えば、

Host foo.local
  User bob
  Port 2222

なら、foo.localに対するアクセスはユーザー名を明示しなくてもユーザーbobになるし、ポートは2222になる。

このHostの値はあくまでsshの値でしかないため、実際に解決可能なホスト名(あるいはアドレス)である必要はない。 むしろそうではないほうが普通で、HostNameで実際の接続先を指定できる。次の例ではfooに対して接続すると、実際にはfoo.example.comに対して、~/.ssh/foo_ed25519鍵を使ってアクセスする。

Host foo
  HostName foo.example.com
  IdentityFile .ssh/foo_ed25519

場合によってはAgent ForwardingやProxy Commandに関わる多段ログインを書くこともある。

このHostOpenSSHが使われる場合、常に有効である。 つまり、内部的にOpenSSHを使用するソフトウェア、例えばscpgitなどで、通常できないプロキシ指定やポート指定などを行うことができる。

サーバーの設定

設定ファイルは/etc/ssh/sshd_config

とりあえず

AuthenticationMethods publickey

と書けば堅牢な公開鍵認証のみになるので安心。 そもそもパブリックにSSHアクセスを認めないのであれば、グローバルセクションに

DenyUsers *

と書いておけば誰もログインできない。

その上でMatchセクションを設定して、指定条件ごとの適用を書く。 例えば、192.168.10.0/24からのみ公開鍵認証を許すなら

AuthenticationMethods publickey
DenyUsers *

Match Address 192.168.10.0/24
  DenyUsers root

といった感じ。

AES-NIとchacha20-poly1305

OpenSSHでサポートされている暗号は、AES関連が8種類と、Triple DES、そしてChaCha20-Poly1305。

Triple DESは古いものとして、ChaCha20-Poly1305って何かというと、軽量な暗号(とメッセージ認証)。 安全で、なおかつAESよりも軽くて高速な暗号になっていて、OpenSSHではデフォルトで最も優先される。

ところが、PCのプロセッサはほぼ間違いなくAES-NIというAES暗号専用のチップを持っているため、ソフトウェアで処理されるChaCha20よりもAESのほうが桁違いに速い。

使用する暗号の指定はssh_configsshd_configの両方でできるけれど、SSHサーバーに対してスマートフォンでアクセスするような可能性を考慮するなら、ssh_config側に書くほうがいい。 サーバーがAES-NIを持っていないことが考えられるなら別だけど。