はじめに
AWS 環境の EC2 インスタンス (Amazon Linux 2023) を利用して、オープンソースで最も広く利用されている RADIUS サーバー「FreeRADIUS」を構築する手順を解説します。
さらに発展編として、実運用で役立つ CloudWatch を使ったログの可視化までをやってみます。
全体構成図
同じ VPC 内に RADIUS サーバーとクライアントを配置し、クライアントからサーバーへ認証リクエストを送信するシンプルな構成です。
構築手順
ステップ1: AWS環境の準備
まず、サーバーとクライアントとして利用する2台のEC2インスタンスを準備します。
以下の設定で2台のEC2インスタンスを作成します。
設定項目 | 値 | 補足 |
---|---|---|
名前 | RADIUS-Server と RADIUS-Client | それぞれの役割が分かるように命名します。 |
AMI | Amazon Linux 2023 AMI | - |
インスタンスタイプ | t2.micro | デモ用途には十分なスペックです。 |
ネットワーク | 同じVPC、同じパブリックサブネット | 2台のインスタンスが相互に通信できるようにします。 |
パブリックIPの自動割り当て | 有効化 | SSH接続用 |
次にRADIUS-SG という名前で新しいセキュリティグループを作成し、2台のインスタンスにアタッチします。以下のインバウンドルールを設定してください。
タイプ | プロトコル | ポート範囲 | ソース | 説明 |
---|---|---|---|---|
SSH | TCP | 22 | マイIP | 管理用のSSH接続 |
カスタムUDP | UDP | 1812 | RADIUS-SG のID | RADIUS認証通信 |
カスタムUDP | UDP | 1813 | RADIUS-SG のID | RADIUSアカウンティング通信 |
- プライベートIPアドレスの確認
後ほどの設定で利用するため、作成した2台のインスタンスのプライベートIPアドレスを控えておきます。
ステップ2: RADIUSサーバーの構築
-
FreeRADIUSのインストール
RADIUS-Server
インスタンスにEC2 Instance ConnectでSSH接続し、FreeRADIUS をインストール・設定します。bashsudo dnf update -y sudo dnf install -y freeradius freeradius-utils
タイムゾーンを日本時間 (Asia/Tokyo) に設定します。
bashsudo timedatectl set-timezone Asia/Tokyo
-
クライアント情報の登録 (clients.conf)
RADIUS サーバーがどのクライアントからのリクエストを受け付けるかを設定します。
sudo vi /etc/raddb/clients.conf
を開き、ファイルの末尾にRADIUS-Client
の情報を追記します。<RADIUS-ClientのプライベートIP>
は控えておいたIPアドレスに置き換えてください。# /etc/raddb/clients.conf # (...ファイルのもともとの内容...) # 自前のRADIUSクライアントを追加 client radius_client { ipaddr = <RADIUS-ClientのプライベートIP> secret = hands-on # サーバーとクライアント間の合い言葉 }
この secret
(共有シークレット) は非常に重要です。
3. ユーザー情報の登録 ( users
)
認証に利用するユーザーを登録します。
sudo vi /etc/raddb/users
を開き、ファイルの先頭にテストユーザーの情報を追記します。
# /etc/raddb/users
# テストユーザーを追加 (ユーザー名: testuser, パスワード: testpassword)
testuser Cleartext-Password := "testpassword"
# 複数人登録する場合は同様に追記する
hanako.yamada Cleartext-Password := "P@ssword_Yamada123"
taro.suzuki Cleartext-Password := "P@ssword_Suzuki456"
# (...ファイルのもともとの内容...)
ステップ3: EAP無効化
FreeRADIUS は、インストール直後の状態では高度な認証方式 (EAP) が有効になっています。しかし、これらの機能はSSL証明書などを必要とするため、シンプルなID/パスワード認証を行う際には、これが原因で起動エラーが発生します。
今回のデモでは、より簡単にするためにあらかじめEAPを無効化しておきます。
-
eap
モジュールを無効化
EAP はセキュアな認証方式ですが、証明書がないと起動に失敗します。以下のコマンドで無効化します。sudo rm /etc/raddb/mods-enabled/eap
-
inner-tunnel
サイトを無効化
inner-tunnel
は EAP のトンネル処理で使われる設定ですが、今回は不要なので無効化します。bashsudo rm /etc/raddb/sites-enabled/inner-tunnel
-
default
サイトの修正モジュールを無効化しても、メインの設定ファイル (
default
) からの呼び出しが残っているため、それらもコメントアウトします。sudo vi /etc/raddb/sites-enabled/default
で開いて、2箇所修正します。-
authorize
セクションの修正(419行目)
※eapだけでなく、{ }の部分もコメントアウトすることを忘れないでください。起動時に構文エラーとなります。/etc/raddb/sites-enabled/default# 編集前 authorize { ... eap { ok = return # updated = return } } # 編集後 authorize { ... #eap { # ok = return # updated = return #} }
-
-
authenticate
セクションの修正(603行目)/etc/raddb/sites-enabled/default# 編集前 authenticate { ... eap ... } # 編集後 authenticate { ... # eap ... }
Tips:以下のコマンドで編集すべき行数を予め知ることができます。
sudo grep -n '^\s*eap' /etc/raddb/sites-enabled/default
これで、シンプルなPAP認証(ID/パスワード認証)に必要な設定だけが残った状態になりました。
ステップ4: サーバーの起動とクライアントの準備
-
FreeRADIUSサービスの起動
RADIUS-Server
で以下のコマンドを実行し、サービスを起動・自動起動設定します。bashsudo systemctl start radiusd sudo systemctl enable radiusd
以下のコマンドで
active (running)
となっていれば成功です。bash[ec2-user@ip-10-0-14-102 ~]# sudo systemctl status radiusd ● radiusd.service - FreeRADIUS high performance RADIUS server. Loaded: loaded (/usr/lib/systemd/system/radiusd.service; enabled; preset: disabled) Active: active (running) since Sun 2025-06-22 11:29:19 UTC; 12s ago Main PID: 31373 (radiusd) Tasks: 6 (limit: 1111) Memory: 40.5M CPU: 80ms CGroup: /system.slice/radiusd.service └─31373 /usr/sbin/radiusd -d /etc/raddb
-
クライアントツールのインストール
RADIUS-Client
インスタンスに SSH で接続し、テストツールをインストールします。bashsudo dnf update -y sudo dnf install -y freeradius-utils
タイムゾーンを日本時間 (Asia/Tokyo) に設定します。
bashsudo timedatectl set-timezone Asia/Tokyo
ステップ5: 認証テスト
RADIUS-Client
から radtest
コマンドを使い、認証テストを実行します。
-
認証成功テスト
正しい共有シークレット (hands-on
) を使ってテストします。bashradtest testuser testpassword <RADIUS-ServerのプライベートIP>:1812 0 hands-on
Received Access-Accept
と返ってくれば認証成功です!bashSent Access-Request Id 95 from 0.0.0.0:55186 to 10.0.14.102:1812 length 78 User-Name = "testuser" User-Password = "testpassword" NAS-IP-Address = 10.0.8.100 NAS-Port = 0 Message-Authenticator = 0x00 Cleartext-Password = "testpassword" Received Access-Accept Id 95 from 10.0.14.102:1812 to 10.0.8.100:55186 length 38 Message-Authenticator = 0xf224b42683d891fa7fcf3193349935ad
-
認証失敗テスト (共有シークレット不一致)
わざと間違った共有シークレット (hands-off
) を使ってみましょう。bashradtest testuser testpassword <RADIUS-ServerのプライベートIP>:1812 0 hands-off
bashSent Access-Request Id 27 from 0.0.0.0:56334 to 10.0.14.102:1812 length 78 User-Name = "testuser" User-Password = "testpassword" NAS-IP-Address = 10.0.8.100 NAS-Port = 0 Message-Authenticator = 0x00 Cleartext-Password = "testpassword" Sent Access-Request Id 27 from 0.0.0.0:56334 to 10.0.14.102:1812 length 78 User-Name = "testuser" User-Password = "testpassword" NAS-IP-Address = 10.0.8.100 NAS-Port = 0 Message-Authenticator = 0x00 Cleartext-Password = "testpassword" Sent Access-Request Id 27 from 0.0.0.0:56334 to 10.0.14.102:1812 length 78 User-Name = "testuser" User-Password = "testpassword" NAS-IP-Address = 10.0.8.100 NAS-Port = 0 Message-Authenticator = 0x00 Cleartext-Password = "testpassword" (0) No reply from server for ID 27 socket 3.
登録されたクライアントからでも共有シークレットが違う場合、サーバーは不正なリクエストとみなし、パケットを破棄します。
【発展】AWSサービスのワンポイント:認証ログの可視化
ステップ6: FreeRADIUSの設定ファイル radiusd.conf
を編集
設定ファイルをテキストエディタで開きます。
sudo vi /etc/raddb/radiusd.conf
log セクション内の auth
の設定(348行目)をnoからyesへ変更します。
#編集前
# Log all (accept and reject) authentication results to the log file.
#
# This is the same as setting "auth_accept = yes" and
# "auth_reject = yes"
#
# allowed values: {no, yes}
#
auth = no
#編集後
# Log all (accept and reject) authentication results to the log file.
#
# This is the same as setting "auth_accept = yes" and
# "auth_reject = yes"
#
# allowed values: {no, yes}
#
auth = yes
デフォルトの設定では取得できなかった成功時のログも吐き出し可能となりました。
ステップ7: CloudWatch Agentのインストールと設定
-
IAMロールのアタッチ
RADIUS-Server
のEC2インスタンスに、CloudWatch Agentがログを送信するための権限が必要です。1-1. IAMコンソールで新しいロールを作成します。
1-2. 信頼されたエンティティタイプ: AWSのサービス
1-3. ユースケース: EC2
1-4. 許可ポリシーとしてCloudWatchAgentServerPolicy
をアタッチします。
1-5. ロール名(例:EC2-CloudWatchAgent-Role
)を付けて作成します。
1-6. EC2ダッシュボードに戻り、RADIUS-Server
インスタンスにこのIAMロールをアタッチします。 -
CloudWatch Agentのインストール
RADIUS-Server
にSSHで接続し、以下のコマンドでAgentをインストールします。bashsudo dnf install -y amazon-cloudwatch-agent
-
Agent設定ファイルの作成
どのログファイルをCloudWatchに送信するかを定義する設定ファイルを作成します。FreeRADIUSは認証結果を/var/log/radius/radius.log
に出力するので、これを対象とします。
sudo vi /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
を実行し、以下の内容を貼り付けます。
{
"agent": {
"metrics_collection_interval": 60,
"run_as_user": "root",
"debug": true
},
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/radius/radius.log",
"log_group_class": "STANDARD",
"log_group_name": "/aws/ec2/freeradius-logs",
"log_stream_name": "{instance_id}",
"retention_in_days": 7,
"timestamp_format": "%a %b %d %H:%M:%S %Y",
"timezone": "LOCAL"
}
]
}
}
},
"metrics": {
"aggregation_dimensions": [
[
"InstanceId"
]
],
"append_dimensions": {
"AutoScalingGroupName": "${aws:AutoScalingGroupName}",
"ImageId": "${aws:ImageId}",
"InstanceId": "${aws:InstanceId}",
"InstanceType": "${aws:InstanceType}"
},
"metrics_collected": {
"disk": {
"measurement": [
"used_percent"
],
"metrics_collection_interval": 60,
"resources": [
"*"
]
},
"mem": {
"measurement": [
"mem_used_percent"
],
"metrics_collection_interval": 60
},
"statsd": {
"metrics_aggregation_interval": 60,
"metrics_collection_interval": 10,
"service_address": ":8125"
}
}
}
}
log_group_name
: CloudWatch Logs内でログを格納するグループ名です。分かりやすい名前をつけましょう。
参考までに上記jsonは以下の内容となっています。変更したいパラメータ等あれば、自由に調整してください。
CloudWatch Agent パラメータ設定
- エージェント共通 (agent)
パラメータ | 設定値 | 説明 |
---|---|---|
run_as_user | root | エージェントを実行するユーザー。rootで実行することでファイルアクセス権限の問題を回避します。 |
metrics_collection_interval | 60 (デフォルト値) | メトリクスを収集する基本間隔(秒)。 |
debug | TRUE | デバッグモードを有効化。詳細な動作ログが出力され、トラブルシューティングに役立ちます。本番環境ではfalse を推奨します。 |
- ログ収集 (logs)
パラメータ | 設定値 | 説明 |
---|---|---|
file_path | /var/log/radius/radius.log | 収集対象のログファイルへのフルパス。 |
log_group_name | /aws/ec2/freeradius-logs | ログを格納するCloudWatch Logsのロググループ名。 |
log_stream_name | {instance_id} | ロググループ内のログストリーム名。{instance_id} とすることで、実行したEC2インスタンスのIDが自動的に設定されます。 |
retention_in_days | 7 | CloudWatch Logsでのログ保持期間(日数)。7日経過後に自動で削除されます。 |
timestamp_format | %a %b %d %H:%M:%S %Y | ログファイル内のタイムスタンプを解釈するための書式。 |
timezone | LOCAL | ログのタイムスタンプに使用するタイムゾーン。LOCALはEC2インスタンスのOS設定に従います。 |
log_group_class | STANDARD | ロググループのストレージクラス。標準のアクセス頻度に適しています。 |
- メトリクス共通 (metrics)
パラメータ | 設定値 | 説明 |
---|---|---|
aggregation_dimensions | InstanceId | 収集したメトリクスをInstanceId単位で集約します。 |
append_dimensions.AutoScalingGroupName | ${aws:AutoScalingGroupName} | 全てのメトリクスにAuto Scalingグループ名のディメンション(タグ)を付与します。 |
append_dimensions.ImageId | ${aws:ImageId} | 全てのメトリクスにAMIのIDのディメンション(タグ)を付与します。 |
append_dimensions.InstanceId | ${aws:InstanceId} | 全てのメトリクスにインスタンスIDのディメンション(タグ)を付与します。 |
append_dimensions.InstanceType | ${aws:InstanceType} | 全てのメトリクスにインスタンスタイプのディメンション(タグ)を付与します。 |
- 収集メトリクス (ディスク・メモリ)
パラメータ | 設定値 | 説明 |
---|---|---|
measurement | used_percent | 収集するディスクの指標。ディスク使用率(%)を収集します。 |
resources | * | 収集対象のリソース。* は全てのマウント済みディスクパーティションを意味します。 |
metrics_collection_interval | 60 | このメトリクスの収集間隔(秒)。 |
measurement | mem_used_percent | 収集するメモリの指標。メモリ使用率(%)を収集します。 |
metrics_collection_interval | 60 | このメトリクスの収集間隔(秒)。 |
- 収集メトリクス (StatsD)
パラメータ | 設定値 | 説明 |
---|---|---|
service_address | :8125 | アプリケーションからカスタムメトリクスを受け付けるStatsDリスナーのアドレスとポート。 |
metrics_collection_interval | 10 | StatsDプロトコルでデータを受け付ける間隔(秒)。 |
metrics_aggregation_interval | 60 | 受け付けたデータを集約し、CloudWatchへ送信する間隔(秒)。 |
4. CloudWatch Agentの起動
以下のコマンドで設定ファイルを読み込み、Agentを起動します。
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json -s
これで、RADIUS-Server
で認証が発生するたびに、そのログが自動でCloudWatch Logsに送信されるようになります。
左がCloudWatchエージェントが取得した情報で、右側がRADIUSサーバ内の radius.log
です。かなり見にくいですが、きちんとログを収集できることがわかります。
ステップ8: CloudWatch Logs Insightsでのログ分析
radtest
コマンドで何度か認証を成功・失敗させてログを生成した後、AWSコンソールのCloudWatch画面を開きます。
- 左側のメニューから「ログ」>「Logs Insights」を選択します。
- 「ロググループを選択」で、先ほど設定した
RadiusServer/radius.log
を選びます。 - クエリエディタに、SQLライクなクエリを入力してログを分析できます。
クエリ
- 最新の認証ログ取得
fields @timestamp, @message
| sort by @timestamp desc
| limit 10
- 認証成功(Access-Accept)と失敗(Access-Reject)の件数を集計
fields @timestamp, @message
| filter @message like /Login OK/ or @message like /error/
| stats count(*) as event_count by if(@message like /Login OK/, 'Login OK', 'Error') as event_type
| sort by event_type asc
- 認証数の推移
fields @timestamp, @message
| filter @message like /Login OK/ or @message like /error/
| stats sum(if(@message like /Login OK/, 1, 0)) as LoginOK_Count, sum(if(@message like /error/, 1, 0)) as Error_Count by bin(1m) as interval
| sort by interval asc
ステップ9: CloudWatch Dashboardでの可視化
Logs Insightsのクエリ結果は、そのままダッシュボードのウィジェットとして追加できます。
- Logs Insightsで上記のクエリを実行した後、「アクション」>「ダッシュボードに追加」をクリックします。
- 「新しいダッシュボードを作成」を選び、ダッシュボード名(例:
RADIUS-Monitoring
)を入力します。 - ウィジェットの種類(折れ線グラフ、円グラフ、数値など)を選択し、「ダッシュボードに追加」をクリックします。
これを繰り返すことで、以下のようなウィジェットを持つダッシュボードを作成できます。
みなさんもお好きなメトリクスを収集して、オリジナルを作ってみてください!
おわりに
今回は AWS 環境で RADIUS サーバーを構築し、認証テストを行うまでの一連の流れを解説しました。
エラーがでそうなところは可能な限りフォローしましたが、こんなエラーがでる!等ありましたらご連絡ください~!