AWS環境でRADIUSサーバー構築からCloudWatch監視まで

はじめに

NTT西日本エンタープライズビジネス営業部の吉田泰隆です。
本記事ではユーザ認証に用いられるRADIUSサーバ・クライアントをAWS上に構築し、CloudWatchによるアクセスログの可視化について紹介します。
本記事は2025年9月時点の情報に基づきます。

対象読者

本記事が想定する対象読者は以下の通りです。

  • AWSやネットワーク認証システムに興味を持っている人
  • AWS環境でサーバー構築経験を積みたい人
  • RADIUSサーバーの導入・設定方法を学びたい人
  • CloudWatchを使ったログ監視・可視化を実装したい人

背景・目的

担当案件でRADIUSサーバーを構築することになりました。その際、ドキュメントや資料を読んだだけでは、認証の仕組みや各設定のつながりが腑に落ちず、深く理解するためには実際に手を動かすしかないと感じました。
本記事は、RADIUSサーバーの構築手順を丁寧に解説するハンズオンです。私が構築中につまずいたポイントや、理解を深めるための補足情報も盛り込んでいます。この記事を通して、読者の皆さんがRADIUSの仕組みを実践的に学び、今後の業務に役立てていただければ幸いです。

全体構成図

同じ VPC 内に RADIUS サーバーとクライアントを配置し、クライアントからサーバーへ認証リクエストを送信するシンプルな構成です。

構築手順

ステップ1: AWS環境の準備

まず、サーバーとクライアントとして利用する2台のEC2インスタンスを準備します。 以下の設定で2台のEC2インスタンスを作成します。

設定項目 補足
名前 RADIUS-Server と RADIUS-Client それぞれの役割が分かるように命名します。
AMI Amazon Linux 2023 -
インスタンスタイプ t2.micro デモ用途には十分なスペックです。
ネットワーク 同じVPC、同じパブリックサブネット 2台のインスタンスが相互に通信できるようにします。
パブリックIPの自動割り当て 有効化 SSH接続用

次にRADIUS-SG という名前で新しいセキュリティグループを作成し、2台のインスタンスにアタッチします。以下のインバウンドルールを設定してください。

タイプ プロトコル ポート範囲 ソース 説明
SSH TCP 22 マイIP(コンソールにアクセスしているユーザーのパブリックIPアドレス) ユーザからのSSH接続
カスタムUDP UDP 1812 RADIUS-SG のID RADIUS認証通信
カスタムUDP UDP 1813 RADIUS-SG のID RADIUSアカウンティング通信
  • プライベートIPアドレスの確認 後ほどの設定で利用するため、作成した2台のインスタンスのプライベートIPアドレスを控えておきます。

ステップ2: RADIUSサーバーの構築

1. RADIUS-ServerインスタンスへのSSH接続
以下2種類の方法でRADIUS-Serverへ接続します。
・EC2 Instance Connect
・SSH クライアント
※手順はコマンドともにコンソールに記載されておりますので、そちら(下記画像)をご参照ください。

2. FreeRADIUSのインストール
FreeRADIUS をインストール・設定します。

sudo dnf update -y
sudo dnf install -y freeradius freeradius-utils

タイムゾーンを日本時間 (Asia/Tokyo) に設定します。

sudo timedatectl set-timezone Asia/Tokyo

3. クライアント情報の登録 (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 (共有シークレット) は非常に重要です。
!注意!本記事では構成を理解する目的で簡単化のため平文でパスワードを使用しています。実運用では絶対に使わないでください。

4. ユーザー情報の登録 ( 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/TLS証明書などを必要とするため、シンプルなID/パスワード認証を行う際には、これが原因で起動エラーが発生します。

今回のデモでは、より簡単にするためにあらかじめEAP(Extensible Authentication Protocol, 拡張認証プロトコル)を無効化しておきます。
※EAP:IEEE 802.1X認証フレームワークの1つ。ユーザーID/パスワードや電子証明書を用いた多様な認証方式(EAP-TLS、EAP-PEAPなど)を柔軟に利用できるようにする仕組み。

!注意!本記事では構成を理解する目的で簡単化のためEAPを無効化しています。盗聴・中間者攻撃のリスク増大のため、実運用では絶対に使わないでください。

1. eap モジュールを無効化 EAP はセキュアな認証方式ですが、証明書がないと起動に失敗します。以下のコマンドで無効化します。

sudo rm /etc/raddb/mods-enabled/eap

inner-tunnel サイトを無効化 inner-tunnel は EAP のトンネル処理で使われる設定ですが、今回は不要なので無効化します。

sudo rm /etc/raddb/sites-enabled/inner-tunnel

3. default サイトの修正

モジュールを無効化しても、メインの設定ファイル ( `default` ) からの呼び出しが残っているため、それらもコメントアウトします。まず、下記コマンドで設定ファイルを開きます。
sudo vi /etc/raddb/sites-enabled/default

その後、2箇所修正します。

  • authorize セクションの修正(419行目) ※eapだけでなく、{ }の部分もコメントアウトすることを忘れないでください。起動時に構文エラーとなります。
        # 編集前
        authorize {
            ...
            eap {
                   ok = return
            #       updated = return
            }
        }
        # 編集後
        authorize {
            ...
            #eap {
            #       ok = return
            #       updated = return
            #}
        }
  • authenticate セクションの修正(603行目)
    # 編集前
    authenticate {
        ...
        eap
        ...
    }
    # 編集後
    authenticate {
        ...
    #   eap
        ...
    }

Tips:編集する行を409, 603行目と記載しましたが、見つからない場合は以下のコマンドをお試しください。編集すべき行数を知ることができます。

sudo grep -n '^\s*eap' /etc/raddb/sites-enabled/default

これで、シンプルなPAP認証(ID/パスワード認証)に必要な設定だけが残った状態になりました。

ステップ4: サーバーの起動とクライアントの準備

1. FreeRADIUSサービスの起動 RADIUS-Server で以下のコマンドを実行し、サービスを起動・自動起動設定します。

sudo systemctl start radiusd
sudo systemctl enable radiusd

以下のコマンドで active (running) となっていれば成功です。

    [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

2. クライアントツールのインストール

RADIUS-Client インスタンスに SSH で接続し、テストツールをインストールします。

sudo dnf update -y
sudo dnf install -y freeradius-utils

ステップ5: 認証テスト

RADIUS-Client から radtest コマンドを使い、認証テストを実行します。

1. 認証成功テスト 正しい共有シークレット ( hands-on ) を使ってテストします。

radtest testuser testpassword <RADIUS-ServerのプライベートIP>:1812 0 hands-on

以下のように Received Access-Accept と返ってくれば認証成功です!

    Sent 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

2. 認証失敗テスト (共有シークレット不一致) わざと間違った共有シークレット ( hands-off ) を使ってみましょう。

radtest testuser testpassword <RADIUS-ServerのプライベートIP>:1812 0 hands-off

今度はサーバーから何の応答もなく、最終的にタイムアウトエラーになります。

    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"
    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

デフォルトの設定では取得できなかった成功時のログも吐き出し可能となりました。
変更を反映させるために、RADIUSサーバを再起動させてください。

sudo systemctl restart radiusd

再起動後、サービスが正常に稼働しているか確認します。active (running)と表示されていれば、正常に再起動されています。

sudo systemctl status radiusd

ステップ7: CloudWatch Agentのインストールと設定

1. 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ロールをアタッチします。

2. CloudWatch Agentのインストール RADIUS-Server にSSHで接続し、以下のコマンドでAgentをインストールします。

sudo dnf install -y amazon-cloudwatch-agent

3. 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画面を開きます。

  1. 左側のメニューから「ログ」>「Logs Insights」を選択します。
  2. 「ロググループを選択」で、先ほど設定した RadiusServer/radius.log を選びます。
  3. クエリエディタに、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のクエリ結果は、そのままダッシュボードのウィジェットとして追加できます。

  1. Logs Insightsで上記のクエリを実行した後、「アクション」>「ダッシュボードに追加」をクリックします。
  2. 「新しいダッシュボードを作成」を選び、ダッシュボード名(例: RADIUS-Monitoring)を入力します。
  3. ウィジェットの種類(折れ線グラフ、円グラフ、数値など)を選択し、「ダッシュボードに追加」をクリックします。

これを繰り返すことで、以下のようなウィジェットを持つダッシュボードを作成できます。 みなさんもお好きなメトリクスを収集して、オリジナルを作ってみてください。

まとめ

今回は AWS 環境で RADIUS サーバーを構築し、認証テストを行うまでの一連の流れを解説しました。 ぜひ、みなさんもトライしてみてください。

執筆者

吉田 泰隆(NTT西日本 エンタープライズビジネス営業部所属)
好きなAWSサービス:Route53
所有資格:AWS Certified Solutions Architect – Professional

参考資料・出典

本記事を執筆するにあたり、以下のサイトを参考にしました。
qiita.com
qiita.com
https://www.hcnet.co.jp/column/detail23.html
https://www.infraexpert.com/study/wireless14.html

商標

「AWS」は、Amazon Web Services,Inc.またはその関連会社の商標もしくは登録商標です。

© NTT WEST, Inc.