HAProxy LDAP Backend

By | 2020-05-31

There are a few good reasons for setting up an HAProxy LDAP backend. Perhaps the client’s TLS implementation is lacking. Maybe the application only supports a single server and you can’t afford down time. In the latter scenario, setting up multiple address records in DNS with the same domain name. The problem with that is if one server goes done, DNS might not be aware of it and still return the address of a down server, causing a failure or error.

Setting this up is pretty straight forward. In the example configuration, I have two OpenLDAP servers setup as a multi-master cluster. When I do this, I usually have HAProxy running on the same host as the application that will be connecting to it.

Configuration

Below is an example HAProxy configuration file:

global
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    stats socket /var/lib/haproxy/stats

    ssl-default-bind-ciphers PROFILE=SYSTEM
    ssl-default-server-ciphers PROFILE=SYSTEM

defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

frontend ldap_front
    bind 127.0.0.1:389
    mode tcp
    option tcplog
    default_backend             ldap_back

backend ldap_back
    mode tcp
    balance roundrobin
    option ldap-check
    server ldap1 192.168.0.1:636 ssl ca-file /pki/cacerts.pem check
    server ldap2 192.168.0.2:636 ssl ca-file /pki/cacerts.pem check

I started with the configuration file that the HAProxy package in the CentOS 8 provides and removed everything except the global and defaults sections. Then I added the front ends and back ends. If you don’t need TLS, omit ssl ca-file /pki/cacerts.pem and change the port from 636 to 389.

For those that are using TLS make sure to replace /pki/cacerts.pem with the path to a file containing the CA certificates that signed your server certs. If you are using self-signed certificates, add the certificates themselves to the file you specify.

The ldap-check configures HAProxy to try an anonymous bind to the servers as its health check. This is a more reliable check that simply attempting to connect to the port, or if you are using TLS, completing the handshake.

Verification

Below I create a shell alias to ldapsearch so I can test the configuration. I am creating the alias on the same host that I have HAProxy running on. The directory servers were installed from source and populated using my own guides.

$ alias ldaptest='ldapsearch -LLL -H ldap://localhost -x -D "cn=admin,dc=tylersguides,dc=com" -b "dc=tylersguides,dc=com" -w a "(uid=testuser)" uid'

I really do use a as for my passwords when I build my VMs for writing these guides. Typing passwords gets old. Don’t use a as a password on a real system.

Now I run my first test:

$ ldaptest
dn: uid=testuser,ou=users,dc=tylersguides,dc=com
uid: testuser

Great. It worked. Now I turn off each server one at a time to ensure HAProxy correctly detects the outage and directs traffic to the surviving server.

# hostname
ldap2.tylersguides.com
# systemctl stop slapd-current
$ hostname
haproxy.tylersguides.com
$ ldaptest
dn: uid=testuser,ou=users,dc=tylersguides,dc=com
uid: testuser
# hostname
ldap2.tylersguides.com
# systemctl start slapd-current

Now for the other server:

# hostname
ldap1.tylersguides.com
# systemctl stop slapd-current
$ hostname
haproxy.tylersguides.com
$ ldaptest
dn: uid=testuser,ou=users,dc=tylersguides,dc=com
uid: testuser
# hostname
ldap1.tylersguides.com
# systemctl start slapd-current

Going Forward

There are a few things you might want to do before going live. You may wish to consider enforcing the use of a specific TLS version or cipher suite. I recommend updating the logging setting.

The default logging configuration bundled with CentOS 8 is log 127.0.0.1 local2. I used CentOS 8 on my test machines. By default, rsyslog on CentOS 8 has its UDP listener turned off. I recommend ensuring your syslog implamentations’s UDP listener can at least accept local traffic. Since HAProxy, typically runs in a chroot environment, it can’t access the UNIX socket that many applications use. I.e. HAProxy requires logging to the syslog over UDP. I would also consider changing the facility from local2 to daemon. This will ensure that the HAProxy logs won’t be ignored by your logging daemon.

Summary

As you can see, setting up an HAProxy LDAP backend is pretty straight forward. Make sure to update and test your logging configuration. If you don’t see any messages in your logs from when you test your connection, there is something wrong. Remember that HAProxy usually needs to connect to a logging daemon over the standard UDP port 514. If you are using TLS, make sure your CA certificate file has the CA certificate(s) for your LDAP servers.

References