Ubuntu 20.04 LTSでは、OpenSSHサーバーのバージョンが8.2にアップデートされました。このバージョンではU2F/FIDOハードウェアデバイスのサポートが追加されており、ハードウェアベースの2要素認証が簡単に行えます。今回は比較的安価に入手できるYubiKey のSecurity Key by Yubico[1] を使い、SSHログインに2要素認証を導入する方法を紹介します。
[1] YubiKeyには様々なモデルが存在しますが、SSHログインのみを行う場合はU2F/FIDOにのみ対応していれば問題ありません。YubiKeyの上位モデル ではワンタイムパスワードやOpenPGPなどにも対応していますが、これらの機能は利用しません。
U2F/FIDOとは
FIDO(ファイド)とはFast IDentity Onlineの略で、「 使いやすさ」「 プライバシーとセキュリティ」「 標準化」の3つを核とした、パスワードにかわる新しい認証規格です。FIDOはGoogleやAmazonといった企業も参加している「FIDOアライアンス」によって標準化されています。
U2Fは[2] Universal 2nd Factorの略で、FIDOによって公開されているプロトコルのひとつです。簡単に言えば、従来のID/パスワードに追加する2要素認証の、2要素目を標準化しようというものです。一般的に2要素認証には、508回 でも紹介したTime-Based One-Time Password(TOTP)を使うケースが多いでしょう。しかしTOTPは、ログインの都度スマホアプリを見てワンタイムパスワードを入力する必要があるなど、運用が面倒くさい点は否定できません。U2Fでは、物理的なセキュリティキーを使って2要素認証を行います。これにより、セキュリティレベルを犠牲にすることなく、認証を簡略化できるのです。
図1 GitHubに2要素認証の要素としてセキュリティキーを登録した例。サインイン画面でパスワードを入力した後、セキュリティキーを使用するボタンが表示される。なおここで「Enter a two-factor code from your phone」をクリックすると、従来通りワンタイムパスワードの入力による認証も可能となっている
図2 セキュリティキーを使うと、ワンタイムパスワードのかわりに物理キーへのタップ操作を要求される。タップするだけで認証は完了する
ecdsa-sk/ed25519-skの鍵ペアを作成する
それでは実際に、Security Key by Yubicoを使ってSSHサーバーへのログインを行ってみましょう。今回はサーバー版の20.04 LTSを使い、自分自身にSSHログインすることで動作を検証しています。
GitHubなどのWebサービスでは、アカウントにセキュリティキーを登録することで、そのキーでの2要素認証を可能にしています。対してセキュリティキーを用いたSSHログインでは、そのキーに対応した鍵ペアを作成する必要があります。OpenSSH 8.2では、ssh-keygenコマンドの-tオプションで指定できる鍵タイプに「ecdsa-sk」と「ed25519-sk」という、ふたつの「-sk」というサフィックスを持つタイプが追加されています。このどちらかを指定して、新しい鍵を作成してください。ここではed25519-skを使用しました。
ssh-keygenコマンドを実行すると、まずキーへのタッチを要求されます[3] 。その後は鍵を保存するファイル名の指定とパスフレーズの設定という、お馴染みの手順になります。
$ ssh-keygen -t ed25519-sk
Generating public/private ed25519-sk key pair.
You may need to touch your authenticator to authorize key generation. ← ここでキーへのタッチを要求される
Enter file in which to save the key (/home/mizuno/.ssh/id_ed25519_sk): ← 鍵のファイル名を指定する。
Enter passphrase (empty for no passphrase): ← 秘密鍵のパスフレーズを入力する
Enter same passphrase again: ← パスフレーズを再入力する
Your identification has been saved in /home/mizuno/.ssh/id_ed25519_sk
Your public key has been saved in /home/mizuno/.ssh/id_ed25519_sk.pub
The key fingerprint is:
SHA256:9w8p7xZ3wdG8KHMlIjfn6pn5lC4BFEVN8/Nc7xgxCCk mizuno@focal
The key's randomart image is:
+[ED25519-SK 256]-+
| .=+oo ..|
| Eo.= =ooo|
| ..o * Bo+|
| . o + B=|
| S o = . =|
| . +..o+.|
| o O=...|
| O+o |
| o=o. |
+----[SHA256]-----+
図3 USBに接続した状態のSecurity Key
図4 タッチを要求されている時は、鍵マークが点滅する
なおセキュリティキーがシステムに接続されていない状態で鍵タイプにed25519-skやecdsa-skを指定した場合、ssh-keygenコマンドは即座に終了します。
Security Keyが見つからなかった場合の例
$ ssh-keygen -t ed25519-sk
Generating public/private ed25519-sk key pair.
You may need to touch your authenticator to authorize key generation.
Key enrollment failed: device not found
作成された公開鍵(この例では.ssh/id_ed25519_sk.pub)を、サーバーのauthorized_keysに登録してください。今回はローカルマシン上で検証を行うので、catコマンドで出力してしまえばよいでしょう。
公開鍵をauthorized_keysファイルの末尾に追記する
$ cat ~/.ssh/id_ed25519_sk.pub >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys
セキュリティキーを使ってSSHログインしてみる
作成した鍵を使用して、サーバーにログインしてみましょう。sshコマンドに-iオプションで、秘密鍵ファイルを指定して実行してください。なお今回作成したように、鍵ファイルにデフォルトの名前(~/.ssh/id_ed25519_sk)をつけている場合は、-iオプションは省略可能です。
秘密鍵ファイルのパスフレーズを入力すると、続いてキーへのタッチが要求されます。タッチをすると、サーバーへログインできます。
$ ssh -i ~/.ssh/id_ed25519_sk localhost
Enter passphrase for key '/home/mizuno/.ssh/id_ed25519_sk': ← 秘密鍵のパスフレーズを入力する
Confirm user presence for key ED25519-SK SHA256:9w8p7xZ3wdG8KHMlIjfn6pn5lC4BFEVN8/Nc7xgxCCk ← キーへのタッチを要求される
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-28-generic x86_64)
(...略...)
mizuno@focal:~$ ← ログイン完了
従来の公開鍵認証では、サーバーに登録した公開鍵と、手元のクライアントにある秘密鍵を使って認証を行っていました。セキュリティキーに対応した鍵で認証を行う場合、クライアント上に作成されている秘密鍵ファイルは、実際にはキーハンドルと呼ばれるものにあたります。このキーハンドルと、セキュリティキー内に保存されているデバイスシークレットを組み合わせることで、実際に使用する秘密鍵を認証時に生成しています。そのためセキュリティキーを使ったSSH認証は、サーバーから見れば従来の公開鍵認証と同じです。公開鍵でログインできるサーバーであれば、sshd_configなどの設定を変更することなく[4] 、U2Fを導入することが可能です。
タッチ操作を省略するには
Security Key by yubicoのタッチ操作は、あくまでキーを使用する合図でしかなく、指紋認証などでキーをロックしているわけではありません。タッチ操作を省いたからといってセキュリティレベルが下がるわけではありませんから、面倒ならタッチ操作は省いてしまいたいと思うのは人情というものでしょう。
タッチ操作を省略するには、鍵とサーバーの両方でオプションを指定する必要があります。まずssh-keygenコマンドで鍵を生成する際に、「 -O no-touch-required」オプションを指定しておく必要があります。
no-touch-requiredオプションつきの鍵を生成する
$ ssh-keygen -t ed25519-sk -O no-touch-required
作成した公開鍵をauthorized_keysに追加する際、ここにも「no-touch-required」というプレフィックスを付加してください。
authorized_keysに登録した鍵にプレフィックスをつける
no-touch-required sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG...(略)
以降、この鍵を使用する際はキーがUSBに挿入されていればよく、タッチ操作なしでのログインが可能になります。
このようにUbuntu 20.04 LTSでは、サーバーに変更を加えたり、クライアントに特別なアプリをインストールすることなく、SSHでセキュリティキーを利用することができます。SSHの認証を強化する施策のひとつとして、導入してみてはいかがでしょうか。なおSSH以外でのU2Fの活用例は、第570回 でも紹介しています。あわせて参考にしてください。