| Top | Solarisの話 | OpenSSLの話 | OpenLDAPの話 | MySQLの話 | FreeRADIUSの話 |
Last update: 2004/11/27
+---------------------------+ +-------------+ | rlm_ldap (authorize) | --- bind ---> | LDAP server | | ldap.attrmap | query | | | +--------+ | | | +---------+ | | |RADIUS | <--- mapping <-----------------| |ldap | | | | attr | | | | attr | | | +--------+ | | +---------+ | +---------------------------+ +-------------+
rlm_ldapモジュールのAuthorizeでは、LDAPからユーザのアトリビュート取得します。 LDAPへのbindはrlm_ldapのオプションのidentify,passwordが使われます。
LDAPから取得するアトリビュートはldap.attrmapに書かれているもので、 取得した後でRADIUSのアトリビュートに変換(マッピング)されます。
ldap.attrmapには、RADIUSのアトリビュートの種類、RADIUSのアトリビュート名、LDAPのアトリビュート名を書きます。RADIUSのアトリビュートの種類にはcheckItemとreplyItemがあり、replyItemのアトリビュートは認証時にNASに送信されます。
LDAPのuserPasswordはRADIUSのUser-Passwordにマッピングされますが、 通常userPasswordの値は{crypt}....のようにcryptされた値や MD5やSHAなどでハッシュされた値が入っていますので、 rlm_mschapモジュールでのAuthenticationには使用できません。
LDAPで別のスキーマを定義してuserPassword以外のアトリビュートを 使うことも出来ますが、 その場合は、rlm_ldapのオプションのpassword_attributeに LDAPのアトリビュートの名前を指定し、 LDAPには生のパスワードを格納することになりますので、 あまりお勧めできません。
その為、rlm_mschapモジュールでAuthenticationを行う場合には、LDAPにはntPasswordとlmPasswordを設定し、ハッシュされたパスワードを格納します。
(src/modules/rlm_mschap/smbencryptコマンドでハッシュされたパスワードを生成することが可能です)
Samba 3.0.xのsamba.schemaでは、スキーマが変更になり、lmPassword -> sambaLMPassword、ntPassword -> sambaNTPassword、acctFlags -> sambaAcctFlagsに変更になっています。新しいスキーマのLDAPを使う場合は、ldap.attrmapを適宜書き換える必要があります。
rlm_ldapではLDAPからユーザを取得する際に検索フィルタを指定できます。 指定したフィルタにマッチしたユーザだけを許可することが可能です。
TLSを使用する場合は、/usr/local/etc/openldap/ldap.confにTLS用の各証明書や鍵の設定を行います。
(LDAPのプロトコルバージョン2を使用する場合は、rlm_ldap.cのソースを書き換える必要があります)
access_attr_used_for_allowの値がyesの場合、 access_attrで指定したLDAPアトリビュートの値が 存在しないか、'FALSE'の時はそのユーザがロックされているとみなされます。
access_attr_used_for_allowがnoの場合、access_attrで指定したLDAPアトリビュートの値が存在する場合は、そのユーザはロックされているとみなされます。
default_profileには、デフォルトで読み込むRADIUS ProfileのDNを設定します。
profile_attributeは、ユーザ毎に違うRADIUS ProfileのDNを適用する場合に、 そのRADIUS Profileを指定するためのアトリビュートの名前を指定します。 このアトリビュートが存在する場合、この値をRADIUS profileのDNとして、指定されたprofileを読み込みます。 グループ毎にプロファイルの値を変える場合に使用します。
rlm_mschapモジュールのAuthenticateでは、AuthorizeモジュールによってLDAPから取得したアトリビュートを使って、認証をおこないます。
rlm_mschapモジュールのPAP/MS-CHAP/MS-CHAPv2認証では、 NT-PasswordとLM-Password、SMB-Account-Ctrl/SMB-Account-Ctrl-Textが使われます。
NT-PasswordとLM-Passwordアトリビュートが存在しない場合は、 User-Password(生パスワード)を元にNT-PasswordやLM-Passwordを計算します。
SMB-Account-Ctrl/SMB-Account-Ctrl-Textは、Windowsのユーザフラグで、 ユーザアカウントの無効やロックアウトのフラグが設定されている場合は、 認証を拒否します。 また、パスワード不要のフラグが設定されている場合は、 パスワードに関係なく許可されますが、MPPEが利用できません。
SMB-Account-Ctrl-Textは、SMB-Account-Ctrlのテキスト形式の値で、SMB-Account-Ctrlが存在しない場合に使用されます。次のような値です。
[UWDX ] |
SMB-Account-Ctrlはバイナリ形式の値で、複数のフラグのOR値です。
| フラグ | バイナリ値 | テキスト値 | 説明 |
|---|---|---|---|
| ACB_DISABLE | 0x0001 | D | アカウント無効 |
| ACB_PWNOTREQ | 0x0004 | N | パスワード不要 |
| ACB_NORMAL | 0x0010 | U | 有効なアカウント (設定しないと無効) |
| ACB_AUTOLOCK | 0x0400 | L | ロックアウト |
SMB-Account-Ctrl、SMB-Account-Ctrl-TEXT共に存在しない場合はACB_NORMALとみなされます。
(rlm_ldapモジュールでSAMBA LDAPのsambaAcctFlags(旧acctFlags)をSMB-Account-Ctrl-Textにマッピングする場合、 値に空白が含まれると空白の後ろが切り詰められてしまい、正しくッピングされません)
rlm_mschapモジュールでPAP認証をする場合は、LM-PasswordかNT-Passwordを使って、NASから送られてきたパスワードをLM HASH/NT HASHして比較します。
rlm_mschapモジュールでMS-CHAP/MS-CHAPv2認証する場合は、LM-PasswordとNT-Passwordを使って、NASから送られてきたChallengeからResponseを計算し、NASから送られてきたとResponseと比較します。
デフォルトではLDAPのlmPassword、ntPassword、acctFlagsのアトリビュートがマッピングされています。これらのLDAPアトリビュートはSAMBA LDAPのschemaを利用するか、独自のschemaを定義する必要があります。
rlm_sqlモジュールのAccountingでは、NASから送られてくるAccounting-RequestをSQLサーバーに残します。
SQLサーバに残すアトリビュートは、sql.confで設定します。アクセスログを記録する場合はaccounting_start_query,accounting_start_query_alt,accounting_stop_query,accounting_stop_query_altを設定します。
VPN装置等で接続元のIPアドレス等を記録する場合は、Tunnel-Client-Endpoint等の値を追加するようにします。
gcc 3.3.2を使用
./configure gmake gmake install
SAMBA LDAPのスキーマとRADIUS-LDAPv3のスキーマをopenldapのschemaディレクトリに入れておきます。RADIUS-LDAPv3.schemaはfreeradius/doc/の中にあります。
include /usr/local/etc/openldap/schema/core.schema
include /usr/local/etc/openldap/schema/cosine.schema
include /usr/local/etc/openldap/schema/inetorgperson.schema
include /usr/local/etc/openldap/schema/nis.schema
include /usr/local/etc/openldap/schema/solaris.schema
include /usr/local/etc/openldap/schema/samba.schema
include /usr/local/etc/openldap/schema/RADIUS-LDAPv3.schema
schemacheck on
# Define global ACLs to disable default read access.
TLSCertificateFile /usr/local/etc/openldap/server-cert.pem
TLSCertificateKeyFile /usr/local/etc/openldap/server-key.pem
TLSCACertificateFile /usr/local/etc/openldap/ca-cert.pem
TLSVerifyClient allow
# Do not enable referrals until AFTER you have a working directory
# service AND an understanding of referrals.
#referral ldap://root.openldap.org
pidfile /usr/local/var/slapd.pid
argsfile /usr/local/var/slapd.args
# Load dynamic backend modules:
# modulepath /usr/local/libexec/openldap
# moduleload back_bdb.la
# moduleload back_ldap.la
# moduleload back_ldbm.la
# moduleload back_passwd.la
# moduleload back_shell.la
# Sample security restrictions
#
# Disallow clear text exchange of passwords
# disallow bind_simple_unprotected
#
# Require integrity protection (prevent hijacking)
# Require 112-bit (3DES or better) encryption for updates
# Require 63-bit encryption for simple bind
# security ssf=1 update_ssf=112 simple_bind=64
# Sample access control policy:
# Root DSE: allow anyone to read it
# Subschema (sub)entry DSE: allow anyone to read it
# Other DSEs:
# Allow self write access
# Allow authenticated users read access
# Allow anonymous users to authenticate
# Directives needed to implement policy:
#access to dn.base="" by * read
#access to dn.base="cn=Subschema" by * read
#access to *
# by self write
# by users read
# by anonymous auth
#
# if no access controls are present, the default policy is:
# Allow read by all
#
# rootdn can always write!
access to dn.base="" by * read
access to dn.base="cn=Subschema" by * read
access to *
by users read
by anonymous auth
access to dn.sub="ou=Users,dc=waga,dc=homeip,dc=net"
attrs=userPassword,lmPassword,ntPassword
by self write
by anonymous auth
#######################################################################
# ldbm database definitions
#######################################################################
database bdb
suffix "dc=waga,dc=homeip,dc=net"
rootdn "cn=Manager,dc=waga,dc=homeip,dc=net"
# Cleartext passwords, especially for the rootdn, should
# be avoid. See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
rootpw slappasswdで生成
# The database directory MUST exist prior to running slapd AND
# should only be accessible by the slapd and slap tools.
# Mode 700 recommended.
directory /usr/local/var/openldap-data
# Indices to maintain
index objectClass eq
index uid pres,eq
index cn,sn,dc pres,eq,sub
index uidNumber pres,eq
index gidNumber pres,eq
|
MySQLにスキーマを作成します。src/modules/rlm_sql/drivers/rlm_sql_mysqlの中にdb_mysql.sqlファイルがあるので、これを使ってデータベースを作り、アクセスするアカウントの権限も設定します。
db_mysql.sqlに書かれているradacctテーブルのCallingStationIdとCalledStationIdは10文字になっていて、VPN等で使用する場合には、IPアドレスが入ることもある為、必要に応じて増やしておきます。その他必要なアトリビュート用のカラムも作成しておきます。
vi db_mysql.sql
CalledStationId varchar(50) NOT NULL default '',
CallingStationId varchar(50) NOT NULL default '',
/usr/local/mysql/bin/mysql -u root -p
mysql> create database radius;
Query OK, 1 row affected (0.02 sec)
mysql> use radius
Database changed
mysql> source db_mysql.sql
Query OK, 0 rows affected (0.03 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> grant select,update,insert on radius.*
-> to hoge@'radius.waga.homeip.net'
-> identified by '??????????';
Query OK, 0 rows affected (0.03 sec)
mysql> alter table radacct add column TunnelClientEndpoint varchar(50);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> alter table radacct add column TunnelType varchar(15);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
|
clients.conf クライアントのシークレットの設定(例)
client 192.168.10.10 {
secret = password
shortname = pptpserver
};
|
users ユーザの基本設定(例)
DEFAULT Auth-Type := MS-CHAP,NAS-IP-Address == 192.168.10.10,Calling-Station-Id =~ ".*" DEFAULT Auth-Type := Reject,NAS-IP-Address == 192.168.10.10,Calling-Station-Id =~ "00.*" DEFAULT Auth-Type := MS-CHAP,NAS-IP-Address == 192.168.10.11 |
ldap.attrmapの設定
SMB-Account-CTRL-TEXTのマッピングをコメントアウトしておく。 (ldapモジュールで、acctFlagsの文字列を正しくマッピング出来ない為) #checkItem SMB-Account-CTRL-TEXT acctFlags |
sql.conf MySQLクライアントの設定(例)
sql {
driver = "rlm_sql_mysql"
server = "mysql.waga.homeip.net"
login = "radserver"
password = "password"
radius_db = "radius"
acct_table1 = "radacct"
acct_table2 = "radacct"
authcheck_table = "radcheck"
authreply_table = "radreply"
groupcheck_table = "radgroupcheck"
groupreply_table = "radgroupreply"
usergroup_table = "usergroup"
deletestalesessions = yes
sqltrace = no
sqltracefile = ${logdir}/sqltrace.sql
num_sql_socks = 5
sql_user_name = "%{User-Name}"
authorize_check_query = "SELECT id,UserName,Attribute,Value,op FROM ${authcheck_table} WHERE Username = '%{SQL-User-Name}' ORDER BY id"
authorize_reply_query = "SELECT id,UserName,Attribute,Value,op FROM ${authreply_table} WHERE Username = '%{SQL-User-Name}' ORDER BY id"
authorize_group_check_query = "SELECT ${groupcheck_table}.id,${groupcheck_table}.GroupName,${groupcheck_table}.Attribute,${groupcheck_table}.Value,${groupcheck_table}.op FROM ${groupcheck_table},${usergroup_table} WHERE ${usergroup_table}.Username = '%{SQL-User-Name}' AND ${usergroup_table}.GroupName = ${groupcheck_table}.GroupName ORDER BY ${groupcheck_table}.id"
authorize_group_reply_query = "SELECT ${groupreply_table}.id,${groupreply_table}.GroupName,${groupreply_table}.Attribute,${groupreply_table}.Value,${groupreply_table}.op FROM ${groupreply_table},${usergroup_table} WHERE ${usergroup_table}.Username = '%{SQL-User-Name}' AND ${usergroup_table}.GroupName = ${groupreply_table}.GroupName ORDER BY ${groupreply_table}.id"
authenticate_query = "SELECT Value,Attribute FROM ${authcheck_table} WHERE UserName = '%{User-Name}' AND ( Attribute = 'User-Password' OR Attribute = 'Password' OR Attribute = 'Crypt-Password' ) ORDER BY Attribute DESC"
accounting_onoff_query = "UPDATE ${acct_table1} SET AcctStopTime='%S', AcctSessionTime=unix_timestamp('%S') - unix_timestamp(AcctStartTime), AcctTerminateCause='%{Acct-Terminate-Cause}', AcctStopDelay = %{Acct-Delay-Time} WHERE AcctSessionTime=0 AND AcctStopTime=0 AND NASIPAddress= '%{NAS-IP-Address}' AND AcctStartTime <= '%S'"
accounting_update_query = "UPDATE ${acct_table1} SET FramedIPAddress = '%{Framed-IP-Address}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress= '%{NAS-IP-Address}'"
accounting_start_query = "INSERT into radacct (RadAcctId, AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay, TunnelClientEndpoint) values('', '%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', '%S', '0', '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '%{Acct-Delay-Time}', '0', '%{Tunnel-Client-Endpoint}')"
accounting_start_query_alt = "UPDATE ${acct_table1} SET AcctStartTime = '%S', AcctStartDelay = '%{Acct-Delay-Time}', ConnectInfo_start = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}'"
accounting_stop_query = "UPDATE ${acct_table1} SET AcctStopTime = '%S', AcctSessionTime = '%{Acct-Session-Time}', AcctInputOctets = '%{Acct-Input-Octets}', AcctOutputOctets = '%{Acct-Output-Octets}', AcctTerminateCause = '%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time}', ConnectInfo_stop = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}'"
accounting_stop_query_alt = "INSERT into radacct (RadAcctId, AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay, TunnelClientEndpoint) values('', '%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', '0', '%S', '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Connect-Info}', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Acct-Terminate-Cause}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0', '%{Acct-Delay-Time}', '%{Tunnel-Client-Endpoint}')"
}
|
radiusd.conf radiusサーバーの設定(例)
prefix = /usr/local
exec_prefix = ${prefix}
sysconfdir = ${prefix}/etc
localstatedir = ${prefix}/var
sbindir = ${exec_prefix}/sbin
logdir = ${localstatedir}/log/radius
raddbdir = ${sysconfdir}/raddb
radacctdir = ${logdir}/radacct
confdir = ${raddbdir}
run_dir = ${localstatedir}/run
libdir = ${exec_prefix}/lib
pidfile = ${run_dir}/radiusd.pid
user = root
group = root
max_request_time = 30
delete_blocked_requests = no
cleanup_delay = 5
max_requests = 1024
bind_address = *
port = 1645
checkrad = ${sbindir}/checkrad
hostname_lookups = no
allow_core_dumps = no
regular_expressions = yes
extended_expressions = yes
log_stripped_names = no
log_auth = no
log_auth_badpass = no
log_auth_goodpass = no
usercollide = no
lower_user = no
lower_pass = no
nospace_user = no
nospace_pass = no
security {
max_attributes = 200
reject_delay = 1
}
proxy_requests = no
$INCLUDE ${confdir}/proxy.conf
$INCLUDE ${confdir}/clients.conf
$INCLUDE ${confdir}/snmp.conf
thread pool {
start_servers = 5
max_servers = 32
min_spare_servers = 3
max_spare_servers = 10
max_requests_per_server = 0
}
modules {
mschap {
authtype = MS-CHAP
use_mppe = yes
require_encryption = yes
require_strong = yes
}
ldap {
server = "localhost"
identity = "cn=admin,dc=waga,dc=homeip,dc=net"
password = "password"
basedn = "ou=People,dc=waga,dc=homeip,dc=net"
filter = "(uid=%u)"
start_tls = no
default_profile = "cn=SambaRadProfile,dc=waga,dc=homeip,dc=net"
profile_attribute = "radiusProfileDn"
dictionary_mapping = ${raddbdir}/ldap.attrmap
ldap_connections_number = 5
timeout = 4
timelimit = 3
net_timeout = 1
}
preprocess {
huntgroups = ${confdir}/huntgroups
hints = ${confdir}/hints
with_ascend_hack = no
ascend_channels_per_line = 23
with_ntdomain_hack = no
with_specialix_jetstream_hack = no
with_cisco_vsa_hack = no
}
files {
usersfile = ${confdir}/users
acctusersfile = ${confdir}/acct_users
compat = no
}
detail {
detailfile = ${radacctdir}/%{Client-IP-Address}/detail
detailperm = 0600
}
$INCLUDE ${confdir}/sql.conf
radutmp {
filename = ${logdir}/radutmp
perm = 0600
callerid = "yes"
}
attr_filter {
attrsfile = ${confdir}/attrs
}
}
authorize {
preprocess
ldap
files
}
authenticate {
mschap
}
preacct {
suffix
files
preprocess
}
accounting {
detail
sql
}
session {
radutmp
}
|
| Top | Solarisの話 | OpenSSLの話 | OpenLDAPの話 | MySQLの話 | FreeRADIUSの話 |