freeradius + AD(samba4) + mac-radius

freeradius で mac-radius を AD(samba4)を経由してやろうという話です。
freeradius で mac-radius をやるには、 users ファイルなどに mac アドレスを書くしかないんですが、
そこをなんとかして、 ADというか ldap 経由で macaddress を引いてこようというと。


既存の freeradius でどうしても無理なので、freeradius のソースを改造し、パッチを作成してみました。
今回をこれを使って、 AD(ldap) + mac-radius を実現してみます。


前回作ったパッチの説明になります。
http://d.hatena.ne.jp/rti7743/20110507/1304717930

mac-address って AD にあったっけ?

mac-address って AD にあったっけ?
ないです。たぶん。もしかしたら、新しい windows serverはあるのかな?

なんで別の適当なカラムで代用します。
もちろん、そんなことをしてしまうと ldapの理念である統一されたスキーマというのが失われてしまいますが、「そんなの関係知らね」ってことで、適当にやります。
今回は、「電話」タブの中にある、ポケベルというカラムで代用してみます。

どうせ、ポケベルなんて使っている人はもういないだろうし・・・
もし、ポケベル使っているなら、別のFAXとかオフィスで個人ごとにもっている人は少ないだろうからここを使うとか。


ポケベルのカラムは、その他のボタンを押すと、同一アトリビュートに複数の項目を入れることができます。
これは一人が複数台のPCを所有していて MAC-ADDRESS を複数もっているような状態を表現するには適しています。


ちなみに、samba4 では、 ポケベルが pager 、複数台のポケベルは otherPager で表現されます。
今回は、ポケベルの所は無視して、複数台のポケベルを使ってデータを表現します。



ポケベルのところには適当な値を入れる。

ポケベルのその他にマックアドレスを入れる。
このとき、すべて小文字で : - などを抜かして入力します。

12-33-44-ab-cc
↓
123344abcc

12:33:44:ab:cc
↓
123344abcc

観察の前に観察用のユーザを作る

AD は、データを閲覧するぬめに閲覧用のユーザが必要になります。
administrator とかでもいいんですが、パスワードをクリアテキストでかかなきゃいけないところも出てくるので専用のユーザを作ったほうがいいです。
今回は、 ldap_bind_user というユーザを作成します。


ADに接続するには、 ガチのActiveDirectoryの場合はコンソールから入ります。
samba4 でやっている人は、 MSのRSATとかから入ります。
RSATと接続する場合、ドメインに所属していないPCからやるとエラーになります。
また、ユーザを作ったり編集したりするので、 Administratorさんか、Administrators グループに所属しているユーザでログインしなくてはいけません。
めんどうなら、Administrator でやればいいじゃない。


Usersのところで右クリックして新規ユーザを作る。

フルネームのところに、 ldap_bind_user と入力。
ユーザログオン名の所も ldap_bind_user と入力。

パスワードは "secret@1" します。
「ユーザは次回ログオン時にパスワードの変更が必要」を「外す」
「パスワードを無期限にする」を「オン」、

依存パッケージをまず入れる。

yum install openldap-clients libtool-ltdl perl-DBI

観察

ldapsearch (openldap-clients パッケージ)コマンドを利用するとldapの中身を観察できます。
しかし、このコマンド結構があって使いづらい・・・


今回、ADのサーバが 192.168.56.234 で稼動していることにします。
ADのUsersの領域は、'cn=Users,dc=rti7743,dc=local' とします。
bindする人は、'ldap_bind_user@rti7743.local' で、
パスワードは "secret@1" します。
注意:シェルなので、パスワードにらメタ文字 ! とかを含む場合は \! とエスケープしてくださいね。




メモ
ADのスキーマが rti7743.local だったとすると、 "dc=rti7743,dc=local" となります。
ADでユーザを入れる領域は Users になりますが、ここは、 "cn=Users,dc=rti7743,dc=local" になります。

ldapsearch -V 3 -h 192.168.56.234 -x -b 'cn=Users,dc=rti7743,dc=local' -D 'ldap_bind_user@rti7743.local' -w "secret@1" "*"
# rti, Users, rti7743.local
dn: CN=rti,CN=Users,DC=rti7743,DC=local
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: rti
instanceType: 4
whenCreated: 20110425212936.0Z
uSNCreated: 3462
name: rti
objectGUID:: dlQ0+UDoq0uBs/8MQuFwFA==
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 0
lastLogoff: 0
lastLogon: 0
primaryGroupID: 513
objectSid:: AQUAAAAAAAUVAAAAggN5mECLrro61m1zUAQAAA==
accountExpires: 9223372036854775807
logonCount: 0
sAMAccountName: rti
sAMAccountType: 805306368
userPrincipalName: rti@rti7743.local
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=rti7743,DC=local
userAccountControl: 512
pwdLastSet: 129482408500000000
otherPager: 123344abcc
otherPager: bbccddee11
whenChanged: 20110507171837.0Z
uSNChanged: 3702
distinguishedName: CN=rti,CN=Users,DC=rti7743,DC=local

これがユーザー分だけどっさりでる。
うまくいかない場合 Simple Bind Failed: NT_STATUS_LOGON_FAILURE

Simple Bind Failed: NT_STATUS_LOGON_FAILURE がでた場合は、 bind するユーザが間違っています。

ldapsearch: @(#) $OpenLDAP: ldapsearch 2.3.43 (Mar 30 2011 20:24:37) $
        mockbuild@builder10.centos.org:/builddir/build/BUILD/openldap-2.3.43/openldap-2.3.43/build-clients/clients/tools
        (LDAP library: OpenLDAP 20343)
ldap_bind: Invalid credentials (49)
        additional info: Simple Bind Failed: NT_STATUS_LOGON_FAILURE
うまくいかない場合 エラーじゃないけど表示されない場合。

名前を打ち間違っていないでしょうか?
この例だと -b 'cn=Users2,dc=rti7743,dc=local' と名前を打ち間違えました。

ldapsearch: @(#) $OpenLDAP: ldapsearch 2.3.43 (Mar 30 2011 20:24:37) $
        mockbuild@builder10.centos.org:/builddir/build/BUILD/openldap-2.3.43/openldap-2.3.43/build-clients/clients/tools
        (LDAP library: OpenLDAP 20343)
# extended LDIF
#
# LDAPv3
# base <cn=Users2,dc=rti7743,dc=local> with scope subtree
# filter: (objectclass=*)
# requesting: 3 *
#

# search result
search: 2
result: 32 No such object
text: 00002030: No such object - No such Base DN: cn=Users2,dc=rti7743,dc=loc
 al

# numResponses: 1

必要なカラムのみを表示する。

なんかいろいろ出てきましたね。
必要なカラムだけ表示してみましょう。

ldapsearch -V 3 -h 192.168.56.234 -x -b 'cn=Users,dc=rti7743,dc=local' -D 'ldap_bind_user@rti7743.local' -w "secret@1" otherPager

ずいぶんすっきりしました。

# rti2, Users, rti7743.local
dn: CN=rti2,CN=Users,DC=rti7743,DC=local
otherPager: abcdef1112223
otherPager: 123e1241cccdd

これがユーザー分だけどっさりでる。

と、いうわけで、 ポケベルのその他に入力した値が取れました。 otherPager を利用して mac-radius をやってみます。

メモ
ふつー検索しない otherPager には、たぶん index がはられていないと思います。
だけど、今のPCだと数万件レベルまでは余裕だと思いますが、、重くなったら index をはらないといけないですね。
samba4 でどうやって index を貼るのか知らないけどw

freeradius の rti改造版を入れます。

freeradius には、 ldap + mac-address 認証がないので、 rti 改造版を入れます。
ここに公開しているので適当に使ってください。
http://rtilabs.net/files/2011_05_07/

rpm から入れたい人はこっち。
wget http://rtilabs.net/files/2011_05_07/freeradius2-utils-2.1.10-ldap_macradius_patch.7.x86_64.rpm
wget http://rtilabs.net/files/2011_05_07/freeradius2-2.1.10-ldap_macradius_patch.7.x86_64.rpm
wget http://rtilabs.net/files/2011_05_07/freeradius2-ldap-2.1.10-ldap_macradius_patch.7.x86_64.rpm

rpm -Uvh freeradius2-2.1.10-ldap_macradius_patch.7.x86_64.rpm freeradius2-ldap-2.1.10-ldap_macradius_patch.7.x86_64.rpm freeradius2-utils-2.1.10-ldap_macradius_patch.7.x86_64.rpm
ソースから入れたい人はこっち。

ソースから入れると、 ディフォルトで /usr/local/* の中に入るよ。
/usr/local/etc/raddb/ が設定で、 /usr/local/sbin/ とか/usr/local/bin/ にコマンド。

wget ftp://ftp.freeradius.org/pub/freeradius/freeradius-server-2.1.10.tar.bz2
tar jxvf freeradius-server-2.1.10.tar.bz2

##パッチはこんなふうに作った
## diff -crN freeradius-server-2.1.10.org freeradius-server-2.1.10 > ldap_mac_radius_mode__set_mac_radius_mode_without_password.patch
#パッチを当てる
wget http://rtilabs.net/files/2011_05_07/ldap_mac_radius_mode__set_mac_radius_mode_without_password.patch
patch < ldap_mac_radius_mode__set_mac_radius_mode_without_password.patch

#ふつーにビルド
./configure
make
make install


とりあえず rpm から入れたと仮定して話をすすめる。

まずは起動する。

ふつーに起動すると、最初は必ず失敗するので、最初の一発目は、ルート権限でデバッグモードで起動する。
Ready to process requests. って出たら、 ctrl + C で終了する。

/usr/sbin/radiusd -X

#
#Ready to process requests. ってでるまでまつ
#
#Ready to process requests.ってでたら Ctrl + C で止める。

#次からは成功するはず
/etc/init.d/radiusd start

ldap対応にするために設定をいじり回ります。

結構あっちこっちの設定をいじります。

ldap.initscript を横にどけます。

ナンカ /etc/raddb/modules/ldap.initscript というファイルができていて、こっちを見に行くってしまう時があるようです。
邪魔なのでどけます。
(なんでこれができるんだろう・・・ダレか教えて!)

mv /etc/raddb/modules/ldap.initscript /etc/raddb/modules/_ldap.initscript

Auth-Type = LDAP の追加

認証の種類に LDAP を追加します。

vi /etc/raddb/dictionary
-----------末尾に追加----------------------------------------------
VALUE           Auth-Type               LDAP    5
-------------------------------------------------------------------

userの認証をLDAPに投げるように指示を出します。

vi /etc/raddb/users
--------------- 上の方に追記----------------
DEFAULT         Auth-Type = LDAP
                Fall-Through = 1
--------------------------------------------

ldap認証を有効にします。

似たような箇所がいくつもあるので注意してください。
今回修正するのは、 authorize と authorize です。他は修正しません。

vi /etc/raddb/sites-available/default
--------------------------------------------------------------------------
authorize {
	〜中略〜
        #
        #  The ldap module will set Auth-Type to LDAP if it has not
        #  already been set
#       ldap

	〜中略〜
}

↓修正修正修正修正修正修正↓

authorize {
	〜中略〜
        #
        #  The ldap module will set Auth-Type to LDAP if it has not
        #  already been set
       ldap

	〜中略〜
}
authenticate {
	〜中略〜
        # Uncomment it if you want to use ldap for authentication
        #
        # Note that this means "check plain-text password against
        # the ldap database", which means that EAP won't work,
        # as it does not supply a plain-text password.
#       Auth-Type LDAP {
#               ldap
#       }

	〜中略〜
}

↓修正修正修正修正修正修正↓

authenticate {
	〜中略〜
        # Uncomment it if you want to use ldap for authentication
        #
        # Note that this means "check plain-text password against
        # the ldap database", which means that EAP won't work,
        # as it does not supply a plain-text password.
       Auth-Type LDAP {
               ldap
       }

	〜中略〜
}
--------------------------------------------------------------------------

ldap認証を有効にします。

vi /etc/raddb/modules/ldap
ldap {
	〜中略〜
        #
        #  Note that this needs to match the name in the LDAP
        #  server certificate, if you're using ldaps.
        server = "ldap.your.domain"
        #identity = "cn=admin,o=My Org,c=UA"
        #password = mypass
        basedn = "o=My Org,c=UA"
        filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
        #base_filter = "(objectclass=radiusprofile)"

	〜中略〜
	〜今回のハックルーチンを有効にします。〜
	〜ファイルの一番下の方にあります。〜

        #
        # mac-radius when you only want to use.
        #ldap filter to authenticate using only ignores the password check.
        #The default is off. (password authentication to)
        #Please enable mac-radius only when performing.
        #
        #set_mac_radius_mode_without_password = no

	〜中略〜


↓修正修正修正修正修正修正↓

ldap {
        #
        #  Note that this needs to match the name in the LDAP
        #  server certificate, if you're using ldaps.
        server = "192.168.56.234"
        identity = "cn=ldap_bind_user,cn=Users,dc=rti7743,dc=local"
        password = "secret@1"
        basedn = "cn=Users,dc=rti7743,dc=local"
        filter = "(otherPager=%{%{Stripped-User-Name}:-%{User-Name}})"

	〜中略〜
	〜今回のハックルーチンを有効にします。〜
	〜ファイルの一番下の方にあります。〜

        #
        # mac-radius when you only want to use.
        #ldap filter to authenticate using only ignores the password check.
        #The default is off. (password authentication to)
        #Please enable mac-radius only when performing.
        #
        set_mac_radius_mode_without_password = yes

クライアント受け入れの準備

さて、テストと行きたいのですが、
radius では設定されていないクライアントからはリクエストできません。
まずは、テスト用のクライアントの設定を書きます。

テストするサーバは 192.168.56.123 、secret は test123 とします。

vi /etc/raddb/clients.conf
--------------- 末尾に追加----------------------------
client  192.168.56.123 {
              secret              = test123
              shortname           = test
}
-----------------------------------------------------

テストのための起動

テストするとき、 radiusデバッグモードで起動すると便利です。

一度止めてから

/etc/init.d/radiusd stop

デバッグモードで起動する

/usr/sbin/radiusd -X

うまくうごきましたか?

うまくいかない場合 /etc/raddb/dictionary に追加し忘れた場合
/etc/raddb/users[49]: Parse error (check) for entry DEFAULT: Unknown value LDAP for attribute Auth-Type
Errors reading /etc/raddb/users
/etc/raddb/modules/files[7]: Instantiation failed for module "files"
/etc/raddb/sites-enabled/inner-tunnel[124]: Failed to load module "files".
/etc/raddb/sites-enabled/inner-tunnel[47]: Errors parsing authorize section.
||

/etc/raddb/dictionary の設定を確認して下さい。


**テスト

さて、radius のテストプログラムから接続してみて挙動を観察します。

ユーザ名に登録された mac address を入れると Access-Accept 。
パスワードはどうなものを入れてもmac addressだけで Access-Accept 。
しかし、登録されていない mac-address を入れると、 Access-Reject 。
うまく動きましたか?


ユーザ名に登録された mac address を入れると Access-Accept 。
>||
[root@samba3test ~]#  /usr/bin/radtest "abcdef1112223" "" 192.168.56.123 1 test123
Sending Access-Request of id 142 to 192.168.56.123 port 1812
        User-Name = "abcdef1112223"
        User-Password = ""
        NAS-IP-Address = 192.168.56.123
        NAS-Port = 1
rad_recv: Access-Accept packet from host 192.168.56.123 port 1812, id=142, length=20


パスワードはどうなものを入れてもmac addressだけで Access-Accept 。

[root@samba3test ~]#  /usr/bin/radtest "abcdef1112223" "nanka" 192.168.56.123 1 test123
Sending Access-Request of id 194 to 192.168.56.123 port 1812
        User-Name = "abcdef1112223"
        User-Password = "nanka"
        NAS-IP-Address = 192.168.56.123
        NAS-Port = 1
rad_recv: Access-Accept packet from host 192.168.56.123 port 1812, id=194, length=20


しかし、登録されていない mac-address を入れると、 Access-Reject
[root@samba3test ~]# /usr/bin/radtest "abcdef1112223XXX" "nanka" 192.168.56.123 1 test123

Sending Access-Request of id 52 to 192.168.56.123 port 1812
        User-Name = "abcdef1112223XXX"
        User-Password = "nanka"
        NAS-IP-Address = 192.168.56.123
        NAS-Port = 1
rad_recv: Access-Reject packet from host 192.168.56.123 port 1812, id=52, length=20
うまくいかない場合 radclient: no response from server for ID 191 socket 3 が出る。

vi /etc/raddb/clients.conf の設定を間違うと発生します。

Sending Access-Request of id 191 to 192.168.56.123 port 1812
        User-Name = "abcdef1112223"
        User-Password = "nanka"
        NAS-IP-Address = 192.168.56.123
        NAS-Port = 1
rad_recv: Access-Accept packet from host 192.168.56.123 port 1812, id=191, length=20
rad_verify: Received Access-Accept packet from home server 192.168.56.123 port 1812 with invalid signature!  (Shared secret is incorrect.)
radclient: no response from server for ID 191 socket 3
うまくいかない場合 LDAP にアクセスしてくれない その1 WARNING: Unknown value specified for Auth-Type. Cannot perform requested action.
Found Auth-Type = LDAP
  WARNING: Unknown value specified for Auth-Type.  Cannot perform requested action.


/etc/raddb/sites-available/default の authenticate の LDAP の設定がうまくいかないと発生します。

vi /etc/raddb/sites-available/default
authenticate {
       Auth-Type LDAP {
                ldap
        }
}
うまくいかない場合 LDAP にアクセスしてくれない その2 LDAP login failed

ldap サーバの設定が間違っていると発生します。

[ldap]  expand: cn=Users,dc=rti7743,dc=local -> cn=Users,dc=rti7743,dc=local
  [ldap] ldap_get_conn: Checking Id: 0
  [ldap] ldap_get_conn: Got Id: 0
  [ldap] attempting LDAP reconnection
  [ldap] (re)connect to 192.168.56.234:389, authentication 0
  [ldap] bind as cn=ldap_bind_user2,cn=Users,dc=rti7743,dc=local/secret@1 to 192.168.56.234:389
  [ldap] waiting for bind result ...
  [ldap] LDAP login failed: check identity, password settings in ldap section of radiusd.conf
  [ldap] (re)connection attempt failed
[ldap] search failed
  [ldap] ldap_release_conn: Release Id: 0
++[ldap] returns fail


/etc/raddb/modules/ldap の設定を見なおしてください。
サーバIPはあっているか、 bind するユーザは正しいかなどを観直してください。
ldapsearch などで本当に引けるかも確認して下さい。

うまくいかない場合 user DN: が定まったあとに認証エラー!

今回の修正パッチバージョンを使っていないか、 /etc/raddb/modules/ldap で set_mac_radius_mode_without_password = yes にしていないと発生します。

Found Auth-Type = LDAP
# Executing group from file /etc/raddb/sites-enabled/default
+- entering group LDAP {...}
[ldap] login attempt by "abcdef1112223" with password "nanka"
[ldap] user DN: CN=rti2,CN=Users,DC=rti7743,DC=local
  [ldap] (re)connect to 192.168.56.234:389, authentication 1
  [ldap] bind as CN=rti2,CN=Users,DC=rti7743,DC=local/nanka to 192.168.56.234:389
  [ldap] waiting for bind result ...
  [ldap] Bind failed with invalid credentials
++[ldap] returns reject
Failed to authenticate the user.
Using Post-Auth-Type Reject

実機で試す!!

ここまで来れば wifi スイッチとか、 mac-radius がしたい機材で試してみるのみです。
機材の情報を /etc/raddb/clients.conf に追加するのを忘れないようにしてくださいね。

client  192.168.56.10 {
              secret              = wifisecret
              shortname           = wifi01
}