技術者が紹介するテクノロジー

【第1回】高機能認証サーバー (FreeRADIUS)

認証の分野で頻繁に利用されるRADIUSを、黎明期から支えてきたオープンソースソフトウェアのFreeRADIUSを紹介します。NTTPCでは、2008年からFreeRADIUSの本格的な調査とサービスへの導入を進めており、今なおその適用範囲は広がろうとしています。
ダイヤルアップ、PPPoE、Wi-Fi、XGP、WiMAX、LTEといように昔も今もこれからも幅広く利用されていくことでしょう。

FreeRADIUSの概要

認証の成功や失敗を判定する、あるサービスを利用した事実を通知する、という手順を確立したRADIUSという決まりごと(通信プロトコル)があります。FreeRADIUSは、RADIUSを実現させるオープンソースソフトウェアです。

認証と言っても方法は様々です。特殊な手法のIDとパスワードの照合、サーバー(またはクライアント)証明書の一致、認証の通信を暗号化する、というようにRADIUSが誕生して十数年が経過し、当初の思想に大幅な追加がなされています。FreeRADIUSは、RADIUSの思想だけでなく、それら新しい手法にも次々と対応を進めています。

RADIUSの利用例

自宅でインターネットの契約をプロバイダと行うと、PPPoEのIDとパスワードが発行された経験がありませんか?このIDとパスワードは、利用者の認証のために使われますが、この認証を行うのがFreeRADIUSのようなRADIUSサーバーです。RADIUSサーバーが認証成功と判定すると、インターネットプロバイダはADSLやFTTHのサービスを利用者に提供開始します。他の例として、携帯キャリアのデータ通信や、ご家庭の無線LANルータにWPA-Enterpriseのような認証方式があれば、RADIUSを利用して認証することもあります。

このように、サービスの利用者はRADIUSをまったく意識しませんが、その裏では認証を取り仕切っている存在です。まさに、縁の下の力持ちのような役割であることがお分かり頂けるのではないでしょうか。

第1回 インストールして使ってみよう!

第1回では、FreeRADIUSのインストールから認証動作を手順を交えてご紹介します。

筆者環境

OS CentOS 6.0 x86_64
CPU Intel Core2 Duo
メモリ 1GB
ハードディスク 80GB
eth0 192.168.10.100
データベース MySQL

データシート

FreeRADIUS 公式サイト: http://freeradius.org/

FreeRADIUS インストールディレクトリ: /usr/local/radius
radclient アトリビュートファイル: /root/radius.auth.attr

環境構築

事前準備

MySQLを利用するため、以下のパッケージを導入します。
特に、mysql-develを導入しないと、FreeRADIUSのインストールが成功してもMySQLは利用できませんので注意してください。

# yum install -y mysql mysql-server mysql-devel

ダウンロード

FreeRADIUSのソースコードアーカイブを公式サイトからダウンロードします。
2011/11/30時点での最新バージョンは、2.1.12です。
ダウンロード後は、コンパイルとインストールを行います。

# tar xzf freeradius-server-2.1.12.tar.gz
# cd freeradius-server-2.1.12
# ./configure --prefix=/usr/local/radius
# make
# make install

FreeRADIUSの設定: クライアント

初期設定では、ループバックアダプタ(localhost)のみが登録されています。
ここでは、自身のeth0のIPアドレスをクライアントに登録します。
これは、のちに行う動作確認で、自分自身にRADIUSパケットを送信するためです。
※ループバックアダプタでも動作確認は可能です。

# vi /usr/local/radius/etc/raddb/clients.conf

ファイル最下行に追加してください。

------------------------------

client 192.168.10.100 {
secret = shared-key
}

------------------------------

PAPとCHAP認証

FreeRADIUSでは、認証ID、パスワード、クライアント証明書などを利用して認証を行うことができます。
今回は、認証IDとパスワードを利用するPAPとCHAPの認証方法について見ていきましょう。
※認証IDとパスワードの組み合わせを、ここではユーザーデータと呼びます。

ユーザーデータはどこかに保存しなければなりません。
FreeRADIUSでは、ユーザーデータの保存先として、様々な選択肢が用意されています。
今回は、ユーザーファイルとMySQLを選択してみましょう。

ユーザーファイル

ユーザーファイルを利用する場合には、特に難解な設定は必要ありません。
初期設定で、ユーザーファイルを読み込むようになっており、必要なユーザーデータを追加するのみです。

# vi /usr/local/radius/etc/raddb/users

ファイル最下行に追加してください。

------------------------------

file@nttpc.co.jp Cleartext-Password := "file-pw"

------------------------------

MySQL

FreeRADIUSの設定: MySQL

MySQLを利用するには、初期設定を変更しなければなりません。
変更内容の詳細な説明はこの場では省略させて頂き、手順を紹介します。

# vi /usr/local/radius/etc/raddb/radiusd.conf

該当行のコメントアウトを解除してください。

------------------------------

$INCLUDE sql.conf

------------------------------
# vi /usr/local/radius/etc/raddb/sql.conf

該当行を下記のように変更してください。

Before
login = "radius"
password = "radpass"
After
login = "root"
password = ""
# vi /usr/local/radius/etc/raddb/sites-enabled/default

177行目のコメントアウトを解除してください。

------------------------------

sql

------------------------------

MySQLの準備

MySQLを起動し、FreeRADIUSが利用するデータベースとテーブルを作成します。
FreeRADIUSは、MySQLの利用が想定されておりテーブルスキーマが用意されています。
作成したら、テーブル一覧で確認しましょう。

# service mysqld start

# mysql -u root -e "create database radius"
# mysql -u root radius < /usr/local/radius/etc/raddb/sql/mysql/schema.sql

# mysql -u root -e "show tables from radius"
+------------------+
| Tables_in_radius |
+------------------+
| radacct     |
| radcheck     |
| radgroupcheck  |
| radgroupreply  |
| radpostauth   |
| radreply     |
| radusergroup   |
+------------------+
7 rows in set (0.00 sec)

認証IDの作成

ユーザーデータは、radcheckテーブルに作成します。
radcheckテーブルの構造を確認して、insertを行いましょう。
insert後は、selectで確認します。

# mysql -u root radius
mysql> desc radcheck;
+-----------+------------------+------+-----+---------+----------------+
| Field   | Type       | Null | Key | Default | Extra     |
+-----------+------------------+------+-----+---------+----------------+
| id    | int(11) unsigned | NO  | PRI | NULL  | auto_increment |
| username | varchar(64)   | NO  | MUL |     |        |
| attribute | varchar(64)   | NO  |   |     |        |
| op    | char(2)     | NO  |   | ==   |        |
| value   | varchar(253)   | NO  |   |     |        |
+-----------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

mysql> insert into radcheck values (null, "mysql@nttpc.co.jp", "Cleartext-Password", ":=", "mysql-pw");
Query OK, 1 row affected (0.00 sec)

mysql> select * from radcheck;
+----+-------------------+--------------------+----+----------+
| id | username     | attribute     | op | value  |
+----+-------------------+--------------------+----+----------+
| 1 | mysql@nttpc.co.jp | Cleartext-Password | := | mysql-pw |
+----+-------------------+--------------------+----+----------+
1 row in set (0.00 sec)

FreeRADIUSの起動

FreeRADIUSを、動作の流れがわかるようにデバックモードで起動します。
デバックモードは、起動オプションに-Xとすれば良いのですが、-XXとすると時刻も表示されるようになります。

初めてデバックモードで起動するときに、初期設定でEAP向けの証明書を作成するようになっており、起動に失敗することがあります。
その場合でも、再度デバックモードで起動すれば問題ありません。

# /usr/local/radius/sbin/radiusd -XX

動作確認: radclient

FreeRADIUSを起動したコンソールと別のコンソールを用意してください。
詳細な説明は、radclientのヘルプを参照くださるとして、ここでは具体的な使い方を見ていきましょう。

radclientは、送信したいアトリビュートをテキストファイルで入力可能です。
※アトリビュートファイルと呼ぶことにします。

アトリビュートファイルは、"#"をコメントアウトとして利用できます。
空行は使用できないので、行頭に"#"のみを記載することで代替えとします。

それでは、アトリビュートファイルを作成しましょう!

ユーザーファイルとMySQLに登録した、認証IDはUser-Nameアトリビュートに入力します。
PAP認証を行う場合は、User-Passwordアトリビュートにパスワードを入力します。
CHAP認証を行う場合は、CHAP-Passwordアトリビュートにパスワードを入力します。
User-PasswordとCHAP−Passwordは暗号化が必要ですが、radclientが暗号化してくれるので平文で入力しましょう。
wrong-pwは、パスワード間違いによる認証失敗のために入力しておきます。

# vi /root/radius.auth.attr

下記の例では、file@nttpc.co.jpのPAP認証が行われる状態になっています。

------------------------------

User-Name=file@nttpc.co.jp
#User-Name=mysql@nttpc.co.jp
#
User-Password=file-pw
#User-Password=mysql-pw
#User-Password=wrong-pw
#
#CHAP-Password=file-pw
#CHAP-Password=mysql-pw
#CHAP-Password=wrong-pw

------------------------------

radclientにアトリビュートファイルをファイルを読み込ませて起動します。
送信するアトリビュートを変更して、いろいろ試してみましょう!
Access-Acceptが返答されれば認証許可(成功)、Access-Rejectが返答されれば認証拒否(失敗)です。
Access-Rejectは、FreeRADIUSの初期設定で1秒応答を待つようになっているので、少しコンソールが止まります。

ユーザーファイルとPAP認証でAccess-Accept
# /usr/local/radius/bin/radclient -x -f /root/radius.auth.attr 192.168.10.100 auth shared-key
Sending Access-Request of id 212 to 192.168.10.100 port 1812
    User-Name = "file@nttpc.co.jp"
    User-Password = "file-pw"
rad_recv: Access-Accept packet from host 192.168.10.100 port 1812, id=212, length=20
ユーザーファイルとPAP認証でAccess-Reject
# /usr/local/radius/bin/radclient -x -f /root/radius.auth.attr 192.168.10.100 auth shared-key
Sending Access-Request of id 41 to 192.168.10.100 port 1812
    User-Name = "file@nttpc.co.jp"
    User-Password = "wrong-pw"
rad_recv: Access-Reject packet from host 192.168.10.100 port 1812, id=41, length=20
ユーザーファイルとCHAP認証でAccess-Accept
# /usr/local/radius/bin/radclient -x -f /root/radius.auth.attr 192.168.10.100 auth shared-key
Sending Access-Request of id 186 to 192.168.10.100 port 1812
    User-Name = "file@nttpc.co.jp"
    CHAP-Password = 0xbab2fed363667eda6c266cc104e1d20716
rad_recv: Access-Accept packet from host 192.168.10.100 port 1812, id=186, length=20
ユーザーファイルとCHAP認証でAccess-Reject
Sending Access-Request of id 47 to 192.168.10.100 port 1812
    User-Name = "file@nttpc.co.jp"
    CHAP-Password = 0x2f542ba84cae4c0f049ab9c1f27594b46b
rad_recv: Access-Reject packet from host 192.168.10.100 port 1812, id=47, length=20
MySQLとPAP認証でAccess-Accept
# /usr/local/radius/bin/radclient -x -f /root/radius.auth.attr 192.168.10.100 auth shared-key
Sending Access-Request of id 131 to 192.168.10.100 port 1812
    User-Name = "mysql@nttpc.co.jp"
    User-Password = "mysql-pw"
rad_recv: Access-Accept packet from host 192.168.10.100 port 1812, id=131, length=20
MySQLとCHAP認証でAccess-Accept
# /usr/local/radius/bin/radclient -x -f /root/radius.auth.attr 192.168.10.100 auth shared-key
Sending Access-Request of id 204 to 192.168.10.100 port 1812
User-Name = "mysql@nttpc.co.jp"
CHAP-Password = 0xcc936ef12390fd901abeb7a35fabebe43e
rad_recv: Access-Accept packet from host 192.168.10.100 port 1812, id=204, length=20

アトリビュートによる認証許可と拒否: 承認

FreeRADIUSでは、認証IDとパスワードの一致していても、Access-Rejectを返答する様々な機能があります。
これが承認を表現しており、認証には成功したけど、承認で失敗したのでAccess-Rejectにするということになります。

承認の一例として、認証要求に設定されたアトリビュート値による制限をご紹介します。
ここでは、発信者番号での制限を実現してみましょう!

アトリビュート値判定のモジュール設定: rlm_checkval

rlm_checkvalを利用するためには、やはり初期設定を変更しなければなりません。 ここでも深く考えずに、手順を見ていきましょう。

			# vi /usr/local/radius/etc/raddb/sites-enabled/default
			

196行目のコメントアウトを解除してください。
※欲しいモジュールを呼び出す

------------------------------

checkval

------------------------------

ユーザーファイル

# vi /usr/local/radius/etc/raddb/users

ユーザーファイルに下記を追記してください。
※発信者番号は、Calling-Station-Idアトリビュートに設定されている。

------------------------------

file@nttpc.co.jp Cleartext-Password := "file-pw", Calling-Station-Id := "0300000000"

------------------------------

MySQL

# mysql -u root radius
mysql> insert into radcheck values (null, "mysql@nttpc.co.jp", "Calling-Station-Id", ":=", "0600000000");
Query OK, 1 row affected (0.00 sec)
mysql> select * from radcheck;
+----+-------------------+--------------------+----+------------+
| id | username     | attribute     | op | value   |
+----+-------------------+--------------------+----+------------+
| 1 | mysql@nttpc.co.jp | Cleartext-Password | := | mysql-pw  |
| 2 | mysql@nttpc.co.jp | Calling-Station-Id | := | 0600000000 |
+----+-------------------+--------------------+----+------------+
2 rows in set (0.00 sec)

FreeRADIUSのプロセス再起動

デバックモードで起動したままでしたら、Ctrl-cなどで終了させてプロセスを起動し直してください。

動作確認: radclient

それでは、radclientで動作確認してみましょう!
認証要求に、アトリビュートファイルを編集してCalling-Station-Idを追加します。

# vi /root/radius.auth.attr

------------------------------

User-Name=file@nttpc.co.jp
#User-Name=mysql@nttpc.co.jp
#
User-Password=file-pw
#User-Password=mysql-pw
#User-Password=wrong-pw
#
#CHAP-Password=file-pw
#CHAP-Password=mysql-pw
#CHAP-Password=wrong-pw
#
Calling-Station-Id=0300000000
#Calling-Station-Id=0600000000
#Calling-Station-Id=0900000000

------------------------------

Calling-Station-Idを変えて、Access-AcceptとAccess-Rejectが返答されることを確かめます。
そのとき、デバックログを見ると、rlm_checkvalが利用されていることがわかります。

さて、Calling-Station-Idが認証要求にない場合はどうなるでしょうか?
なんと、Access-Rejectにはなりません。

rlm_checkvalモジュールの初期設定では、判定対象がリクエストにない場合にはRejectにしないようになっています。
これを変えるためには、rlm_checkvalモジュールの設定を変更します。
変更したあとは、FreeRADIUSのプロセスを再起動してください。

再度、Calling-Station-Idがないリクエストで試すと、Access-Rejectになることが確認できますね!

Calling-Station-Idが一致
# /usr/local/radius/bin/radclient -x -f /root/radius.auth.attr 192.168.10.100 auth shared-key
Sending Access-Request of id 27 to 192.168.10.100 port 1812
    User-Name = "file@nttpc.co.jp"
    User-Password = "file-pw"
    Calling-Station-Id = "0300000000"
rad_recv: Access-Accept packet from host 192.168.10.100 port 1812, id=27, length=20

--- デバックログの一部 ---

Debug: rlm_checkval: Item Name: Calling-Station-Id, Value: 0300000000
Debug: rlm_checkval: Value Name: Calling-Station-Id, Value: 0300000000
Info: ++[checkval] returns ok

--------------------------
Calling-Station-Idが不一致
# /usr/local/radius/bin/radclient -x -f /root/radius.auth.attr 192.168.10.100 auth shared-key
Sending Access-Request of id 112 to 192.168.10.100 port 1812
User-Name = "file@nttpc.co.jp"
User-Password = "file-pw"
Calling-Station-Id = "0900000000"
rad_recv: Access-Reject packet from host 192.168.10.100 port 1812, id=112, length=20

--- デバックログの一部 ---

Debug: rlm_checkval: Item Name: Calling-Station-Id, Value: 0900000000
Debug: rlm_checkval: Value Name: Calling-Station-Id, Value: 0300000000
Info: ++[checkval] returns reject

--------------------------
Calling-Station-Idがない
# /usr/local/radius/bin/radclient -x -f /root/radius.auth.attr 192.168.10.100 auth shared-key
Sending Access-Request of id 81 to 192.168.10.100 port 1812
    User-Name = "file@nttpc.co.jp"
    User-Password = "file-pw"
rad_recv: Access-Accept packet from host 192.168.10.100 port 1812, id=81, length=20

--- デバックログの一部 ---

Debug: rlm_checkval: Could not find item named Calling-Station-Id in request
Info: ++[checkval] returns notfound

--------------------------
rlm_checkvalモジュールの設定変更
# vi /usr/local/radius/etc/raddb/modules/checkval

該当行のコメントアウトを解除して、変更してください。
--------------------------

notfound-reject = yes

--------------------------
再度、Calling-Station-Idがない
# /usr/local/radius/bin/radclient -x -f /root/radius.auth.attr 192.168.10.100 auth shared-key
Sending Access-Request of id 156 to 192.168.10.100 port 1812
    User-Name = "file@nttpc.co.jp"
    User-Password = "file-pw" rad_recv: Access-Reject packet from host 192.168.10.100 port 1812, id=156, length=20

--- デバックログの一部 ---

Debug: rlm_checkval: Could not find item named Calling-Station-Id in request
Info: ++[checkval] returns reject

--------------------------

認証応答にアトリビュートを設定する

リプライアトリビュートは、チェックアトリビュートと異なりFreeRADIUSが任意に設定するアトリビュートです。
必要に応じて、様々なアトリビュートを設定することができます。

ここでは、実際の例に沿って、IPアドレスをネットワーク機器に指示することを想定して設定を行います。
IPアドレスを指示するには、IPアドレスとIPアドレスのマスクが必要です。
それぞれ、Framed-IP-AddressとFramed-IP-Netmaskがそのアトリビュートとして決められています。

ここでも、あまり深く考えずに手順を見ていきましょう。

ユーザーファイル

# vi /usr/local/radius/etc/raddb/users

ユーザーファイルに下記を追記してください。 Framed-IP-Addressの先頭に半角スペース(またはタブ)が必須です。

------------------------------

file@nttpc.co.jp Cleartext-Password := "file-pw", Calling-Station-Id := "0300000000"
Framed-IP-Address := 172.16.1.1, Framed-IP-Netmask := "255.255.255.255"

------------------------------

MySQL

これまでと異なり、radreplyテーブルに追加します。 構造は、radcheckテーブルと同様です。

# mysql -u root radius
mysql> desc radreply;

mysql> insert into radreply values (null, "mysql@nttpc.co.jp", "Framed-IP-Address", ":=", "172.16.2.1");
mysql> insert into radreply values (null, "mysql@nttpc.co.jp", "Framed-IP-Netmask", ":=", "255.255.255.255");

mysql> select * from radreply;
+----+-------------------+-------------------+----+-----------------+
| id | username     | attribute     | op | value      |
+----+-------------------+-------------------+----+-----------------+
| 1 | mysql@nttpc.co.jp | Framed-IP-Address | := | 172.16.2.1   |
| 2 | mysql@nttpc.co.jp | Framed-IP-Netmask | := | 255.255.255.255 |
+----+-------------------+-------------------+----+-----------------+
2 rows in set (0.00 sec)

FreeRADIUSのプロセス再起動

デバックモードで起動したままでしたら、Ctrl-cなどで終了させてプロセスを起動し直してください。

動作確認: radclient

それでは、radclientで動作確認してみましょう!
認証要求には、何も追加する必要はありません。

radclientに、Framed-IP-AddressとFramed-IP-Netmaskが追加されるようになりましたね。
FreeRADIUSの初期設定では、Access-Rejectにはほとんどアトリビュートを設定できません。
Framed-IP-AddressとFramed-IP-Netmaskも設定できないようになっています。
これは、認証応答で設定してもよいアトリビュートを制限するモジュールが働いているためです。

ユーザーファイルでPAP認証(Access-Accept)
# /usr/local/radius/bin/radclient -x -f /root/radius.auth.attr 192.168.10.100 auth shared-key
Sending Access-Request of id 222 to 192.168.10.100 port 1812
    User-Name = "file@nttpc.co.jp"
    User-Password = "file-pw"
    Calling-Station-Id = "0300000000"
rad_recv: Access-Accept packet from host 192.168.10.100 port 1812, id=222, length=32
    Framed-IP-Address = 172.16.1.1
    Framed-IP-Netmask = 255.255.255.255
ユーザーファイルでPAP認証(Access-Reject)
# /usr/local/radius/bin/radclient -x -f /root/radius.auth.attr 192.168.10.100 auth shared-key
Sending Access-Request of id 122 to 192.168.10.100 port 1812
    User-Name = "file@nttpc.co.jp"
    User-Password = "wrong-pw"
    Calling-Station-Id = "0300000000"
rad_recv: Access-Reject packet from host 192.168.10.100 port 1812, id=122, length=20
MySQLでPAP認証(Access-Accept)
# /usr/local/radius/bin/radclient -x -f /root/radius.auth.attr 192.168.10.100 auth shared-key
Sending Access-Request of id 81 to 192.168.10.100 port 1812
    User-Name = "mysql@nttpc.co.jp"
    User-Password = "mysql-pw"
    Calling-Station-Id = "0600000000"
rad_recv: Access-Accept packet from host 192.168.10.100 port 1812, id=81, length=32
    Framed-IP-Address = 172.16.2.1
    Framed-IP-Netmask = 255.255.255.255
MySQLでPAP認証(Access-Reject)
# /usr/local/radius/bin/radclient -x -f /root/radius.auth.attr 192.168.10.100 auth shared-key
Sending Access-Request of id 19 to 192.168.10.100 port 1812
    User-Name = "mysql@nttpc.co.jp"
    User-Password = "wrong-pw"
    Calling-Station-Id = "0600000000"
rad_recv: Access-Reject packet from host 192.168.10.100 port 1812, id=19, length=20

おわりに

いかがでしたでしょうか?
今回は、細かい説明は省略して手順に絞ってご紹介しました。
次回は、さらに深く使ってみたい方向けの内容にしたいと思います。

たとえば…
・802.1X(EAP-TLS/TTLS)の認証
・モジュールの具体的な使い方
・FreeRADIUSのさらに深い設定方法

どうぞお楽しみに!

この技術を使ったNTTPCのサービス

認証アウトソースサービス (RADIUSタイプ)

page top