LDAP redundant with LDAP-Group within users file
Hi, We use radius (freeradius2-2.1.7-7.el5) for user authentication/authorization on network devices. Therefore we use a mapping from huntgroups to ldap groups. We have three ldap server running, and wanted to use "redundant" or "redundant-load-balance". I have tested two cases till now, because i already found messages that point to known problems with ldap redundancy and extends (ldap-groups) within the users file. Case 1 ================ Defining 3 separate ldap server whithin modules/ldap ldap ldap-1 { server = "<IP ldap-1>" .} ldap ldap-2 { server = "<IP ldap-2>" .} ldap ldap-2 { server = "<IP ldap-3>" And using "redundant" for ldap whithin authorize and authenticate: authorize { preprocess files redundant { ldap-1 ldap-2 ldap-3 handled } pap } authenticate { Auth-Type PAP { pap } Auth-Type ldap-1 { ldap-1 } Auth-Type ldap-2 { ldap-2 } Auth-Type ldap-3 { ldap-3 } Auth-Type LDAP { redundant { ldap-1 ldap-2 ldap-3 handled } } } Problem: radius is using always the same ldap server for group extends. If this (one!) server fails, radius authentication is not possible. Very bad, because we have "redundancy" configured, and expected to have zero outage. Case 2 ================ Defining all three server whithin one section in modules/ldap ldap { server = "<IP ldap-1> <IP ldap-2> <IP ldap-3>" .} And setting just "ldap" within authorize and authenticate: authorize { preprocess files ldap pap } authenticate { Auth-Type PAP { pap } Auth-Type LDAP { ldap } } With this config an other ldap server is choosen, if the one that has handelt the communication for ldap group extends fails. But failover took 15 minutes. Thats much too long for us. (1-3 minutes at most will be acceptable, "zero outage" gorgeous/expected) I found mails regarding similar problems within the archive, but no suitable solution. (e.g http://www.mail-archive.com/freeradius-users@lists.freeradius.org/msg23408.h... from 2006) Is there a solution for reducing the outage and having loadbalancing for our case? I hope that i explained my problem in an understandingly (native language is german), and didn´t paste too much configs. Jan Just a gap of our users file, we have 18 default lines and additional 4 for a local/PAP user: DEFAULT Auth-Type := LDAP, Huntgroup-Name == consoleserver, LDAP-Group == "<LDAP-GROUP-Team-a>" Login-Service = Telnet DEFAULT Auth-Type := LDAP, Huntgroup-Name == consoleserver, LDAP-Group == "<LDAP-GROUP-Team-b>" Login-Service = Telnet DEFAULT Auth-Type := LDAP, Huntgroup-Name == consoleserver, LDAP-Group == "<LDAP-GROUP-Team-c>" Login-Service = Telnet DEFAULT Auth-Type := LDAP, Huntgroup-Name == "nexus", LDAP-Group == "<LDAP-GROUP-Team-a>" Login-Service = Telnet, Vendor-Specific = 9, Cisco-AVPair = "shell:roles*\"network-admin\" \"vdc-admin\"" DEFAULT Auth-Type := LDAP, Huntgroup-Name == "brocade", LDAP-Group == "<LDAP-GROUP-Team-a>" Vendor-Specific = 1991, Foundry-Privilege-Level = 0, foundry-command-string="*", foundry-command-exception-flag=0 DEFAULT Auth-Type := LDAP, LDAP-Group == "<LDAP-GROUP-Team-a>" Service-Type = Administrative-User, Login-Service = Telnet, Vendor-Specific = 9, cisco-avpair = "shell:priv-lvl=15"
On 28/06/11 16:12, Jan.Gnepper@t-systems.com wrote:
Problem: radius is using always the same ldap server for group extends. If this (one!) server fails, radius authentication is not possible. Very bad, because we have "redundancy" configured, and expected to have zero outage.
Sorry. The "ldap" module and FreeRADIUS do not work that way. "LDAP-Group" is a virtual attribute, that is registered by the first LDAP module to be created; it can't "fail over". It doesn't know about "redundant {}" or similar.
Defining all three server whithin one section in modules/ldap
ldap { server = "<IP ldap-1> <IP ldap-2> <IP ldap-3>" .}
And setting just "ldap" within authorize and authenticate:
With this config an other ldap server is choosen, if the one that has handelt the communication for ldap group extends fails. But failover took 15 minutes. Thats much too long for us. (1-3 minutes at most will be acceptable, "zero outage" gorgeous/expected)
It should not take 15 minutes. What is your "net_timeout" set to? Unfortunately, when you supply >1 LDAP server, this is handled internally by libldap, and libldap tries the LDAP servers in series, not in parallel. So there will always be some outage. FreeRADIUS does not currently have connection pools, and they're a bit hard with LDAP because libldap doesn't have a great API.
I found mails regarding similar problems within the archive, but no suitable solution. (e.g http://www.mail-archive.com/freeradius-users@lists.freeradius.org/msg23408.h... from 2006)
Is there a solution for reducing the outage and having loadbalancing for our case?
At the moment, the "ldap" module does not have the kind of instant failover you're looking for. You will need some kind of IP loadbalancing solution in front of your LDAP servers to achieve this.
Phil Mayers <p.mayers@imperial.ac.uk> wrote:
Unfortunately, when you supply >1 LDAP server, this is handled internally by libldap, and libldap tries the LDAP servers in series, not in parallel. So there will always be some outage.
FreeRADIUS does not currently have connection pools, and they're a bit hard with LDAP because libldap doesn't have a great API.
The API is good enough. I keep meaning to do this for the sql module (well, postgresql) but it can be done for libldap too. Open the socket directly in freeradius, using SOCK_NONBLOCK -> connect() -> SO_RCVTIMEO/SO_SNDTIMEO and then pass that all to ldap_init_fd(). connect() can now catch timeouts with select() and it means we also catch networking errors rather than just server/client errors. I await Alan's "show me the money^Wpatch"...well maybe I'll find some time next week. Cannot have Imperial stealing the whole show :) Cheers -- Alexander Clouter .sigmonster says: You will have many recoverable tape errors.
On 06/28/2011 08:15 PM, Alexander Clouter wrote:
I keep meaning to do this for the sql module (well, postgresql) but it can be done for libldap too. Open the socket directly in freeradius, using SOCK_NONBLOCK -> connect() -> SO_RCVTIMEO/SO_SNDTIMEO and then pass that all to ldap_init_fd(). connect() can now catch timeouts with select() and it means we also catch networking errors rather than just server/client errors.
ldap_init_fd seems to be a relatively new API. It's absent for example in the OpenLDAP 2.3.27 libs that come with RHEL5. So it's not surprising there's nothing like this in the code. It's also damn tedious because you get into all the "joys" of parsing the LDAP url, calling getaddrinfo() to resolve it properly, looping over the results, deciding whether to fork off connections in "happy eyeballs" mode 300 milliseconds apart etc. etc. It's a mystery to me why there isn't an "ldap_open_s" and an "ldap_open", the latter doing what you suggest. Anyway, certainly it's doable. But as per my discussion in other fora, it's relatively useless if you do this "inline" with the radius request. The whole point is to pull up a working connection, and until you've got one, fast-fail the module so "redundant {}" can do it's work. That means a worker thread.
participants (3)
-
Alexander Clouter -
Jan.Gnepper@t-systems.com -
Phil Mayers