Multiple LDAP server in Freeradius

當環境裡面有多個Active Directory/LDAP Server,並且存在不同Domain,身份驗證需要輪詢所有的Server時,會有以下條件需要達成:

  • 帳號需要依據順序向每個Active Directory/LDAP Server進行驗證
  • 驗證失敗時需要向下一台Active Directory/LDAP Server驗證
  • 驗證成功後要離開驗證程序

mods-available/ldap

將每個ldap server加入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
ldap ldap1 {
server = 'ldap1'
identity = 'cn=admin,dc=ldap1,dc=local'
password = '<admin password>'
base_dn = 'dc=ldap1,dc=local'
user {
base_dn = "${..base_dn}"
filter = "(cn=%{%{Stripped-User-Name}:-%{User-Name}})"
}
pool {
start = 0
}
}
ldap ldap2 {
server = "ldap2"
identity = "cn=admin,dc=ldap2,dc=local"
password = "<admin password>"
base_dn = "dc=ldap2,dc=local"
user {
base_dn = "${..base_dn}"
filter = "(cn=%{%{Stripped-User-Name}:-%{User-Name}})"
}
pool {
start = 0
}
}
ldap ldap3 {
server = "ldap3"
identity = "cn=admin,dc=ldap3,dc=local"
password = "<admin password>"
base_dn = "dc=ldap3,dc=local"
user {
base_dn = "${..base_dn}"
filter = "(cn=%{%{Stripped-User-Name}:-%{User-Name}})"
}
pool {
start = 0
}
}
ldap ldap4 {
server = "ldap4"
identity = "cn=admin,dc=ldap4,dc=local"
password = "<admin password>"
base_dn = "dc=ldap4,dc=local"
user {
base_dn = "${..base_dn}"
filter = "(cn=%{%{Stripped-User-Name}:-%{User-Name}})"
}
pool {
start = 0
}
}

預設pool裡面start的值是5,意思是啟動freeradius過程時會建立5個threads。
這裡改成0的用意是避免在freeradius啟動前,ldap server已無法正常運作,會造成freeradius啟動失敗。

policy.d/ldap

加入ldap authorize policy。

1
2
3
4
5
6
7
ldap.authorize {
if (User-Password && !control:Auth-Type) {
update control {
Auth-Type := LDAP
}
}
}

sites-available/default

authorize section

replace -ldap to ldap

1
2
3
4
5
6
authorize {
#
# The ldap module reads passwords from the LDAP database.
# -ldap
ldap
}

authenticate secion

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
authenticate {
Auth-Type LDAP {
group {
ldap1 {
fail = 1
reject = 1
notfound = 1
ok = return
}
ldap2 {
fail = 1
reject = 1
notfound = 1
ok = return
}
ldap3 {
fail = 1
reject = 1
notfound = 1
ok = return
}
ldap4 {
fail = 1
reject = 1
notfound = 1
ok = return
}
handled
}
}
}

這裡運用到unlang語法,並且使用 group 這個statement,在這個group裡面的服務均會循序執行。

另外在每個ldap裡面會看到4個return code

rcode vaule(priority)
fail 1
reject 1
notfound 1
ok return

priority數值越高,則 優先執行,而return跳出(break) 這個group statement。

將priority設定為1可以避免觸發break機制。

handled則表示已完成所有request。

結論

這樣的方式畢竟是因環境的限制而產生的應用,當其中一個instance(ldap)無法服務,就會拖累下一個instance,讓整個身份驗證變慢,進而觸發access-request timeout,所以需要特別注意。

Reference

  • https://networkradius.com/doc/current/unlang/group.html
  • https://networkradius.com/doc/current/raddb/mods-available/always.html
  • https://networkradius.com/doc/current/unlang/failover_table.html