VPN と Wi-Fi 向け RADIUS マルチ ファクター認証: Casdoor RADIUS サーバーによる TOTP 2FA
RADIUS を介して VPN にマルチ ファクター認証を導入する場合、VPN ゲートウェイはユーザー名とパスワードを PAP で RADIUS サーバーに送信します。サーバーはパスワードを検証し、Access-Challenge で応答します。クライアントはプロンプトを表示し、ユーザーは認証アプリから取得した 2FA コードを 2 番目のリクエストに入力します。Casdoor には、TOTP を設定しているユーザーに対してまさにこの処理を行う RADIUS サーバーが組み込まれているため、Access-Challenge プロンプトを表示できるゲートウェイ(ベンダー ドキュメントに記載されている FortiGate SSL VPN など)では、追加のソフトウェアなしでパスワードと 2FA コードの両方を要求できます。WPA2/WPA3-Enterprise を使用した Wi-Fi は異なります。802.1X は EAP 上で実行され、EAP には入力用のコードを受け取る仕組みがないため、Casdoor にはこれらのクライアント用にコードをスキップするためのスイッチがあります。
RADIUS そのものの背景や、ネットワーク デバイスにおける LDAP との比較については、まず RADIUS vs LDAP をお読みください。この記事では MFA の部分、つまり通信内容、第 2 要素をサポートできるクライアント、そして Casdoor でそれを有効にする方法について説明します。
Casdoor で RADIUS MFA を使用できるクライアント
この表は、各ベンダーがドキュメントに記載している内容をリストしています。「Challenge support」とは、クライアントが Access-Challenge プロンプトをユーザーに表示し、回答を返送することを意味します。確認したベンダー ページに記載がない場合は、推測する代わりにその旨を記載しています。
| クライアント | Casdoor と併用する RADIUS 認証方式 | Access-Challenge サポート | 備考 |
|---|---|---|---|
| FortiGate SSL VPN | PAP (方式を PAP に設定、またはデフォルトのままにすると PAP を最初に試行) | はい (Fortinet により記載あり) | Fortinet によると、SSL VPN はチャレンジをクライアントに転送し、回答を待ちます |
| FortiGate IPsec VPN (FortiClient を含む) | PAP | デフォルトでは転送されない | Fortinet の解決策には RADIUS サーバー側での MS-CHAP が必要ですが、Casdoor はこれをサポートしていません。SSL VPN を使用するか、MFA をスキップしてください |
| Cisco ASA (AnyConnect / Secure Client) | PAP (ASA のすべての接続タイプでのデフォルト) | ASA RADIUS 設定ガイドに記載なし | トンネル グループで password-management を有効にしないでください。ASA が MS-CHAPv2 に切り替わります |
| OpenVPN Access Server | PAP (CHAP と MS-CHAPv2 も提供) | RADIUS 設定ページに記載なし | アカウンティングは別のトグルで、デフォルト ポートは 1813 です |
| pfSense (RADIUS 認証サーバー、OpenVPN で使用) | PAP (MD5-CHAP、MS-CHAPv1、MS-CHAPv2 も可) | Netgate ドキュメントに記載なし | Netgate の OTP の例ではコードをパスワード フィールド内に含めますが、Casdoor はこれを受け入れません |
| WireGuard | なし | 該当なし | ピアは公開鍵のみで認証するため、RADIUS が検証すべきログインが存在しません |
| Wi-Fi, WPA2/WPA3-Enterprise (802.1X) | EAP (PEAP、EAP-TTLS など) | 入力用コードのプロンプトなし | Casdoor は EAP を実装していません。Wi-Fi セクションを参照してください |
セルに「not stated」とある場合は、展開前に実際の VPN クライアントでテストし、プロンプトが表示され、コードが正しく通ることを確認してください。
Casdoor が検証するパスワードを伝達できるのが PAP のみの理由
RADIUS にはパスワードを送信するいくつかの方法があり、それによってサーバーが検証できる内容が決まります。
PAP を使用すると、クライアントは User-Password 属性にパスワードを入力し、共有シークレットとリクエスト認証器の MD5 ハッシュで隠蔽します(RFC 2865、セクション 5.2)。サーバーは同じシークレットを用いてこの処理を逆転させ、平文のパスワードを取得し、保存されたハッシュまたは LDAP バインドに対してチェックできます。Casdoor は User-Password を読み取り、サインインページと同じパスワードチェックを実行します。
CHAP を使用すると、クライアントはパスワードを送信しません。代わりに、パスワードとランダムなチャレンジのハッシュを送信します。RFC 2865 では、そのハッシュを再計算するためにサーバー側でユーザーの平文パスワードが必要であると明確に述べられています。MS-CHAPv2 も NT ハッシュを使用する点で同様の仕組みです。パスワードを一方向ハッシュとして保存する ID プロバイダー(Casdoor の組み込み組織では bcrypt を使用)は、どちらの方法でも検証を行うことができません。Casdoor RADIUS サーバーは User-Password のみを読み取るため、CHAP または MS-CHAPv2 リクエストはパスワードなしで到達し、拒否されます。
PAP の隠蔽は共有シークレットによる MD5 のみであるため、長いランダムなシークレットを使用し、ゲートウェイと Casdoor 間では RADIUS をプライベートネットワークまたは VPN 上に保ち、クライアント側で Message-Authenticator 属性を有効にしてください。Casdoor はリクエストに Message-Authenticator が含まれている場合にそれを検証し、その場合は返信にも署名を付けます。これは Blast-RADIUS(CVE-2024-3596)に対する緩和策です。詳細は RADIUS サーバードキュメントにあります。
Access-Challenge とパスワードへのコード追加の比較
RADIUS 経由で 2FA コードを取得するには、主に 2 つの一般的な方法があります。
- Access-Challenge. サーバーはまずパスワードを確認し、次に
Access-Challenge、State属性、およびReply-Messageで応答します。クライアントはそのメッセージを表示し、ユーザーがコードを入力すると、クライアントはコードをUser-Passwordに含め、同じStateを保持した新しいAccess-Requestを送信します。RFC 2865 セクション 4.4 では、チャレンジに対応していないクライアントの場合の挙動も規定されており、Access-ChallengeをAccess-Rejectとして扱わなければなりません(MUST)。 - パスワードへのコード追加. ユーザーは単一のパスワードフィールドに
password123456のように入力し、サーバーは最後の 6 桁を取り出します。この方法はあらゆるクライアントで動作するため、古いゲートウェイ向けに構築された製品ではこの方式が提供されています。
Casdoor は最初の方式のみを実装しています。以下は Casdoor の RADIUS サーバー(radius/server.go)におけるフローです:
- 最初の
Access-Requestは正しいパスワードを含んでいる必要があります。MFA を有効にしているユーザーにはAccess-Challenge、ランダムなState、およびplease enter OTPというReply-Messageが返されます。 Stateの有効期間は 120 秒で、一度しか使用できません。これは最初のリクエストの組織名とユーザー名に関連付けられています。- 2 番目の
Access-Requestには、そのStateと、ユーザーの認証アプリから取得した 6 桁の TOTP コードをUser-Passwordに含める必要があります。Casdoor はコードをユーザーの TOTP シークレットに対してチェックし、Access-AcceptまたはAccess-Rejectで応答します。 - 誤ったコードは、誤ったパスワードとは別に、ユーザーのアプリケーションのサインイン失敗制限(デフォルトでは 5 回の試行と 15 分の凍結期間)にカウントされます。
これにより 2 つの結果が生じます。「パスワードとコードを 1 つのフィールドに入れる」ことしかできないクライアントは失敗します。なぜなら、Casdoor は文字列全体をパスワードとしてチェックするからです。また、RADIUS 経由では TOTP のみが機能します。SMS やメールコードは、パスワードステップ後に Casdoor がメッセージを送信する必要があり、RADIUS サーバーはその処理を行わないためです。唯一の MFA メソッドが SMS またはメールであるユーザーは、チャレンジを受け取った後に拒否されるため、RADIUS ユーザーには認証アプリの設定を推奨してください。
Wi-Fi: 802.1X と WPA-Enterprise
WPA2-Enterprise または WPA3-Enterprise を使用する Wi-Fi では、アクセスポイント自体がパスワードを収集しません。デバイス(サプレカント)と RADIUS サーバー間の EAP 会話の中継を行い、RADIUS は EAP-Message 属性内で EAP パケットを伝送します。この設定では Access-Challenge はすでに使用されています。EAP 交換の各ラウンドトリップは Access-Request と Access-Challenge のペアとなるためです(RFC 3579)。RFC 3579 では、EAP-Message を含むメッセージに Reply-Message を含めてはならないと定められているため、「please enter OTP」用のフィールドがなく、スマートフォンやノートパソコン上でコードを入力するためのダイアログも存在しません。
Casdoor に関する実用上の重要なポイントが 2 つあります:
- Casdoor の RADIUS サーバーは EAP を実装していません。WPA-Enterprise でアクセスポイントが直接接続することはできません。TLS トンネルを終端し、プレーンな PAP リクエストを転送する EAP サーバーを前面に配置する必要があります。FreeRADIUS は EAP-TTLS と内部メソッドとしての PAP を使用することでこれを実現でき、内部リクエストを別の RADIUS サーバーへプロキシできます。ただし、デバイスは TTLS かつ内部が PAP になるように設定する必要があります。多くのデバイスでデフォルトとなっている PEAP と MS-CHAPv2 の組み合わせは、前述の PAP セクションの理由により Casdoor では動作しません。
- これらのユーザーについては、組織設定で Skip MFA for RADIUS を有効にしてください。Casdoor はその後、パスワードチェックだけで MFA を有効なユーザーを許可します。Web サインインページでの MFA は影響を受けません。
ポート、共有シークレット、課金情報
RFC 2865 では RADIUS 認証に UDP ポート 1812 を割り当て、RFC 2866 では課金情報に 1813 を割り当てています。Casdoor は単一の UDP ポート radiusServerPort でリッスンし、そこで Access-Request と Accounting-Request の両方を処理します。したがって、ゲートウェイの課金情報を認証と同じポート(デフォルトでは 1812)に向ける必要があります。1813 に向けると、課金パケットはどこにも届きません。Casdoor をコンテナで実行する場合は、UDP でポートを公開してください。例えば -p 1812:1812/udp です。
共有シークレットはすべてのクライアントで共通の値であり、radiusSecret で指定します。Casdoor と通信するすべてのゲートウェイがこの値を使用します。
課金情報について、Casdoor はデータベース(テーブル radius_accounting)に Start、Interim-Update、Stop メッセージを記録します。これにはセッション ID、セッション時間、NAS アドレス、フレーム IP、バイト数およびパケット数のカウンターが含まれます。これは RADIUS が有効になっている組織に対してのみ実行されます。
Casdoorの設定
1. RADIUS オプションを設定します。 conf/app.conf 内、または同じ名前の環境変数として設定します:
radiusServerPort = 1812
radiusDefaultOrganization = "my-company"
radiusSecret = "a-long-random-string-shared-with-the-gateway"
radiusDefaultOrganization は、リクエストに Class 属性が含まれていない場合に Casdoor が使用する組織です。ゲートウェイがリクエストに Class 属性を追加できない場合、この設定によって RADIUS 経由でサインインするユーザーの所属組織が決まります。すべてのキーは 構成リファレンス に記載されています。
2. 組織で RADIUS を有効にする。 組織の編集ページで Enable RADIUS をオンにします。デフォルトではオフになっており、グローバル管理者のみが変更できます。オフの場合、Casdoor はその組織に対するすべての Access-Request を拒否し、アカウンティングも無視します。
3. RADIUS の MFA を決定する。 Access-Challenge をサポートする VPN ゲートウェイの場合は、Skip MFA for RADIUS をオフのままにします。WPA-Enterprise Wi-Fi など、チャレンジに応答できない RADIUS クライアントを持つ組織の場合は、これをオンにします。
4. ユーザーを TOTP に登録する。 ユーザーはプロフィールページから認証アプリを設定します。詳細は 多要素認証 を参照してください。必須にするには、組織の MFA アイテム で TOTP アイテムに Required ルールを追加します。順序に注意してください:必要な MFA の設定が未完了のユーザーや、まずパスワードの変更が必要なユーザーは、Casdoor のサインインページでそれを完了するまで RADIUS 経由では拒否されます。
5. コマンドラインからテストする。 FreeRADIUS の radclient は PAP リクエストを送信し、応答を表示します:
echo 'User-Name = "alice", User-Password = "her-password"' \
| radclient -x casdoor.example.com:1812 auth a-long-random-string-shared-with-the-gateway
TOTP を使用しているユーザーの場合、State と Reply-Message を含む Access-Challenge が表示されるはずです。その State を使ってコードを 120 秒以内に送信してください:
echo 'User-Name = "alice", User-Password = "123456", State = 0x...' \
| radclient -x casdoor.example.com:1812 auth a-long-random-string-shared-with-the-gateway
最初の応答の State 値を 0x... の代わりに貼り付けます。Access-Accept が返されれば、セットアップは正しく、次はゲートウェイの設定です。
また、Casdoor 自体の Web サインインの第2要因として外部 RADIUS サーバーを使用したい場合は、これは逆方向であり、RADIUS MFA プロバイダー で説明されています。
参考資料
- RFC 2865: Remote Authentication Dial In User Service (RADIUS)
- RFC 2866: RADIUS Accounting
- RFC 3579: RADIUS Support for EAP
- Fortinet: SSL VPN と IPsec VPN での RADIUS Access-Challenge 処理の違い
- FortiOS 7.6.5: RADIUS サーバーの設定
- Cisco ASA 9.22: AAA 用の RADIUS サーバー
- OpenVPN Access Server: 認証
- pfSense: RADIUS 認証サーバー
- WireGuard
- FreeRADIUS
inner-tunnelバーチャルサーバー - Casdoor RADIUS サーバー