SoftEther + (Radius + Google-Authenticator) でMFA認証VPN

# 前置き
「SoftEtherのVPN接続でワンタイムパスワードにできる？」
できたのでメモ。

# 【AWS環境編】
サーバはAWS EC2(Amazonlinux)で用意。t2.microで。
SoftEtherとRadiusはサーバを分けて構築。
 -> ユースケースによってはまとめてもよい

## SG設定
【SoftEther側】

|protocol|port|source|
|:--:|:--:|:--:|
|tcp|22(ssh)|ローカルPC|
|udp|4500(VPN)|0.0.0.0/0|
|udp|500(VPN)|0.0.0.0/0|

【Radius側】

|protocol|port|source|
|:--:|:--:|:--:|
|tcp|22(ssh)|ローカルPC|
|udp|1812-1813(Radius)|SoftEtherサーバ|
※ssh接続は今回雑に、どっちのサーバも直。

【VPN接続先EC2】

|protocol|port|source|
|:--:|:--:|:--:|
|全て|全て|SoftEtherサーバ|

# 【SoftEther編】
以下を参考にしています。
https://qiita.com/showwin/items/92861057a8b62611444d

## インストール
```
# 以下すべてrootで行います
$ sudo su –

# make で必要
yum install -y gcc

# ソースコードのDL及び解凍
# 差し当たって最新のRTM版を選択
wget http://jp.softether-download.com/files/softether/v4.25-9656-rtm-2018.01.15-tree/Linux/SoftEther_VPN_Server/64bit_-_Intel_x64_or_AMD64/softether-vpnserver-v4.25-9656-rtm-2018.01.15-linux-x64-64bit.tar.gz
tar -zxvf softether-vpnserver-v4.25-9656-rtm-2018.01.15-linux-x64-64bit.tar.gz

# ビルド: ライセンス同意の文言は全て1(承諾)で。
cd vpnserver
yes 1 | make

# ビルド後のデータ移動/権限操作
cd
mv vpnserver /usr/local
chmod 600 /usr/local/vpnserver/*
chmod 700 /usr/local/vpnserver/vpncmd
chmod 700 /usr/local/vpnserver/vpnserver
```
```
# SoftEtherコマンドラインでインストール完了確認
/usr/local/vpnserver/vpncmd /TOOLS /CMD check
.
.
.
'カーネル系' のチェック中...
              [合格] ○
'メモリ操作系' のチェック中...
              [合格] ○
'ANSI / Unicode 文字列処理系' のチェック中...
              [合格] ○
'ファイルシステム' のチェック中...
              [合格] ○
'スレッド処理システム' のチェック中...
              [合格] ○
'ネットワークシステム' のチェック中...
              [合格] ○
.
.
.
```
こんな感じ。vpncmdの引数等は以下マニュアル内、6.2.3の項を参照。
https://ja.softether.org/4-docs/1-manual/6/6.2
## Daemon登録

```/etc/init.d/vpnserver
#!/bin/sh
# chkconfig: 2345 99 01
# description: SoftEther VPN Server
DAEMON=/usr/local/vpnserver/vpnserver
LOCK=/var/lock/subsys/vpnserver
test -x $DAEMON || exit 0
case "$1" in
start)
$DAEMON start
touch $LOCK
;;
stop)
$DAEMON stop
rm $LOCK
;;
restart)
$DAEMON stop
sleep 3
$DAEMON start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0
```

権限変更と起動テスト

```
chmod 755 /etc/init.d/vpnserver
/sbin/chkconfig --add vpnserver
service vpnserver start
```

## SoftEther設定
SoftEtherコマンドラインに対する操作。選択肢は以下3つ。

- 対話型で進める
- 引数+ファイルによる"バッチ処理モード"を利用
- vpn_server.configを直で触る

今回はバッチ処理モードでまとめる方向。シェルスクリプト風にコマンド羅列されたtxtファイルを用意する。

```softether-radius.txt
HubCreate {HUBNAME} /PASSWORD:{PASSTOHUB}
Hub {HUBNAME}
UserCreate * /GROUP:none /REALNAME:none /NOTE:none
RadiusServerSet {PRIVATEIP} /SECRET:{SECRET_WITH_RADIUS} /RETRY_INTERVAL:1000
IPsecEnable /L2TP:yes /L2TPRAW:no /ETHERIP:no /PSK:{SECRET_WITH_DEVICE} /DEFAULTHUB:{HUBNAME}
SecureNatEnable
HubList
UserList
RadiusServerGet
```
以下を任意に設定した状態で用意。
{HUBNAME}: 仮想Hub名。割となんでも良い。
{PASSTOHUB}: Hubへの接続pass。
{PRIVATEIP}: Radiusの動くサーバのホスト名。Ex.172.12.34.56
{SECRET_WITH_RADIUS}: Radius側へ設定する共有シークレット
{SECRET_WITH_DEVICE}: VPN接続元端末に設定するパス

引数込めて実行。

```
/usr/local/vpnserver/vpncmd localhost /SERVER /IN:softether-radius.txt
```
上から順番に処理される。

- パスワード設定のされた仮想Hub作成
- 作成された仮想Hubへの接続
- アスタリスクなダミーユーザを作成
- Radius認証の有効化
- L2TP/IPsec設定
- SecureNAT 機能の有効化
- 仮想Hub設定確認
- ユーザ設定確認
- Radius設定確認

ラスト3行は確認用なので省略可。
L2TP/IPsecやSecureNATは接続元の端末(Macなど)の都合で必要となる設定。

これでSoftEtherに接続があった場合、全てのユーザーはRadius側の判断へと回されるように。
(個別にユーザ設定も可能だが、その場合ユーザ追加等はRadius側と二重管理になる)

# 【Radius編】
こちらは以下を参照
https://www.virment.com/radius-server-configuration/

## インストール
こちらもrootで...

```
yum -y install freeradius freeradius-utils \
            git gcc pam-devel \
            qrencode qrencode-libs qrencode-devel autoconf automake libtool
```

## 各種設定ファイル操作
結構多い。
/etc/raddb/radiusd.conf
/etc/raddb/users
/etc/raddb/sites-available/default
/etc/pam.d/radiusd
/etc/raddb/clients.conf
### /etc/raddb/radiusd.conf
```/etc/raddb/radiusd.conf
#user = freerad　（変更前）
#group = freerad （変更前）
user = root （変更後）
group = root（変更後）

#  Port on which to listen.
	#  Allowed values are:
	#	integer port number (1812)
	#	0 means &quot;use /etc/services for the proper port&quot;
        #port = 0 (変更前)
         port = 1812 (変更後)

#  Log authentication requests to the log file.
	#
	#  allowed values: {no, yes}
	#
        #auth = no　(変更前)
         auth = yes (変更後)

         auth_badpass = yes(変更後)
         auth_goodpass = yes(変更後)
```
portの部分はOSによって `/etc/raddb/proxy.conf` に分かれて記述されていたりも。
ログ出力も設定している。デフォルトの出力先は `/var/log/radius/radius.log`

### /etc/raddb/users

```

DEFAULT    Group != "radius-enabled", Auth-Type := Reject
       Reply-Message = "Your account has been disabled."
DEFAULT        Auth-Type := PAM
```
普通のRadiusユーザー登録とは違う流れなので注意
### /etc/raddb/sites-available/default

```/etc/raddb/sites-available/default
PAM  # コメントアウトを消す
```

### /etc/pam.d/radiusd
```/etc/pam.d/radiusd
#%PAM-1.0
# auth       include	password-auth
# account    required	pam_nologin.so
# account    include	password-auth
# password   include	password-auth
# session    include	password-auth
auth    requisite /usr/local/lib/security/pam_google_authenticator.so
account required  pam_permit.so
session required  pam_permit.so
```
`/usr/local/lib/security/pam_google_authenticator.so` はGoogle-Authenticatorのインストール後、絶対パスがあっているか念のため確認する。

### /etc/raddb/clients.conf
末尾に追記

```/etc/raddb/clients.conf
client 10.0.0.0/16 {  # VPC の CIDR         
        secret          = {SECRET_WITH_RADIUS}   # SoftEtherで設定していた共有シークレット
        shortname       = from-vpc               # ログに出てくる以上の意味はない
}
```

起動。

```
service radiusd start
```
## Google-Authenticator導入
※ radiusサーバに同居。
https://blog.enokawa.co/2018/01/11/login-to-amazon-workspaces-with-google-authenticator/
やはりrootってしまう

```
git clone https://github.com/google/google-authenticator-libpam.git
cd google-authenticator-libpam/
./bootstrap.sh
./configure
make
make install
```
## 接続ユーザ作成
RadiusサーバのOSユーザ ＝ VPN接続ユーザ となる

```
groupadd radius-enabled
useradd -g radius-enabled user001
```
既存のユーザに対しては以下で所属グループを追加。

```
# ユーザーをグループのメンバーに追加
gpasswd -a ユーザー名 グループ名
```
## ユーザ別MFA設定
```
sudo -u user001 /usr/local/bin/google-authenticator
```
### 1.「時間ベースの二段階認証にするか」に y
```
Do you want authentication tokens to be time-based (y/n) y
```
### 2.ターミナル上にQRコードが表示されるので、アプリに読み込ませる
もしくは、同時に発行されるsecret keyを入力
### 3.アプリに出力されるワンタイムパスワードを入力
```
Enter code from app (-1 to skip):123456
```
 - 「Code confirmed」の表示と「emergency scratch codes」を確認
 - emergency scratch codes: 緊急用の使い捨てコード。

### 4.「設定ファイルを保存するか」に y
```
Do you want me to update your "~/.google_authenticator" file (y/n) y
```
### 5.「一度使ったワンタイムパスワードの再利用を禁止」に y
```
Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y
```
### 6.「ワンタイムパスワードの有効期限を4分にするか」に y
- yを選択すると4分間に8つのキーで認証可能
- nを選択すると1.5分間に3つのキーで認証可能

```
By default, tokens are good for 30 seconds and in order to compensate for
possible time-skew between the client and the server, we allow an extra
token before and after the current time. If you experience problems with poor
time synchronization, you can increase the window from its default
size of 1:30min to about 4min. Do you want to do so (y/n) y
```
### 7.「30秒間に可能なログイン試行回数を3回に制限するか」に y
```
If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting (y/n) y
```
### 8.Radiusサーバ内接続テスト
```
radtest {登録者ユーザ名}　{ワンタイムパスワード} {踏み台サーバPrivateIP} 1812 {SECRET_WITH_RADIUS}

# 実行例
radtest user001 060526 172.12.34.56 1812 testing123
Sent Access-Request Id 84 from 0.0.0.0:54910 to 172.12.34.56:1812 length 77
	User-Name = "user001"
	User-Password = "060526"
	NAS-IP-Address = 172.12.34.56
	NAS-Port = 1812
	Message-Authenticator = 0x00
	Cleartext-Password = "060526"
Received Access-Accept Id 84 from 172.12.34.56:1812 to 0.0.0.0:0 length 20
```
`Received Access-Accept` 表示があれば認証成功

##### ※ google-authenticatorの緊急用使い捨てコード(emergency scratch codes)について

- 各ユーザの `~/.google_authenticator` で確認ができる。
- ここで制御、というよりは、使用済みかどうかの判断にだけ使っている様子。
    - 使用済み->削除される
    - 別な文字列を入れても意味がない
        - コメントアウトすると使用済み扱いになる
    - 削除された分を書き込むと再度使用可能になる

```~/.google_authenticator
XXXXXXXXXXXXXXXXXXXXXXXXXX
" RATE_LIMIT 3 30
" WINDOW_SIZE 17
" DISALLOW_REUSE
" TOTP_AUTH
12345678
23456789
34567890
45678901
56789012
```
---
既存OSユーザ(秘密鍵sshできる)に追加設定して行く場合、ssh接続には直接影響しないのでとりあえず足せていける。
逆にsshにもMFAやりたい場合、pam.dとsshdの設定ファイルをそれぞれ変更する必要がある(以下参照)
https://blog.k3n.link/entry/add-2fa-to-ssh-authentication

## VPN接続
MacからのVPN接続は以下を参照。
https://ja.softether.org/4-docs/2-howto/L2TP_IPsec_Setup_Guide/5

パスワード：MFAアプリに出力されるワンタイムパスワード
共有シークレット: SoftEther側に設定した `{SECRET_WITH_DEVICE}`

# 【おまけ】　SoftEtherとRadiusのサーバをまとめる場合
変更点は以下。

1.AWS:SG
・Radius側に設定していた `udp:1812` が不要
・代わりに自SG内の許可設定を追加
2. `{RadiusサーバPrivateIP}`
・変更というか、SoftEtherサーバ=Radiusサーバ となるのでそのまま自身のIPを設定する