LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Server
User Name
Password
Linux - Server This forum is for the discussion of Linux Software used in a server related context.

Notices


Reply
  Search this Thread
Old 11-07-2019, 10:31 AM   #1
lqoreader
LQ Newbie
 
Registered: Sep 2019
Posts: 16

Rep: Reputation: Disabled
HAProxy or OpenLDAP frontend for OpenLDAP failover cluster


Hi OpenLDAP Pros!

Trying to implement an OpenLDAP cluster, I already managed to set up the two backend LDAP servers in mirroring mode.

The application (iRedMail) using the LDAP service is running on the same systems as the LDAP servers. This applications needs the LDAP configuration in the former slapd.conf manner and not in the CONFIG-DB way. So I added the mirroring parameters to the slapd.conf file. The file looks like this on the first backend node:

Code:
include     /etc/openldap/schema/core.schema
include     /etc/openldap/schema/corba.schema
include     /etc/openldap/schema/cosine.schema
include     /etc/openldap/schema/inetorgperson.schema
include     /etc/openldap/schema/nis.schema
include     /etc/openldap/schema/calentry.schema
include     /etc/openldap/schema/calresource.schema
include     /etc/openldap/schema/amavisd-new.schema
include     /etc/openldap/schema/iredmail.schema

pidfile     /var/run/openldap/slapd.pid
argsfile    /var/run/openldap/slapd.args

# The syncprov overlay
moduleload syncprov.la

disallow    bind_anon
require     LDAPv3
loglevel    0

access to attrs="userPassword,mailForwardingAddress,employeeNumber"
    by anonymous    auth
    by self         write
    by dn.exact="cn=vmail,dc=myCompany,dc=de"   read
    by dn.exact="cn=vmailadmin,dc=myCompany,dc=de"  write
    by users        none

access to attrs="cn,sn,gn,givenName,telephoneNumber"
    by anonymous    auth
    by self         write
    by dn.exact="cn=vmail,dc=myCompany,dc=de"   read
    by dn.exact="cn=vmailadmin,dc=myCompany,dc=de"  write
    by users        read

access to attrs="objectclass,domainName,mtaTransport,enabledService,domainSenderBccAddress,domainRecipientBccAddress,domainBackupMX,domainMaxQuotaSize,domainMaxUserNumber,domainPendingAliasName"
    by anonymous    auth
    by self         read
    by dn.exact="cn=vmail,dc=myCompany,dc=de"   read
    by dn.exact="cn=vmailadmin,dc=myCompany,dc=de"  write
    by users        read

access to attrs="domainAdmin,domainGlobalAdmin,domainSenderBccAddress,domainRecipientBccAddress"
    by anonymous    auth
    by self         read
    by dn.exact="cn=vmail,dc=myCompany,dc=de"   read
    by dn.exact="cn=vmailadmin,dc=myCompany,dc=de"  write
    by users        none

access to attrs="mail,accountStatus,domainStatus,userSenderBccAddress,userRecipientBccAddress,mailQuota,backupMailAddress,shadowAddress,memberOfGroup,member,uniqueMember,storageBaseDirectory,homeDirectory,mailMessageStore,mailingListID"
    by anonymous    auth
    by self         read
    by dn.exact="cn=vmail,dc=myCompany,dc=de"   read
    by dn.exact="cn=vmailadmin,dc=myCompany,dc=de"  write
    by users        read

access to dn="cn=vmail,dc=myCompany,dc=de"
    by anonymous                    auth
    by self                         write
    by users                        none

access to dn="cn=vmailadmin,dc=myCompany,dc=de"
    by anonymous                    auth
    by self                         write
    by users                        none

access to dn.regex="domainName=([^,]+),o=domains,dc=myCompany,dc=de$"
    by anonymous                    auth
    by self                         write
    by dn.exact="cn=vmail,dc=myCompany,dc=de"   read
    by dn.exact="cn=vmailadmin,dc=myCompany,dc=de"  write
    by dn.regex="mail=[^,]+@$1,o=domainAdmins,dc=myCompany,dc=de$" write
    by dn.regex="mail=[^,]+@$1,ou=Users,domainName=$1,o=domains,dc=myCompany,dc=de$" read
    by users                        none

access to dn.subtree="o=domains,dc=myCompany,dc=de"
    by anonymous                    auth
    by self                         write
    by dn.exact="cn=vmail,dc=myCompany,dc=de"    read
    by dn.exact="cn=vmailadmin,dc=myCompany,dc=de"  write
    by users                        read

access to dn.subtree="o=domainAdmins,dc=myCompany,dc=de"
    by anonymous                    auth
    by self                         write
    by dn.exact="cn=vmail,dc=myCompany,dc=de"    read
    by dn.exact="cn=vmailadmin,dc=myCompany,dc=de"  write
    by users                        none

access to dn.regex="cn=[^,]+,dc=myCompany,dc=de"
    by anonymous                    auth
    by self                         write
    by users                        none

access to *
    by anonymous                    auth
    by self                         write
    by users                        read

database monitor
access to dn="cn=monitor"
    by dn.exact="cn=Manager,dc=myCompany,dc=de" read
    by dn.exact="cn=vmail,dc=myCompany,dc=de" read
    by * none

database    mdb
suffix      dc=myCompany,dc=de
directory   /var/lib/ldap/myCompany.de
rootdn      cn=Manager,dc=myCompany,dc=de
rootpw      {SSHA}V5/UQXm9SmzRGjKK2zAKB79eFSaysc2wG9tPIg==
sizelimit   unlimited
maxsize     2147483648
checkpoint  128 3
mode        0700

index objectclass,entryCSN,entryUUID                eq
index uidNumber,gidNumber,uid,memberUid,loginShell  eq,pres
index homeDirectory,mailMessageStore                eq,pres
index ou,cn,mail,surname,givenname,telephoneNumber,displayName  eq,pres,sub
index nisMapName,nisMapEntry                        eq,pres,sub
index shadowLastChange                              eq,pres
index member,uniqueMember eq,pres

index domainName,mtaTransport,accountStatus,enabledService,disabledService  eq,pres,sub
index domainAliasName    eq,pres,sub
index domainMaxUserNumber eq,pres
index domainAdmin,domainGlobalAdmin,domainBackupMX    eq,pres,sub
index domainSenderBccAddress,domainRecipientBccAddress  eq,pres,sub

index accessPolicy,hasMember,listAllowedUser,mailingListID   eq,pres,sub

index mailForwardingAddress,shadowAddress   eq,pres,sub
index backupMailAddress,memberOfGroup   eq,pres,sub
index userRecipientBccAddress,userSenderBccAddress  eq,pres,sub
index mobile,departmentNumber eq,pres,sub

#Mirror Mode
serverID    001

# Consumer
syncrepl rid=001 \
provider=ldap://rm2.myCompany.de \
bindmethod=simple \
binddn="cn=vmail,dc=myCompany,dc=de" \
credentials="gtV9FwILIcp8Zw8YtGeB1AC9GbGfti" \
searchbase="dc=myCompany,dc=de" \
attrs="*,+" \
type=refreshAndPersist \
interval=00:00:01:00 \
retry="60 +"
# Provider
overlay syncprov
syncprov-checkpoint 50 1
syncprov-sessionlog 50

mirrormode on
There are only two differences in the second node's config file:

Code:
[...]
#Mirror Mode
serverID    002
[...]

# Consumer
[...]
provider=ldap://rm2.myCompany.de \
[...]
As mentioned before the mirroring works perfectly.

Now I need a single connection address for the LDAP clients, i.e. web applications using LDAP as authentication mechanism.

I read that you can use an OpenLDAP proxy for that purpose. The LDAP client (here: web application) connects to the LDAP proxy and the proxy will retrieve the authentication data from multiple backend LDAP servers.

I set up an OpenLDAP proxy, it uses CONFIG-DB, not the ancient way. The slapd.conf file looks like this:

Code:
include         /etc/openldap/schema/corba.schema
include         /etc/openldap/schema/core.schema
include         /etc/openldap/schema/cosine.schema
include         /etc/openldap/schema/duaconf.schema
include         /etc/openldap/schema/dyngroup.schema
include         /etc/openldap/schema/inetorgperson.schema
include         /etc/openldap/schema/java.schema
include         /etc/openldap/schema/misc.schema
include         /etc/openldap/schema/nis.schema
include         /etc/openldap/schema/openldap.schema
include         /etc/openldap/schema/ppolicy.schema
 
pidfile         /var/run/openldap/slapd.pid
argsfile        /var/run/openldap/slapd.args

modulepath  /usr/lib/openldap
modulepath  /usr/lib64/openldap
moduleload  back_ldap.la       
loglevel	0

database		ldap
readonly		yes            
protocol-version	3
rebind-as-user
uri			"ldap://rm1.myCompany.de:389"
suffix		        "dc=myCompany,dc=de"
uri                     "ldap://rm2.myCompany.de:389"
suffix		        "dc=myCompany,dc=de"
First issue:

Creating the CONFIG-DB using slaptest, the command fails, claiming:

Code:
5dc44107 /etc/openldap/slapd.conf: line 48: suffix already served by this backend!.
slaptest: bad configuration directory!
The slaptest command looks like this:

Code:
slaptest -f /etc/openldap/slapd.conf -F /etc/openldap/slapd.d/
It is possible that I didn't understand completely the concept, because all guides I found are using subdomain prefixes for the different LDAP backend servers, i.e. instead of:

Code:
uri			"ldap://rm1.myCompany.de:389"
suffix		        "dc=myCompany,dc=de"
uri                     "ldap://rm2.myCompany.de:389"
suffix		        "dc=myCompany,dc=de"
they use:

Code:
uri			"ldap://rm1.myCompany.de:389"
suffix		        "dc=ou1,dc=myCompany,dc=de"
uri                     "ldap://rm2.myCompany.de:389"
suffix		        "dc=ou2,dc=myCompany,dc=de"
What I didn't understand: On the backend servers there is no ou1 and ou2 respectively. How can they expect to find anything in the backend LDAPs if the DNs do not match?

I temporarily commented the second uri in order to check if, apart from this issue, LDAP queries to the LDAP proxy succeed, but ran into the second issue.


Second issue:

If I run an ldapsearch against directly to the two backend LDAP servers (one after the other), all of the LDAP users will be enumerated.

If I run the same ldapsearch against the LDAP proxy, only the user "vmail" will be enumerated. I think that the same users should be listed as in the direct query.

This is the ldapsearch command:

Code:
ldapsearch -D "cn=vmail,dc=myCompany,dc=de" -w gtV9FwILIcp8Zw8YtGeB1AC9GbGfti -p 389 -h 192.168.0.92 -b "dc=myCompany,dc=de" -s sub "(objectclass=person)"
Did I miss sth.?


Thank you for your considerations!

Best regards,
Florian

Last edited by lqoreader; 11-18-2019 at 09:23 AM. Reason: changed serverID 001 to 002
 
Old 11-08-2019, 08:11 AM   #2
tyler2016
Member
 
Registered: Sep 2018
Distribution: Debian, CentOS, FreeBSD
Posts: 243

Rep: Reputation: Disabled
Whenever I have bad ldap clients that can't define multiple servers, I use a local haproxy instance in TCP mode. Here is an example:

Code:
frontend ldap 127.0.1.1:389
    mode tcp
    option tcplog
    default_backend  ldap_backend

backend ldap_backend
    mode tcp
    option ldap-check
    balance  roundrobin
    server server1 10.0.0.1:389 check
    server server2 10.0.0.2:389 check
 
Old 11-08-2019, 08:49 AM   #3
lqoreader
LQ Newbie
 
Registered: Sep 2019
Posts: 16

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by tyler2016 View Post

Code:
frontend ldap 127.0.1.1:389
Hi @tyler

slaptest claims that it does not know the directive "frontend"

Code:
5dc57fa9 /etc/openldap/slapd.conf: line 53: unknown directive <frontend> outside backend info and database definitions.
slaptest: bad configuration directory!
The example you provided has to be added to the slapd.conf file or not?
 
Old 11-08-2019, 09:00 AM   #4
tyler2016
Member
 
Registered: Sep 2018
Distribution: Debian, CentOS, FreeBSD
Posts: 243

Rep: Reputation: Disabled
No. Completely different service. Install HAProxy on the host(s) with the bad ldap client, configure the frontend/backend per my example, and set the URI on the client to ldap://127.0.1.1:389/WHATEVER_YOU_NEED_TO_ADD. haproxy is in the repositories for most distros. The config file is usually /etc/haproxy/haproxy.conf or /etc/haproxy/haproxy.cfg or something similar. I use HAProxy all the time to handle things like this, bad TLS implementations, etc.
 
Old 11-08-2019, 09:05 AM   #5
lqoreader
LQ Newbie
 
Registered: Sep 2019
Posts: 16

Original Poster
Rep: Reputation: Disabled
Okay. We run a bunch of servers and web applications with LDAP authentication. I will keep your HAProxy model in mind if there is no way to make the central access point work.

My idea is, that all of the servers and web applications are configured to access the LDAP proxy's IP or FQDN for authentication.

Thank you very much!
 
Old 11-11-2019, 05:46 AM   #6
lqoreader
LQ Newbie
 
Registered: Sep 2019
Posts: 16

Original Poster
Rep: Reputation: Disabled
Tried the configuration which I had mentioned above including the ou1/ou2 in the suffix' DN:

Code:
uri		"ldap://rm1.myCompany.de:389"
suffix		        "dc=ou1,dc=myCompany,dc=de"
uri                     "ldap://rm2.myCompany.de:389"
suffix		        "dc=ou2,dc=myCompany,dc=de"
Result: ldapsearch query is not possible, error message is:

Code:
ldap_bind: Invalid credentials (49)
 
Old 11-18-2019, 10:07 AM   #7
lqoreader
LQ Newbie
 
Registered: Sep 2019
Posts: 16

Original Poster
Rep: Reputation: Disabled
Giving up on LDAP frontend configuration as I read that the HAProxy application - mentioned by @tyler2016 - can also be used on a single server working as the central access point for LDAP clients:

Several LDAP clients on different servers -> asking HAProxy for LDAP authentication -> distributing requests to the backend LDAP servers.

I don't need LDAPS, unencrypted LDAP is okay.

This is the haproxy.cfg on my HAProxy server:

Code:
global
        log 127.0.0.1   local0
        log 127.0.0.1   local1 debug
        maxconn   45000 # Total Max Connections.
        daemon
        nbproc      1 # Number of processing cores.

defaults
        timeout server 86400000
        timeout connect 86400000
        timeout client 86400000
        timeout queue   1000s

# Reporting
listen stats
    bind :9000
    mode http

    # Enable statistics
    stats enable

    # Hide HAPRoxy version, a necessity for any public-facing site
    stats hide-version

    # Show text in authentication popup
    stats realm Authorization

    # URI of the stats page: localhost:9000/haproxy_stats
    stats uri /haproxy_stats

    # Set a username and password
    stats auth hapxy:g5thw3wq5455tgftgfr4

frontend ldap
        mode            tcp
        log             global
        bind            192.168.0.92:389
        option          tcplog
        option          logasap
        option          socket-stats
        option          tcpka
        timeout client  5s
        default_backend ldapcluster

backend ldapcluster
        mode            tcp
        option          ldap-check
        balance         roundrobin
        server rm1      192.168.0.109:389 check
        server rm2      192.168.0.111:389 check
Issue: If I run an ldapsearch on a system with LDAP client against the HAProxy system, I get the following error:

Code:
[root@ldapclient ~]# ldapsearch -D "cn=vmail,dc=myCompany,dc=de" -w gtV9FwILIcp8Zw8YtGeB1AC9GbGfti -p 389 -h 192.168.0.92 -b "dc=myCompany,dc=de" -s sub "(objectclass=person)"
ldap_result: Can't contact LDAP server (-1)
Observation1: If I run the same ldapsearch query directly against one of the LDAP backend servers, I get all LDAP users enumerated.

Observation2: The HAProxy service is running on the HAProxy system ('systemctl status haproxy' returns 'active (running)')

Observation3: Netstat indicates that haproxy is listening on port 389 TCP on the HAProxy system (192.168.0.92:389 just like configured in haproxy.cfg)

Observation4: Performing telnet HAProxy 389 from the LDAP client system, the connection will be opened and immediately closed by the foreign host (=HAProxy)

Observation5: Performing telnet 389 directly against one of the LDAP backend nodes, the connection is opened and kept open.

Observation6: Trying to authenticate a properly configured user and LDAP authentication module from an web application against the HAProxy system: Failing returning "no bind result"

Observation7: Same web application, reconfigured to authenticate directly against backend LDAP node: Login will succeed.


Any idea what could be the cause for the error message
Code:
ldap_result: Can't contact LDAP server (-1)
on the HAProxy sytem?
 
Old 11-18-2019, 03:26 PM   #8
tyler2016
Member
 
Registered: Sep 2018
Distribution: Debian, CentOS, FreeBSD
Posts: 243

Rep: Reputation: Disabled
Firewall? TCP Wrappers? SELinux? I just tested your HAProxy config on my system and it works fine.
 
Old 11-18-2019, 04:23 PM   #9
lqoreader
LQ Newbie
 
Registered: Sep 2019
Posts: 16

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by tyler2016 View Post
Firewall? TCP Wrappers? SELinux? I just tested your HAProxy config on my system and it works fine.
Firewall: port 389 TCP open. 'telnet 192.168.0.92 389' (192.168.0.92 is the HAProxy system): Connection establishes but will be closed immediately.

TCP Wrappers: Installed but not configured (host.allow & hosts.deny are empty)

SELinux: disabled in the config file. getenforce returns 'Disabled'.
 
Old 11-18-2019, 05:00 PM   #10
tyler2016
Member
 
Registered: Sep 2018
Distribution: Debian, CentOS, FreeBSD
Posts: 243

Rep: Reputation: Disabled
What about the firewall of the system you are connecting from? I run outbound firewalls on all of my systems. Are the IP addresses in the back end correct?
 
Old 11-19-2019, 02:09 AM   #11
lqoreader
LQ Newbie
 
Registered: Sep 2019
Posts: 16

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by tyler2016 View Post
What about the firewall of the system you are connecting from? I run outbound firewalls on all of my systems. Are the IP addresses in the back end correct?
With firewalld disabled on the connecting system with LDAP client the result is the same.

I don't think that the issue is to be found on the connecting system. Tried a CentOs, a Debian 8 and some web applications using LDAP authentication. All of them fail, trying to authenticate via HAProxy and all of them succeed authenticating directly against the LDAP backend.

The issue must be with the HAProxy.

Is there a log on the HAProxy I could check?

Supplement:

Enabled rsyslog for HAProxy, but the only entry whenever I execute the ldapsearch query is the following (192.168.0.108 is the querying system):

Code:
Nov 19 10:58:10 localhost haproxy[1296]: 192.168.0.108:58016 [19/Nov/2019:10:58:10.148] ldap ldapcluster/<NOSRV> -1/-1/+0 +0 SC 0/0/0/0/0 0/0

Last edited by lqoreader; 11-19-2019 at 04:00 AM.
 
Old 11-19-2019, 08:17 AM   #12
tyler2016
Member
 
Registered: Sep 2018
Distribution: Debian, CentOS, FreeBSD
Posts: 243

Rep: Reputation: Disabled
Try commenting out each of the two LDAP servers. That will eliminate anything weird with the load balancing.
 
Old 11-20-2019, 06:13 AM   #13
lqoreader
LQ Newbie
 
Registered: Sep 2019
Posts: 16

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by tyler2016 View Post
Try commenting out each of the two LDAP servers. That will eliminate anything weird with the load balancing.
Commented out both of the servers (one after the other) and conducted ldapsearch queries. I performed further queries with the option "balance roundrobin" disabled.
Result of all trials:
Code:
ldap_result: Can't contact LDAP server (-1)
 
Old 11-20-2019, 09:22 AM   #14
tyler2016
Member
 
Registered: Sep 2018
Distribution: Debian, CentOS, FreeBSD
Posts: 243

Rep: Reputation: Disabled
At this point, I would leave one server commented out in your proxy config and run a packet sniffer on the remaining LDAP server and see if the traffic is coming in at all. This seems to be a network issue. Can you ping and SSH between the proxy and LDAP hosts? I know you said firewalld was off, but have you run iptables -L -n and verified that there is no netfilter configuration?
 
Old 11-21-2019, 04:14 AM   #15
lqoreader
LQ Newbie
 
Registered: Sep 2019
Posts: 16

Original Poster
Rep: Reputation: Disabled
Ran tcpdump on the remaining LDAP backend server:

The ldapsearch query from the LDAP client system via the HAProxy system does not come in (not one single output by tcpdump).

Running the ldapsearch query from the LDAP client system directly against the LDAP backend server, a lot of output is generated on the tcpdump sniffer.

Installed openldap-clients on the HAProxy system and ran the same ldapsearch query against the LDAP backend server: All LDAP users returned and a lot of tcpdump output.

Quote:
Can you ping and SSH between the proxy and LDAP hosts?
Yes, absolutely no problem. PING and SSH work fine.


Quote:
have you run iptables -L -n and verified that there is no netfilter configuration?
Output for 'iptables -L -n' on the HAProxy system (same output on the LDAP backend system):

Code:
[root@HAProxy ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
I can't help, but I have the impression that the setup of the HAProxy is incomplete.

May be I messed sth. up using different HAProxy tutorials?

If I start from scratch, can you recommend one single tutorial covering the implementation of an HAProxy to work as LDAP frontend?
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Centos 6.4 with OpenLDAP+TLS: OpenLDAP ok, add TLS =>not ok chrism01 Linux - Server 2 10-27-2013 03:15 PM
nss_ldap, openldap and openldap-server ... what is openldap for? chakkerz Linux - Server 2 08-13-2009 07:16 PM
LXer: OpenLDAP Quick Tips: OpenLDAP Logfile analysis LXer Syndicated Linux News 0 12-01-2008 04:00 PM
LXer: OpenLDAP Quick Tips: Regularly upgrade OpenLDAP! LXer Syndicated Linux News 0 11-25-2008 02:00 PM
LXer: OpenLDAP Quick Tips: Using syslog or syslog-ng with slapd for OpenLDAP logging LXer Syndicated Linux News 0 11-14-2008 08:41 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Server

All times are GMT -5. The time now is 10:17 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration