YubiKey NEO で Linux でも ２段階認証しよう！

# YubiKey NEO で Linux でも ２段階認証しよう！

先日、前から気になっていた YubuKey を手に入れました。
セキュリティ関連のハードウェアというと Linux でのサポートはどうなんだ？というところが気になる点です。
YubiKey は Linux もサポートしており、（むしろ Linux の方が柔軟）設定関連のソフトウェアも揃っています。

今回は YubiKey で何ができるのかも含めて紹介したいと思います。

## YubiKey のタイプについて

尚、今回使用しているのは YubiKey NEO です。
外部サービスの2段階認証だけでなく抜き差しをする想定のため、NEO を使用します。
外部サービスの2段階認証のために使うのであれば抜き差しをあまり行わない nano でもいいかも知れません。
とはいえ U2F の機能があるものが良いと思います。

YubiKey はセキュリティで使用する設定をプログラムすることができます。
YubiKey には slot1, slot2 と設定を格納する場所が ２つあり個別に設定することができます。

U2F の機能は slot1 slot2 とは別の場所にプログラムされているので U2F 対応のものを使えば最大 3 種類の設定を扱うことができます。
slot1 と slot2 があると言いましたが、YubiKey を見えると切り替えスイッチのようなものが見当たりません。どのように slot1 と slot2 を切り替えて使うのでしょうか？
答えは「タッチする時間によって切り替える」です。0.5 〜 1 秒間タッチすると slot1、2 〜8 秒タッチすると slot2 の設定を使用します。slot2 を使う場合が触りっぱなしにしていた方が確実でしょう。8秒以上触っていると slot2 と判断し、入力が進みます。

## 事前準備

### 基本的なセキュリティ

YubiKey を使えばセキュリティはあがります。ですが YubiKey があってもマシンそのものは脆弱です。

- USB ブートで別 OS から HDD がマウントされ YubiKey の設定が無効化された
- HDD が取り出されて直接データが読み出されてしまった

などといった物理的な攻撃に対して YubuKey は無力です。
まず以下の対策を行いましょう。

- パスワードは長いものを使用する
- 設定、ブートオーダーなどを変えれないように BIOS にパスワードを設定する
- 最悪 HDD 自体をとり出されても良いようにファイルを暗号化する

YubiKey があっても万が一に備え、上記の対策は必ず行うようにしましょう。
基本的に、YubiKey は 2 段階認証として使うので認証の片方であるパスワードもそれなりに強固にしておくべきでしょう。
（もちろん運用ルールにもよります）

ただ、YubiKey の設定をいろいろやっている際に、設定を間違えログインできなくなることが多々あります。その際は USB などから別OSを立ち上げるのですが、その際 BIOS パスワードを入れるのが煩わしい場合があります。設定が安定した後、BIOS のパスワードをかけても良いかも知れません。

### カスタマイズソフトウェアのインストール

YubiKey NEO の場合、出荷時は slot1 に OTP、slot2 は空き、U2F は有効となっています。
外部サービスの 2段階認証として使う場合には基本的に何もソフトウェアはインストールしなくても事足りるかも知れません。

少しでもカスタマイズしたい場合には設定用のソフトウェアをインストールする必要があります。
今回は サーバーの2段階認証の導入などもやってみようと思いますので PAM Module などをインストールします。

今回の使用する環境は Arch Linux です。多くのディストリビューションでもそうですが、YubiKey のソフトウェアはほとんどパッケージ化されており、インストールもそこまで大変ではありません。

まず、personalization tool を入れましょう。

```
$ packer -S yubikey-personalization yubikey-personalization-gui yubikey-neo-manager
```

今回使用しているバージョンは以下です。

- yubikey-neo-manager 1.3.0-2
- yubikey-personalization 1.17.1-2
- yubikey-personalization-gui 3.1.21-2

依存関係で問題がある場合にはそれらを先にインストールしてから再度インストールしてください。
設定を行うツールである Personalization Tool を立ち上げてみましょう。

```
$ yubikey-personalization-gui
```

を実行し、Personalization Tool が立ち上がることを確認しましょう。
YubiKey を差し込んで `YubiKey is Inserted` と表示されることを確認しましょう。

## 初期設定の確認

YubiKey NEO の場合、全機能使用することができます。
YubiKey を挿し、`yubikey-personalization-gui` を起動し初期設定を確認しましょう。

NEO の場合、画面右側のfeature に全てチェックが入っていると思います。
また slot1、slot2 に設定があるかも表示されます。

以下がメニューです。

- Yubico OTP
- OATH - HOTP
- Static Password
- Challenge - Response
- Settings
- Tools

全体的な設定は Settings になります。
OTP などの設定は複雑なところもあるので設定自体に Quick と Advanced の 2 モード用意されています。とても親切ですね。設定は最終的にどちらの slot に設定するかを決めて書き込みます。

初期設定は slot1 に OTP の設定があります。もし、slot2 に設定を追加したい、slot1 の設定を書き換えたい場合にはこの `yubikey-personalization-gui` を使って変更します。

### mode

YubiKey には slot に設定する設定の他に `mode` というものがあります。
U2F が slot と別の場所に設定されていると言いましたが、それが `mode` になります。
出荷時は `OTP+U2F` という `mode` になっています。
もし、あなたが PGP の鍵を YubiKey に埋め込みたい場合には `mode` を変更する必要があります。

U2F をサポートしている YubiKey NEO の場合、`mode` は 3 つになります。

- OTP
- CCID
- U2F

`mode` 変更するには yubikey-neo-manager を起動します。

```
$ neoman
```

起動すると `Change Connection mode [OTP+U2F]` と表示されているはずです。
CCIDをサポートしたい場合にはここで `mode` を変更してください。

## Google など外部サービスの 2 段階認証で YubiKey を使う

では早速 Yubikey を使っていきたいと思います。
尚、U2F が使える場合はなるべく U2F を使っていく前提となっています。

### Google

Google に関してはドキュメントなどもありますのでそちらを参考にしてください。

基本的には、「ログインとセキュリティ」 → 「2 段階認証プロセス」へ行きセキュリティキーを追加するだけです。
入力はありません。キーを挿してタッチするだけです。非常に楽ですね。

参考
http://qiita.com/yugui/items/382275bb04c3fad09ff7

### Dropbox

Dropbox も U2F に対応しています。
同様にアカウントの設定から 2 段階認証プロセスでキーを設定します。

参考
https://blogs.dropbox.com/dropbox/2015/08/u2f-security-keys/

### Yubico Authenticator

その他、2 段階認証には Google 認証システムを使うものがあります。
Yubikey NEO であればGoogle 認証システムの代わりに Yubico Authenticator を使うことができます。

Yubico Authenticator は OTP 生成のシード値などを NFC を使い Yubikey 側から読み取ります。
OTP のシード値がローカルに保存されていないスマートフォンのセキュリティホールを突かれてもシード値が盗まれることはありません。

Yubico Authenticator は YubiKey 側とデータをやりとりするために NFC を使います。
Yubico Authenticator を起動し、YubiKey を端末にタッチすることで初めてコードが表示されます。YubiKey をタッチしない状態では何も表示されません。

その他、Yubico Authenticator の基本的な使い方は Google 認証システムの使い方とほぼ同じです。
QRコードを読み込んで設定を追加していきます。
追加時も YubiKey をタッチしないと追加されません。そのため、不正なエントリを追加することも難しくなっています。

参考

https://developers.yubico.com/yubioath-android/
https://developers.yubico.com/yubioath-desktop/


## PAM を使った 2 段階認証

ここからが本題です。
ここまででも十分便利ですが、さらにあなたのマシンへのログイン、操作に対してもYubiKey で認証をかけ 2 段階認証にすることができます。
基本的には PAM を使うだけです。ここでは PAM について詳しくは触れません。

ではインストールしましょう。

```
$ packer -S yubico-pam pam_u2f
```

依存ライブラリもパッケージ化されていますので足りない場合は適時インストールして下さい。
今回使用しているバージョンは以下です。

- yubico-pam 2.19-2
- pam_u2f 1.0.1-1

これらの PAM Module やライブラリは Yubico 側が OSS として公開しています。
ディストリビューションによっていは共有ライブラリが PAM Module を読み込むディレクトリ
にインストールされていないかも知れませんので確認して下さい。

インストールが済んだら設定を行います。

## Yubico PAM Module (OTP) を使った認証

まずは `yubico_pam` を使い OTP での認証を設定してみましょう。
ログイン時にパスワードの他に、YubiKey による OTP での認証を行い、2段階認証にします。

### PAM の設定

PAM の設定は `/etc/pam.d` にあるファイルに記述します。

今回は認証部 `/etc/pam.d/system-login` に設定します。
ディストリビューションによってファイル名は変わると思います。
以下の行を追加して `yubico_pam` を読み込むようにします。

例：

```
auth      sufficient pam_yubico.so  id={Your ID} key={Your Key} authfile=/etc/yubikey_mappings
```

オプションについては参考URLを参照して下さい。
今回は `authfile` を指定して、各ユーザーの設定をまとめます。

`yubico_pam` は認証サーバーも置き換えることができますがここでは割愛します。
基本的には Yubico の提供しているサーバー、YubiCloud を使用すれば良いと思います。

id, key はあなたのキーを識別するための `Client ID` を入れます。
デフォルトの YubiCloud を使う場合には以下の URL から入手することができます。

https://upgrade.yubico.com/getapikey/

その他の詳細な設定についてはドキュメントを参照してください。

https://developers.yubico.com/yubico-pam/

### 認証用マッピングファイルの作成

次にシステム上のどのユーザーがどの YubiKey を使うのか、ユーザーと YubiKey のトークンを紐付ける設定を行います。
設定はシステム全体（全ユーザーで 1 ファイル）と個別（/home/<user>/)に設定する方法があります。
今回は全ユーザーで 1 ファイルに設定します。

設定は passwd ファイルのような形式で記述します。

`/etc/yubikey_mappings`

```
<first user name>:<Yubikey token ID1>:<Yubikey token ID2>:….
<second user name>:<Yubikey token ID3>:<Yubikey token ID4>:….
```

`Yubikey Token ID` とは OTP で出力される文字列の先頭12文字です。
YubiKey OTP は 44 文字のパスワードを生成します。そのうちの先頭12文字は固定になっています。その部分が Token ID となります。

ターミナルを開き、 YubiKey にタッチすると OTP の文字列が入力されます。その先頭12文字をコピーしてください。

```
$ cccccccgklgcvnkcvnnegrnhgrjkhlkfhdkclfncvlgj
bash: cccccccgklgcvnkcvnnegrnhgrjkhlkfhdkclfncvlgj: command not found
```

よくわからない場合は以下の URL から確認することができます。
以下の `Modhex Calculator`サ イトで OTP を選択し、YubiKey をタッチして OTP を生成し、送信します。
結果の以下の部分があなたの YubiKey の Token ID になります。

```
`Modhex encoded: XXXXXXX`
```

Modhex Calculator：
https://demo.yubico.com/php-yubico/Modhex_Calculator.php

YubiKey を複数持っている場合には、`:` で区切り複数設定することも可能です。

### 個別でマッピングファイルを作成する際の注意

個別の設定は `/home/<your>/.yubico/authorized_yubikeys` に設定します。
これは場合によってはうまく動かないかも知れません。Ubuntu などのファイルの暗号化は `/home/` 配下を暗号化する方法です。認証時には `/home` 以下はまだ暗号化されており、設定ファイルが読み込めない可能性があります。設定、運用ポリシーに合わせ、個別設定を使用するか検討してください。

### SSH + OTP を使った 2段階認証

ssh で認証する際にも 2 段階認証を設定することができます。
なんらかの原因で鍵が盗まれても YubiKey がないとログインできないよう設定することができます。

SSH で 2 段階認証するには OTP を入力するため、設定を変更する必要があります。
設定例を以下に示します。

`/etc/pam.d/sshd `

```
auth      required pam_yubico.so  id=xxxxxx key=xxxxxxxxxxxxxxxxxxxxxx authfile=/etc/yubikey_mappings  
auth      include   system-remote-login
account   include   system-remote-login
password  include   system-remote-login
session   include   system-remote-login
```

`/etc/ssh/sshd_config` 一部抜粋

```
...
UsePAM yes
PasswordAuthentication no
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
...
```

重要なのは PAM を有効化する、ChallengeResponseAuthentication を有効化する（トークンを入力するため）、AuthenticationMethods を正しく設定する点です。
設定すると以下のように 2 段階認証になります。
YubiKey をタッチし、O入力すると認証が通ります。

```
$ ssh -YC ma2@xxxxxxx
Authenticated with partial success.
YubiKey for `ma2':
```

## Challenge Response を使ったローカル認証

OTP を使う方法の欠点はオンラインではないと認証できない点です。
ラップトップ環境などネットワークがあるかどうかわからない場合でもローカル認証することができます。
Challenge Response を使った場合はタッチするなどのアクションは不要です。
YubiKey が刺さっていない限り認証が失敗します。

### PAM の設定

Challenge Response を使用する場合には `mode` を設定する必要があります。
`mode` に `challenge-response` を設定し、 challenge file のパスを設定します。

例：

```
auth      sufficient pam_yubico.so  mode=challenge-response chalresp_path=/etc/yubico
```

その他の詳細な設定についてはドキュメントを参照してください。

https://developers.yubico.com/yubico-pam/

### Challenge-Response をプログラムする

YubiKey に Challenge-Response を使うようにプログラムします。
例では slot2 に設定しています。

```
$ ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 -oserial-api-visible
...
Commit? (y/n) [n]: y
$
```

### Challenge File の作成

次に challenge file を作成します。

```
$ mkdir $HOME/.yubico
$ ykpamcfg -2 -v
...
Stored initial challenge and expected response in '/home/user/.yubico/challenge-123456'.
$
```

PAM の設定で `chalresp_path` を設定しない場合はこのパスのファイルを使用します。

システムで集中管理する場合には PAM で設定したパスに challenge file を移動させます。

```
$ mkdir /etc/yubico
$ chmod +t /etc/yubico
$ chmod 777 /etc/yubico
$ mv /home/user/.yubico/challenge-####### /etc/yubico/username-#######
...

```

これでローカル認証できるようになります。

例えば PAM で `sudo` に Challenge Response を設定した場合、パスワードが正しくても YubuKey が刺さっていない限り認証が通らなくます。

## pam_u2f を使った認証

ローカル認証にはもうひとつ FIDO U2F を使う方法があります。
Challenge-Response では slot をひとつ潰してしまいますが、U2F は slot を消費せず使うことができます。

### pam_u2f の設定

`pam_u2f` の設定例を以下に示します。
基本的にな使い方をする分には `yubico_pam` と同様そんなに設定することはありません。

```
auth       required   pam_u2f.so           authfile=/etc/u2f_mappings
```

場合によっては `cue` オプションを設定した方が良いかも知れません。
`pam_u2f` はデフォルトで YubiKey にタッチしてなどのメッセージを表示をしません。
（YubiKey は点灯しますが）
そのため、入力待ちになっているかどうかがわからない事があります。
`gdm` などではパスワード入力のテキストボックスが表示されません。

`yubico_pam` 同様に詳細にカスタマイズすることも可能です。
その他の設定については以下を参照して下さい。

設定など：
https://developers.yubico.com/pam-u2f/

### 認証用マッピングファイルの作成

OTP の時と同様にマッピングファイルを作成します。
OTP と同様システム全体で 1 つのマッピングファイルを使用します。

`/etc/u2f_mappings`

フォーマットは以下のようなフォーマットになります。

```
<username1>:<KeyHandle1>,<UserKey1>:<KeyHandle2>,<UserKey2>:...
<username2>:<KeyHandle1>,<UserKey1>:<KeyHandle2>,<UserKey2>:...
```

デフォルトの設定であれば KeyHandle, UserKey は以下のコマンドで生成できます。

```
$ pamu2fcfg -u <username>  
```

生成された KeyHandle, UserKey のセットを記述します。
これで設定完了です。

PAM の設定で `sudo` に設定し、`cue` オプションを有効にした場合は以下のように表示されます。

```
$ sudo ls
Please touch the device.

```

## YubuKey を抜いたらスクリーンロックする

その他にもこのようなことができるという一例を紹介したいと思います。

YubiKey で認証を 2 段階にしたのはいいですが、ログインしている状態では全てのリソースに触れてしまいます。
離席時などにもガードをかけれるように YubiKey が抜かれたら、スクリーンロックをかけ、再度認証が必要になるよう設定します。
スクリーンロックからの回復は通常のログインと同じです。
2 段階認証を設定していればYubiKey がないとロックが解除できません。

### シリアルキーの確認

では設定をしてみます。
YubiKey にはそれぞれキーに特有のID、シリアルキーが存在しています。
まずあなたの YubiKey が抜かれた場合のみロックがかかるようにするため、 YubiKey の情報を確認します。

以下のコマンドを実行し、 YubiKey を抜き差しして下さい。

```
$ udevadm monitor --environment –udev
```

その中に `ID_SERIAL_SHORT` があるか確認して下さい。
その値があなたの YubiKey の背面に書かれているキーと一致するか確認して下さい。

### シリアルキーが表示されない場合

シリアルキーが表示されない場合は `yubikey-personalization-gui` を起動して表示できる
ように設定します。

`yubikey-personalization-gui` を起動したら Settings を選択し、USB descriptor にチェック
を入れ設定をどちらかの slot に保存します。
再度上記の手順で確認すると `ID_SERIAL_SHORT` が表示できていると思います。

### ロックをかける

あとは `ID_SERIAL_SHORT` を含めた条件で udev のルールを記述します。

`/etc/udev/rules.d/85-yubikey.rules`

```
# Yubikey Udev Rule: running a bash script in case your Yubikey is removed
ACTION=="remove", ENV{ID_VENDOR_ID}=="1050", ENV{ID_MODEL_ID}=="0116", ENV{ID_SERIAL_SHORT}=="00000000000", RUN+="/usr/local/bin/yubikey-lock"
```

上記では YubiKey が抜かれると yubikey-lock のスクリプトが呼ばれます。
スクリプト内でロックするように設定します。
デスクトップ環境によってロックの方法が変わります。
例は GNOME3 の場合です。

`/usr/local/bin/yubikey-lock`

```
#!/bin/bash

user=`ps aux | grep -v root | grep gdm-x-session | head -n 1 | awk '{print $1}'`
sessionid=`/bin/loginctl list-sessions | grep ${user} | awk '{print $1}'`

if [ -z "$(lsusb | grep Yubico)" ]; then
    logger "YubiKey Removed"
    /bin/loginctl lock-session $sessionid
fi
```

これで設定完了です。
YubiKey が抜かれるとロックスクリーンが表示されるようになります。
PAM に設定で `system-login` に required で設定すれば YubiKey が無い以上パスワードがあっていようとも認証は必ず失敗します。

## 最後に

ざっと簡単に YubiKey の使い方、設定を紹介してみました。
YubiKey を使い始めて思ったことは思った以上にカスタマイズ可能でかつカジュアルに扱えるという点です。
私は U2F、 slot1 に OTP, slot2 に Static-Password を設定して使っています。

次回は PGP 鍵を YubiKey に埋め込み SSH 鍵として使用する方法を紹介したいと思います。