Amazon Linux 2023 + FreeRADIUS で WorkSpaces の MFA を構築する

記事タイトルとURLをコピーする

はじめに

こんにちは、WorkSpacesのログイン認証でMFAを導入する方法について検証しましたので、必要に応じて参照いただけると幸いです。

Amazon WorkSpaces で多要素認証(MFA)を導入する場合、RADIUS サーバーが必要になります。

本記事では、Amazon Linux 2023(AL2023)上に FreeRADIUS + Google Authenticator を構築し、WorkSpaces の MFA を実現する手順を解説します。

全体構成図

構成図

通信フロー

  1. ユーザーがWorkSpaces クライアントで ID・パスワード・MFA コードを入力
  2. Managed AD が パスワード認証を実施(ここで ID/PW の検証は完了)
  3. Managed AD が OTPコード部分だけを RADIUS サーバー(FreeRADIUS)に転送(UDP 1812)
  4. FreeRADIUS が PAM 経由で Google Authenticator の OTPを検証
  5. 認証結果(Accept / Reject)を Managed AD に返却
  6. WorkSpaces へのログインが許可または拒否される

ネットワーク要件

通信 プロトコル ポート 方向
RADIUS 認証 UDP 1812 Managed AD → FreeRADIUS

前提条件

  • ディレクトリサービス: AWS Managed Microsoft AD が構築済み
    • ※ Simple AD は MFA(RADIUS 連携)非対応
  • EC2: Amazon Linux 2023、Managed AD と同一 VPC 内に配置
  • セキュリティグループ: UDP 1812 が Managed AD の DC から許可されていること
  • Managed AD: テスト用ユーザーが作成済みであること
  • WorkSpaces: 少なくとも1台が起動済み(動作確認用)
  • スマートフォン: Google Authenticator アプリがインストール済み

FreeRADIUS のインストール

パッケージのインストール

FreeRADIUS及びGoogle Authenticator、QRコード出力のためのパッケージをインストールします。

# FreeRADIUS 本体とユーティリティをインストール
sudo dnf install -y freeradius freeradius-utils

# Google Authenticator PAM モジュールをインストール
sudo dnf install -y google-authenticator qrencode

尚、QRコードを出力する方法については以下ブログもご参照ください。

blog.serverworks.co.jp

インストール確認

# バージョン確認
radiusd -v

# 設定ファイルの場所を確認
ls /etc/raddb/

主な設定ファイル:

ファイル 用途
/etc/raddb/radiusd.conf メイン設定
/etc/raddb/clients.conf RADIUS クライアント定義
/etc/raddb/mods-available/pam PAM モジュール設定
/etc/raddb/sites-available/default 認証フロー定義(sites-enabled/default はこのシンボリックリンク)
/etc/pam.d/radiusd PAM 認証設定(自分で作成)

FreeRADIUS の設定

0. 設定ファイルのバックアップ

編集前に、元の設定ファイルをバックアップしておきます。

sudo cp -rp /etc/raddb /etc/raddb.original

1. クライアント設定(clients.conf)

Managed AD のドメインコントローラーを RADIUS クライアントとして登録します。

sudo vi /etc/raddb/clients.conf

以下を末尾に追加します。構築先の環境に合わせて記載してください。 共有シークレットについては、自由に設定が可能です。 共有シークレットは後ほど WorkSpaces のディレクトリ設定でも同じ値を入力します。完全一致 が必要なので、必ずメモをしてください。

# AWS Managed Microsoft AD
client managed-ad {
    # Managed AD の DC が存在するサブネットの CIDR
    ipaddr = 10.0.0.0/24
    secret = <共有シークレット>
}

2. EAP の無効化(起動エラー対策)

FreeRADIUS はデフォルトで EAP 認証が有効になっており、SSL/TLS 証明書がないと起動時にエラーになります。本構成では PAP のみ使用するため、EAP 関連を無効化します。

# EAP モジュールのシンボリックリンクを削除
sudo rm /etc/raddb/mods-enabled/eap

# inner-tunnel サイトを無効化
sudo rm /etc/raddb/sites-enabled/inner-tunnel

3. PAM モジュールの有効化

# PAM モジュールへのシンボリックリンクを作成
sudo ln -s /etc/raddb/mods-available/pam /etc/raddb/mods-enabled/pam

4. PAM 設定ファイルの作成

FreeRADIUS 用の PAM 設定を作成します。

sudo vi /etc/pam.d/radiusd

以下の内容を記述してください。

#%PAM-1.0
auth required pam_google_authenticator.so secret=/etc/radius/google-authenticator/${USER}/.google_authenticator
account required pam_permit.so
設定 説明
secret=... OTPシークレットファイルの場所を指定(中央集約管理)
pam_permit.so アカウント検証は常に許可(パスワード検証は Managed AD 側で完了済み)

5. OTPシークレット用ディレクトリの作成

sudo mkdir -p /etc/radius/google-authenticator
sudo chown root:root /etc/radius/google-authenticator
sudo chmod 755 /etc/radius/google-authenticator

pam_google_authenticator は OTPファイル読み込み時に setuid() で対象ユーザーに切り替えます。各ユーザーがこのディレクトリを横断できる必要があるため、親ディレクトリは 755 にします。

6. radiusd を root で動作させる設定

pam_google_authenticator は内部で setuid() を実行するため、FreeRADIUS を root 権限で動作させる必要があります。

sudo vi /etc/raddb/radiusd.conf

以下の項目を変更:

user = root      # デフォルト: radiusd
group = root     # デフォルト: radiusd

7. Auth-Type の強制設定(users ファイル)

PAM のみの構成では、authorize セクションの pap モジュールが「known good password」(ファイルや DB に保存されたパスワード)を見つけられないため、Auth-Type が自動設定されません。その結果、authenticate セクションの Auth-Type PAP { pam } が発火せず、認証が失敗します。

これを解決するため、users ファイルで Auth-Type を強制的に PAP に設定します。

sudo sh -c 'echo "DEFAULT Auth-Type := PAP" >> /etc/raddb/users'

8. 認証フロー設定(sites-available/default)

sudo vi /etc/raddb/sites-available/default

デフォルトの sites-available/default には多くのモジュールが有効になっています。EAP 関連の eap 呼び出しをすべてコメントアウトし、他のモジュールはデフォルトのまま残します。

authorize セクション

pap モジュールは Auth-Type PAP を発火させるために必須ですが、AL2023 の FreeRADIUS 3.2.5 ではデフォルト設定にすでに含まれています。 EAP ブロック(eap { ok = return })のみコメントアウトします。他のモジュールはデフォルトのまま残します。

authorize {
    filter_username
    preprocess
    chap
    mschap
    digest
    suffix
    # eap {              # ← コメントアウト(EAP ブロック全体)
    #     ok = return
    # }
    files
    -sql
    -ldap
    expiration
    logintime
    pap                  
}

authenticate セクション

Auth-Type PAP ブロックの中身を pap から pam に変更します。

AL2023 の FreeRADIUS 3.2.5 デフォルトでは Auth-Type EAP ブロックはすでにコメントアウトされていますが、代わりに bare eap 行(Auth-Type ブロック外の単独 eap 呼び出し)が存在します。

eap モジュールを削除した状態でこの行が残っているとエラーになるため、コメントアウトが必要です。

authenticate {
    Auth-Type PAP {
        pam              # ← pap から pam に変更(PAM で OTP検証)
    }

    Auth-Type CHAP {
        chap
    }

    Auth-Type MS-CHAP {
        mschap
    }

    mschap
    digest

    # pam               # ← コメントアウトのまま(authenticate のデフォルト pam 行)

    # eap               # ← コメントアウト(eap モジュール削除済みのため必須)
}

post-auth / post-proxy にも bare eap 行あり: sites-available/default の post-auth(Access-Reject サブセクション)と post-proxy セクションにも eap 行があります。すべてコメントアウトが必要です。以下のコマンドで一括確認できます:

上記で出力された行をすべてコメントアウトしてください。

sudo grep -n '^\s*eap$' /etc/raddb/sites-available/default | grep -v '#'

9. 設定の構文チェックと起動確認

すべての設定が完了したら、構文チェックを行います。

# 構文チェック(エラーがなければ "Configuration appears to be OK" と出力)
sudo radiusd -XC

# 起動してポートを確認
sudo systemctl start radiusd
sudo ss -ulnp | grep radiusd

# 期待される出力:
# UNCONN 0  0  0.0.0.0:1812  0.0.0.0:*  users:(("radiusd",...))
# UNCONN 0  0  0.0.0.0:1813  0.0.0.0:*  users:(("radiusd",...))

ユーザーの OTPセットアップ

ユーザー追加スクリプト

各 WorkSpaces ユーザーに対して、Linux システムユーザーの作成と OTPシークレットの生成を行います。

#!/bin/bash
# add-radius-user.sh
USERNAME=$1

if [ -z "$USERNAME" ]; then
    echo "Usage: $0 <username>"
    exit 1
fi

# Linux システムユーザーを作成(ログイン不可・ホームディレクトリなし)
sudo useradd -r -s /sbin/nologin -M "$USERNAME" 2>/dev/null

# OTPシークレット用のディレクトリを作成
USER_DIR="/etc/radius/google-authenticator/${USERNAME}"
sudo mkdir -p "$USER_DIR"
sudo chown "$USERNAME":"$USERNAME" "$USER_DIR"
sudo chmod 700 "$USER_DIR"

# Google Authenticator シークレットを生成
sudo -u "$USERNAME" google-authenticator -t -d -f -w 3 -r 3 -R 30 \
    -s "${USER_DIR}/.google_authenticator"

# ファイル権限を設定
sudo chown "$USERNAME":"$USERNAME" "${USER_DIR}/.google_authenticator"
sudo chmod 600 "${USER_DIR}/.google_authenticator"

echo "Done: ${USER_DIR}/.google_authenticator"

スクリプトの実行

chmod +x add-radius-user.sh
sudo ./add-radius-user.sh testuser

実行するとQRコードが表示されるので、スマートフォンの Google Authenticator アプリでスキャンします。

動作確認

1. デバッグモードで起動

# 通常のサービスを停止(起動済みの場合)
sudo systemctl stop radiusd

# デバッグモードで起動(ログがリアルタイムで表示される)
sudo radiusd -X

2. radtest でローカルテスト

Google Authenticator アプリで現在のOTPコードを確認してから、別のターミナルで実行します。

PAM のみの構成では、FreeRADIUS に送信されるのは OTPコードのみです。パスワードは含めません。 尚、ローカルでのテストの場合、共有シークレットは先ほど設定したものとは異なります。

/etc/raddb/clients.confclient localhost { 内にある共有シークレットを利用してください。

# radtest <ユーザー名> <OTPコード> localhost 1812 <共有シークレット>
# 例: ユーザー testuser、OTPコード 123456、共有シークレット MyRadiusSecret123
radtest testuser 123456 localhost 1812 testing123

3. デバッグログの読み方

デバックログを読み取り、結果をご確認ください。

# 成功パターン
(0) pam: Using pamauth string "radiusd" for pam.conf lookup
(0) pam: User "testuser" authenticated successfully
Sending Access-Accept               ← 認証 OK

# 失敗パターン(OTPコード不一致)
pam_google_authenticator: Invalid verification code for testuser
Sending Access-Reject               ← 認証 NG

4. サービスとして起動

動作確認が取れたらサービスを起動します。

sudo systemctl enable radiusd
sudo systemctl start radiusd
sudo systemctl status radiusd

WorkSpaces 側の MFA 設定

Directory Service コンソールでの設定

  1. AWS マネジメントコンソール → Directory Service → 対象の Managed AD を選択
  2. ネットワークとセキュリティ タブ → 多要素認証 セクション → アクション → 有効化
  3. 以下を入力:
項目 設定値
RADIUS サーバーの IP アドレス FreeRADIUS 用 EC2 のプライベート IP
ポート 1812
共有シークレット clients.conf に設定した値と同一
プロトコル PAP
サーバータイムアウト 30(秒)
最大リトライ回数 3

ログイン検証

MFA を有効化すると、WorkSpaces クライアントのログイン画面に MFA code 入力欄が追加されます。

  1. WorkSpaces クライアントを起動し、Registration Code を入力
  2. 以下の 3 つを入力:
    • ユーザー名: AD 上のユーザー名
    • パスワード: AD のパスワード
    • MFA code: Google Authenticator の 6 桁コード
  3. デスクトップが起動すれば成功

まとめ

本記事では、Amazon Linux 2023 上に FreeRADIUS + Google Authenticator を構築し、WorkSpaces の MFA を実現する手順を紹介しました。

Amazon Linux2023での構築手順は調べてみると手順は多く出ますが、詰まるポイントも多いですので、ご参考までに利用していただけたらと思います。

篠﨑 勇輔(書いた記事を見る)

クロスインダストリー本部SA2課