Monitoring LDAPS with check_ldap and running into the hostname problem (Could not bind to the LDAP server)

Written by - 0 comments

Published on - Listed in Linux Monitoring Icinga Nagios


When monitoring LDAP servers, one very common way is to use the check_ldap plugin from either nagios-plugins or monitoring-plugins projects. This plugin works for both LDAP and encrypted LDAPS.

However when using LDAPS, you might run into connection issue due to the server certificate.

Monitoring LDAPS

Monitoring a LDAPS server is straight forward, especially if you have been using check_ldap in the past for LDAP servers. The additional arguments -T (for using a STARTTLS connection) and -p 636 (for using the LDAPS port) should usually be enough for a change.

ck@icinga:~$ /usr/lib/nagios/plugins/check_ldap -H ldap.example.com -T -p 636 -3 -b "OU=Users,dc=example,dc=com" -D "CN=Service Account Icinga,OU=Service Accounts,OU=Users,DC=example,DC=com" -P "secret"
LDAP OK - 0.025 seconds response time|time=0.024745s;;;0.000000

To take the command apart:

  • -H => The hostname or IP address of the LDAP server
  • -T => Use STARTTLS connection/encryption
  • -p => Use this port (636 is for LDAPS)
  • -3 => Use LDAP protocol v3
  • -b => Use this BASEDN (User)
  • -D => Use this account for LDAP BIND (BINDDN)
  • -P => Password for the LDAP BASEDN (User)

Another possibility is to use the -U parameter to connect to a LDAP server using an URL format:

ck@icinga:~$ /usr/lib/nagios/plugins/check_ldap -U ldaps://ldap.example.com -T -p 636 -3 -b "OU=Users,dc=example,dc=com" -D "CN=Service Account Icinga,OU=Service Accounts,OU=Users,DC=example,DC=com" -P "secret"
LDAP OK - 0.033 seconds response time|time=0.033222s;;;0.000000

Note: The -U parameter is currently only available in check_ldap from the nagios-plugins project.

Both ways (using -H or -U) used a FQDN hostname. Why this is important? We'll see right away...

Issue with IP addresses / no hostname matching

In many Nagios/Icinga monitoring environments, checks are executed against the IP addresses of the servers ($HOSTADDRESS$ in Nagios or $host.address$ in Icinga2).

The Icinga2 ITL documentation for the "ldap" command also mentions that vars.ldap_address defaults to the server's address:

ldap_address     Optional. Host name, IP Address, or unix socket (must be an absolute path). Defaults to “$address$” if the host’s address attribute is set, “$address6$” otherwise.

Using the LDAP servers IP address works fine to check LDAP:

ck@icinga:~$ /usr/lib/nagios/plugins/check_ldap -H 192.168.0.100 -3 -b "OU=Users,dc=example,dc=com" -D "CN=Service Account Icinga,OU=Service Accounts,OU=Users,DC=example,DC=com" -P "secret"
LDAP OK - 0.012 seconds response time|time=0.011560s;;;0.000000

But the check does not work for LDAPS:

ck@icinga:~$ /usr/lib/nagios/plugins/check_ldap -H 192.168.0.100 -T -p636 -3 -b "OU=Users,dc=example,dc=com" -D "CN=Service Account Icinga,OU=Service Accounts,OU=Users,DC=example,DC=com" -P "secret"
Could not bind to the LDAP server

The following systems architecture drawing shows such a situation, where a HAProxy is placed in front of multiple LDAP servers, serving the LDAPS certificate:

check_ldaps on LDAP server IP address fails

The reason behind it is not obvious at all (and the plugin won't tell it either). The LDAP connection fails because the LDAPs certificate was issued for "ldap.example.com" - yet the communication connects to the IP address. The LDAPS certificate therefore does not match the requested hostname.

A similar "problem" happens on HTTPS connection. But check_http solves this nicely with the possibility to combine -I (for the HTTP server's IP address) and -H (for sending a HTTP Host Header).

Unfortunately there is no such (IP address) parameter available in check_ldap.

No solution with the OpenLDAP C library functions

"Let's fix the check_ldap plugin!" That was my first thought and wouldn't have been my first contribution in the nagios-plugins or monitoring-plugins project. However I quickly became to realize, that the OpenLDAP C library (which is used by check_ldap) does not allow a "mix" of LDAP IP and LDAP Hostname:

check_ldap uses ldap_init, ldap_open and ldap_initialize (for the LDAP URL style in the nagios-plugins project). Neither of them support multiple arguments:


OpenLDAP LDAP (libldap, -lldap)

#include <ldap.h>

LDAP *ldap_open(host, port)
char *host;
int port;

LDAP *ldap_init(host, port)
char *host;
int port;

int ldap_initialize(ldp, uri)
LDAP **ldp;
char *uri;

#include <ldap_pvt.h>

int ldap_init_fd(fd, proto, uri, ldp)
ber_socket_t fd;
int proto;
char *uri;
LDAP **ldp;

I was hoping for optional arguments in one of the functions, something in the style of:

LDAP *ldap_init(host, port [, servername])
char *host;
int port;
char *servername;

But, as far as I can tell from my research, there's currently no way around it with these three LDAP connection functions.

As a potential workaround I looked at the ldap_set_option function, which allows to set LDAP options for a LDAP connection. I saw the option LDAP_OPT_HOST_NAME and wanted to test if this could be set for a connection using an IP address:

        /* initialize ldap claudiokuenzler */
        printf ("CK Tests\n");
        if (ldap_set_option (ld, LDAP_OPT_HOST_NAME, &ld_host) != LDAP_OPT_SUCCESS ) {
                printf(_("Could not set host_name %s\n"), ld_host);
                return STATE_CRITICAL;
        }
        else {
                printf(_("host_name %s set\n"), ld_host);
        }
        if (!(ld = ldap_init ("192.168.0.100", ld_port))) {
                printf ("Could not connect to the server %s at port %i\n", ld_host, ld_port);
                return STATE_CRITICAL;
        }

But this would have been too nice for a workaround. Unfortunately this idea sacked:

ck@icinga:~$ ./plugins/check_ldap -H ldap.example.com -p636 -3 -b "OU=Users,dc=example,dc=com" -D "CN=Service Account Icinga,OU=Service Accounts,OU=Users,DC=example,DC=com" -P "secret" -T
CK Tests
host_name ldap.example.com set
ldap_bind: Can't contact LDAP server (-1)
    additional info: (unknown error code)
Could not bind to the LDAP server

With the current library there really seems no way around this. 

Note: If you, dear reader, come up with a solution, let me know or create a pull request in nagios-plugins or monitoring-plugins.

TL;DR: check_ldap LDAPS monitoring must match Hostname

In order to monitor LDAPS servers with check_ldap, you must use the FQDN hostname in either -H or -U, so that the configured LDAPS certificate matches the requested hostname - as mentioned at the beginning of this post.

check_ldaps on LDAP server with matching hostname works


Add a comment

Show form to leave a comment

Comments (newest first)

No comments yet.

RSS feed

Blog Tags:

  AWS   Android   Ansible   Apache   Apple   Atlassian   BSD   Backup   Bash   Bluecoat   CMS   Chef   Cloud   Coding   Consul   Containers   CouchDB   DB   DNS   Database   Databases   Docker   ELK   Elasticsearch   Filebeat   FreeBSD   Galera   Git   GlusterFS   Grafana   Graphics   HAProxy   HTML   Hacks   Hardware   Icinga   Influx   Internet   Java   KVM   Kibana   Kodi   Kubernetes   LVM   LXC   Linux   Logstash   Mac   Macintosh   Mail   MariaDB   Minio   MongoDB   Monitoring   Multimedia   MySQL   NFS   Nagios   Network   Nginx   OSSEC   OTRS   Office   OpenSearch   PGSQL   PHP   Perl   Personal   PostgreSQL   Postgres   PowerDNS   Proxmox   Proxy   Python   Rancher   Rant   Redis   Roundcube   SSL   Samba   Seafile   Security   Shell   SmartOS   Solaris   Surveillance   Systemd   TLS   Tomcat   Ubuntu   Unix   VMWare   VMware   Varnish   Virtualization   Windows   Wireless   Wordpress   Wyse   ZFS   Zoneminder