多要素認証で安全なリモートアクセスVPN - Cisco AnyConnect+YubiKey -

## はじめに
働き方改革や新型コロナウイルス対策の一環としてテレワークが日常化する中、不正アクセスによる情報漏洩が後を絶ちません。テレワークでは、自宅と会社間を接続して利用されることの多いリモートアクセスVPNを、より安全に運用することが課題となっています。
この課題を解決するために有用な手段として、多要素認証（Multi Factor Authentication 以下、MFA）が挙げられます。
本記事では、Cisco社のVPNルーターを利用してリモートアクセスVPNを行う際のログイン認証をMFA化することを目的としています。

>下記、**RADIUS Server構築** と **pam_yubicoのインストール**についてはRadius認証をMFA化する内容です。Cisco製品以外のVPNサーバーでも応用が可能ですので、必要に応じてご参照ください。

## Why MFA?
　一般的なログイン認証には、ユーザー名（ID）とパスワードを用います。しかし、パスワードは一度漏洩してしまうと、意図しない他ユーザー（悪意を持ったユーザも含む）でも認証が可能となり、情報漏洩の原因になります。
　そこで、認証に必要な要素を複数（多要素）にすることで、万が一パスワードが漏洩した場合でも、パスワード以外の他要素が揃わないとログイン認証ができないMFA化が、情報漏洩対策には非常に有効な手段となります。

## MFAの認証要素
今回のMFA認証要素は、利用者が『**知っている要素**』と『**持っている要素**』の二要素でMFA化するための手順を紹介します。
##### MFA構成要素
> - **知っている要素**  = パスワード
> - **持っている要素**  = 認証器（**YubiKey**<sup>※1</sup>）

##### **YubiKey**<sup>※1</sup>
Yubico社が提供しているハードウェア認証デバイスです。現在、ユーザー認証で利用される主要なプロトコルOTP、FIDO、OAuth、PIV、OpenPGP等に対応している製品です。
RDIUS認証ではYubico OTP（One Time Password:一度きりの使い捨てパスワード）という仕組みを利用します。

>![YubiKey.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/792709/6e5f154a-ef1c-28c0-befc-bbc812451a59.png)
YubiKeyのご紹介：https://www.meettheyubikey.com/technology/detail.php?eid=00003

## 運用イメージ：
リモートアクセスVPNのログインをMFA化することにより、運用イメージは次の動画のようになります。（Yubico Blogより）
<br>

[![Secure VPN access with MFA](https://img.youtube.com/vi/TWsambmmUxs/0.jpg)](https://www.youtube.com/embed/TWsambmmUxs "Secure VPN access with MFA")

>参照(yubico blog)：
https://www.yubico.com/blog/5-ways-the-yubikey-can-protect-your-remote-workforce-from-phishing-and-other-attacks/


## 構成概要

Cisco ASA5506-X(VPNルーター) と AnyConnect(VPNクライアント)で構成したリモートアクセスVPN環境を元に、YubiKeyを用いてMFAを構成します。
Cisco ASAはRADIUS Clientとして動作可能です。アカウントの認証や認可を外部のRADIUS Serverに委ねることができ、MFAなどの認証を拡張する際に必要な機能となります。今回は、YubiKeyによるMFAを行うRADIUS Serverを構築し、Cisco ASAと認証連携する流れとなります。

##### システム構成図
実験環境は、以下の構成でリモートアクセスVPNを構築しています。
![System構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/792709/ad4c0601-4535-4598-a8e6-22e5152a70f2.png)

##### Cisco ASA Server
- VPNルーターとしてCisco ASA5506-Xを使用しています。

##### AnyConnect
- 利用者のリモート環境にインストールしてVPN接続するためのソフトです。
- WindowsやmacOSをはじめ、LinuxやiOS、Androidに対応しています。

##### FreeRADIUS
- RDIUS Serverを構築する際に利用するコンポーネントです。

##### pam_yubico
- YubiKeyの認証を行うことが可能なPAM(Pluggable Authentication Modules)です。PAMは、UNIX(Linux)で利用される認証の仕組みで、様々な認証方法で構成することが可能です。
pam_yubicoはyubico社が無償で提供しています。詳細は以下をご参照ください。
https://developers.yubico.com/yubico-pam/

##### 主要コンポーネント
>1.リモートアクセスVPN Server(Cisco ASA5506-X)
> - ASDM		：asdm-7141-48.bin
>
>2.VPN Clientソフトウェア
> AnyConnect
> - Windows用		：anyconnect-win-4.8.03052-webdeploy-k9.pkg
> - macOS用		：anyconnect-mac-4.8.03052-webdeploy-k9.pkg
>
>3.RADIUS Server
> - OS : CentOS 8		：4.18.0-193.6.3.el8_2.x86_64
> - FreeRADIUS		  ：FreeRADIUS Version 3.0.17
> - pam_yubico		  ：pam_yubico-2.26-4.el8.x86_64.rpm

## RADIUS Server構築
今回、RADIUS Serverで使用したのはCentOS 8(4.18.0-193.6.3.el8_2.x86_64)です。
※OSは既にインストール済みとして説明します。
カーネル、パッケージ情報は事前にアップデートして下さい。
カーネルの更新が行われた場合は、変更内容を反映させるため再起動する必要があります。

```shell:bash
sudo dnf -y update
sudo dnf -y update kernel *
sudo reboot
```

#### ユーザーアカウントの追加
リモートアクセスVPNのユーザーアカウントを作成します。ここでは、testuser1、testuser２というアカウントを追加しています。(パスワードを"password"と設定していますが、システムポリシーに従って決定して下さい)

```shell:bash
sudo useradd testuser1
sudo passwd testuser1
ユーザー testuser1 のパスワードを変更。
新しいパスワード:
新しいパスワードを再入力してください:

sudo useradd testuser2
sudo passwd testuser2
ユーザー testuser2 のパスワードを変更。
新しいパスワード:
新しいパスワードを再入力してください:
```

#### freeRADIUSのインストール
freeRADIUSと動作確認を行うためのユーティリティをインストールします。

```shell:bash
sudo dnf -y update
sudo dnf install -y @freeradius freeradius-utils
```
#### RADIUSセッティング
1./etc/raddb/radiusd.confをバックアップし、RADIUSデーモンからPAMモジュールを呼び出せるようにroot権限を付与します。

```shell:bash
cp -piv /etc/raddb/radiusd.conf /etc/raddb/radiusd.conf_`date "+%Y%m%d"`.org
sudo vi /etc/raddb/radiusd.conf
```

>user = radiusd
>group = radiusd
>  ↓
>user = root
>group = root

2./etc/raddb/sites-available/defaultをバックアップし、RADIUS認証でPAMを有効化します。

```shell:bash
cp -piv /etc/raddb/sites-available/default /etc/raddb/sites-available/default_`date "+%Y%m%d"`.org
sudo vi /etc/raddb/sites-available/default
```
>`#`
>`#` Pluggable Authentication Modules.
>`#` pam
  ↓
>`#`
>`#` Pluggable Authentication Modules.
> pam

3./etc/raddb/clients.confをバックアップし、ファイルの末尾に次のclient定義を追加し、IPアドレスレンジとsecretを設定します。

```shell:bash
cp -piv /etc/raddb/clients.conf /etc/raddb/clients.conf_`date "+%Y%m%d"`.org
sudo vi /etc/raddb/clients.conf
```
>client remote_access_vpn_auth {
>`    `ipaddr = 192.168.1.0/24
>`    `secret = secret-key
>}

※例ではremote_access_vpn_authという名前で、IPアドレスレンジとsecretを設定していますが、環境に合わせて設定してください。


4./etc/raddb/usersをバックアップし、Auth-TypeをPAMに変更します。

```shell:bash
cp -piv /etc/raddb/users /etc/raddb/users_`date "+%Y%m%d"`.org
sudo vi /etc/raddb/users
```
>DEFAULT        Auth-Type := System
>  ↓
>DEFAULT        Auth-Type := PAM

5.シンボリックリンクを追加し、PAMモジュールを有効化します。

```shell:bash
$ sudo ln -s /etc/raddb/mods-available/pam /etc/raddb/mods-enabled/pam
```

6.RADIUSサービスを有効化して起動します。

```shell:bash
  $sudo systemctl enable --now radiusd.service
```

## pam_yubicoのインストール

ユーザーに割り当てたYubiKeyの認証を行うためのPAM(Pluggable Authentication Modules)をインストールします。

```shell:shell
$ cd /tmp
$ wget https://dl.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/l/libyubikey-1.13-11.el8.x86_64.rpm
$ wget https://dl.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/y/ykclient-2.15-9.el8.x86_64.rpm
$ wget https://dl.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/y/ykpers-1.20.0-3.el8.x86_64.rpm
$ wget https://dl.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/p/pam_yubico-2.26-4.el8.x86_64.rpm
$ rpm -Uvh libyubikey-1.13-11.el8.x86_64.rpm
$ rpm -Uvh ykclient-2.15-9.el8.x86_64.rpm
$ rpm -Uvh ykpers-1.20.0-3.el8.x86_64.rpm
$ rpm -Uvh pam_yubico-2.26-4.el8.x86_64.rpm
$ rm -f *.rpm
```

PAMモジュールが正しくインストールされているか確認します。

```shell:bash
find / -name "pam_yubico.so" -print
/usr/lib64/security/pam_yubico.so
```

YubiKey Mappingファイルを作成して設定します。

```shell:bash
sudo vi /etc/yubikey_mappings
```
pam_yubico.soが認証できるようにユーザーとYubiKeyを紐付け、/etc/yubikey_mappingsという名前でマッピングファイルを作成します。
ファイル内容は以下のフォーマットで指定します。
>ユーザー1:トークンID1:[トークンID2]...
>ユーザー2:トークンID1:[トークンID2]...
>...


今回は、上記 **ユーザーアカウントの追加** で作成したtestuser1、testuser２にそれぞれ別のYubiKeyを割り当てます。
実際のトークンIDはお手持ちのYubiKeyに設定されている値を指定してください。
※トークンIDは、YubiKeyのボタンを押したときに発行されるOTPの先頭12文字です。

>testuser1:xxxxxxxxxxxe
>testuser2:xxxxxxxxxxxf

RDIUS認証で使用する認証定義ファイル/etc/pam.d/radiusdを現在日付でバックアップして編集します。

```shell:bash
cp -piv /etc/pam.d/radiusd /etc/pam.d/radiusd_`date "+%Y%m%d"`.org
sudo vi /etc/pam.d/radiusd
```
RDIUS認証で使用する認証定義ファイル/etc/pam.d/radiusdを編集します。
radiusdの先頭行に以下の定義を追加します。
>auth required pam_yubico.so id=16 debug authfile=/etc/yubikey_mappings


## YubiKeyによるMFA認証の動作確認
***
RADIUS Serverが正常に起動していることを確認するためにはradtestコマンドを利用します。
第二引数は、パスワードとYubicoOTPを繋ぎ合わせた文字列を指定します。
>radtest USERNAME **パスワード+YubicoOTP** DST-ADDRESS SRC-PORT SHARED-SECRET

実行後、成功すればReceived Access-Acceptが表示されます。Received Access-Rejectの場合は、/var/log/radius/radius.logの内容を確認し、拒否された原因を確認します。

```shell:bash
$ radtest testuser1 passwordxxxxxxxxxxxevgdgthvebvgdenllcdnfbfijhdvcrefu 192.168.1.251 123456 secret-key
Sent Access-Request Id 59 from 0.0.0.0:35079 to 192.168.1.251:1812 length 122
	User-Name = "testuser1"
	User-Password = "passwordxxxxxxxxxxxevgdgthvebvgdenllcdnfbfijhdvcrefu"
	NAS-IP-Address = 127.0.0.1
	NAS-Port = 123456
	Message-Authenticator = 0x00
	Cleartext-Password = "passwordxxxxxxxxxxxevgdgthvebvgdenllcdnfbfijhdvcrefu"
Received Access-Accept Id 59 from 192.168.1.251:1812 to 192.168.1.251:35079 length 20
```


## ASA5506とRADIUS Serverの連携(CUI)

ASA5506-XとRadius Serverを連携します。Radius ServerのIPアドレスは192.168.1.251としています。
ASA5506のLAN側を192.168.1.0/24としてinboundという名称を付けて、server_groupを"YUBIKEY-RADIUS-AUTH"として定義しています。

>aaa-server *YUBIKEY-RADIUS-AUTH* protocol radius
> accounting-mode *YUBIKEY-RADIUS-AUTH* simultaneous
>aaa-server *YUBIKEY-RADIUS-AUTH* (*inbound*) host 192.168.1.251
> key ***secret-key***
> authentication-port 1812
> accounting-port 1813
>aaa authentication ssh console LOCAL
>aaa authentication http console LOCAL

※keyにはRadius Serverで設定したシークレット(***secret-key***)を設定します。