Linuxサーバへの二要素認証

## はじめに

自分向けの二要素認証設定メモ

業務上で二段階認証なり二要素認証しろって話がしょっちゅう出てくるのでお試しでLinuxサーバへの二要素認証(2FA)を試してみた。
※今回選択したLinuxのディストリビューションはRockyLinux8を利用。

今回は知識要因と所持要因を使って2FAをしている。

二要素認証（2FA）とは、セキュリティを強化するために2つの異なる認証方法を要求するシステムのことです。これらの方法は一般的に以下の3つのカテゴリーのうちの2つを含みます：

知識要因（何かユーザーが知っているもの）：例えば、パスワードやPINコード。
所持要因（何かユーザーが持っているもの）：例えば、携帯電話やトークンデバイス。
生体要因（ユーザーの身体的特徴）：例えば、指紋や顔認識。

SSHログインでパスワード（知識要因）とGoogle Authenticatorを使用する場合、Google Authenticatorは所持要因（通常はスマートフォンにインストールされるアプリ）として機能。ユーザーはまずパスワードを入力し、次にGoogle Authenticatorアプリが生成する一時的なコードを入力する。

## 手順

###利用するパッケージをインストール(Google authenticatorやQRコードを生成するためのライブラリ)
※dnf使うべきだったか?

```
yum install epel-release
yum install google-authenticator
yum install qrencode
```

## SSHDの設定変更

 /etc/ssh/sshd_configの中身を書き換える。
ChallengeResponseAuthenticationの部分がデフォルトではnoになっているのでyesに変更。

```
# Change to no to disable s/key passwords
ChallengeResponseAuthentication yes
#ChallengeResponseAuthentication no
```

## 

```
systemctl restart sshd
```

## PAM設定
SSH接続の際にGoogle Authenticator PAMモジュールを呼び出す設定を追加。
nullokは認証コードなしでログインできることを許可する設定。
段階的にGoogleAuthenticatorを導入するような場合は必要。全てのユーザが二要素認証を使う
環境になれば不要となるが・・・。
echo_verification_codeは入力時に認証コードを表示できるようになる。

```
auth required pam_google_authenticator.so nullok echo_verification_code
```

##Google Authenticator の設定

二要素認証を必要とするユーザ(今回はtestというユーザを作った)で以下コマンド( google-authenticator)を実行すると対話形式で設定をすることになる。全てyにしてOK
・パスの保存先
・同じ確認コードを複数回使うことを禁止する設定
・クライアント(GoogleAuthenticatorをインストールした端末)とサーバ間で最大4分のズレを許容する設定
・30秒ごとに3回以上のログインを試行しないように制限する設定


```
google-authenticator

Do you want authentication tokens to be time-based (y/n) y
Warning: pasting the following URL into your browser exposes the OTP secret to Google:

この後QRコード表示(qrencodeのパッケージを入れていないと出てこない)
スマホアプリ等でQRコードを読み取ってGoogleAuthenticatorに登録

Your new secret key is: xxxxxxxxxxxxxx
Enter code from app (-1 to skip): 123456(GoogleAuthenticatorに出力される6桁の数字を投入)
Code confirmed
Your emergency scratch codes are:(緊急用のコード)
  12345678
  12345678
  12345678
  12345678
  12345678

Do you want me to update your "/home/test/.google_authenticator" file? (y/n) 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

By default, a new token is generated every 30 seconds by the mobile app.
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. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.
Do you want to do so? (y/n) 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


```

## ログイン試行

二要素認証を有効にしたユーザ(test)でサーバにログイン。
パスワード認証が完了した後にGoogleAuthenticatorの認証コードを投入してログイン完了。

```
ssh test@192.168.1.23
(test@192.168.1.23) Password:
(test@192.168.1.23) Verification code: 399615
Activate the web console with: systemctl enable --now cockpit.socket

Last failed login: Sun Nov 26 09:38:18 EST 2023 from 192.168.1.22 on ssh:notty
There were 9 failed login attempts since the last successful login.
Last login: Sun Nov 26 09:11:52 2023
```


## まとめ
二要素認証でのSSHログインの仕方の確認ができた。
が、この方法だとPAMのnullok設定の部分どうするかリアルで運用する場合は一工夫必要だなと感じた。
二要素認証でないとサーバのログインを許さん!とした場合、
この手法だと対象ユーザは最初にgoogle-authenticatorコマンドをうってもらって登録してらもわらないといけないのだが例えば以下のような考慮が必要になりそう。
・一時的にnullokで対応してもらう
・管理者がユーザーにバーコードを配る?
・ローカルのサーバの前に来てもらって各ユーザに設定してもらう

今後はRadiusサーバの認証＋GoogleAuthenticatorを試す予定