Estuve peleando un rato con certificados autofirmados (self-signed certificates) para lograr que los clientes se comuniquen con Openldap usando TLS.
Recientemente hice una migración de un Primary Domain Controller, el cual tenía OpenLDAP y algunos clientes configurados sin TLS con ldap://server.domain y otros con SSL con ldaps://server.domain. Habían unos certificados «self-signed» que se presentaban para autenticar a los clientes con SSL todo esto en una versión antigua de openldap.
Sin embargo, OpenLDAP deprecó el uso de ldaps:// (puerto 636) y a partir de su versión 2.0 en el mismo puerto ‘389’ se manejan conexiones con y sin encriptación como lo indica la documentacion oficial, ahora para encriptar la comunicación se usa la configuración StartTLS.
Adicional a estos cambios, la configuración de Openldap ya no se centraliza en el archivo ldap.conf (servidor), sino en preferiblemente en la estructura cn=config que se manipula de una forma particular (un tanto incómoda).
Para utilizar certificados autofirmados y que estos sean accesibles para los clientes debemos:
- Generar los certificados autofirmados (self-signed) como indica el HowTo de OpenLDAP TLS o también este buen tutorial en Digital Ocean
- Agregar los certificados, key y el CA en la configuración de cn=config
- Configurar los clientes (de ser necesario).
- Verificar los permisos de los certificados
- Reiniciar Openldap
Agregar los certificados vía cn=config
Genere un archivo add-certs.ldif con el siguiente contenido:
dn: cn=config changetype: modify add: olcTLSCACertificateFile olcTLSCACertificateFile: /etc/ssl/certs/ca_server.pem - add: olcTLSCertificateFile olcTLSCertificateFile: /etc/ssl/certs/ldap_server.pem - add: olcTLSCertificateKeyFile olcTLSCertificateKeyFile: /etc/ssl/private/ldap_server.key
Y ejecute:
ldapmodify -H ldapi:// -Y EXTERNAL -f addcerts.ldif
Verifique que los paths en el archivo generado concuerdan con la ubicación de sus certificados y que además que el usuario openldap pueda acceder a los mismos (verifique los permisos además de las rutas)
Durante el proceso, obtuve los siguientes errores:
- service nscd restart
- nscd -i groups
- nscd -i passwd
Si no realizan esto, podrían experimentar el error : Could not connect to any LDAP server as (null) – Can’t contact LDAP server
Una vez se haya invalidado la caché de nscd, espere unos minutos y pruebe nuevamente.
additional info: TLS already started
Error
root@servidor: ~ # ldapsearch -ZZ -x -H ldaps://servidor.dominio.example ldap_start_tls: Operations error (1) additional info: TLS already started
Solución
O bien usamos la opción -ZZ y ldap:// o utilizamos ldaps:// sin la opción -ZZ pero no ambas juntas:
root@servidor: ~ # ldapsearch -ZZ -x -H ldap://servidor.dominio.example ldapsearch -x -H ldaps://servidor.dominio.example
Otros errores
- TLS: peer cert untrusted or revoked (0x42)
- ldap_sasl_bind(SIMPLE): Can’t contact LDAP server (-1)
- TLS: can’t connect: (unknown error code)
- connection_read(13): unable to get TLS client DN, error=49 id=5
Estos errores estaban asociados a lo mismo, pueden obtenerse iniciando en modo debug el servidor de openldap:
#Iniciar Openldap en modo debug slapd -h "ldapi:/// ldap:// ldaps://" -u openldap -g openldap -d 65 -F /etc/ldap/slapd.d/ -d 65 #Realizar debug desde clientes con -d1 hasta -d8 ldapsearch -v -H ldaps://servidor.dominio.example/ -D cn=admin,dc=dominio,dc=example -W -x -b dc=dominio,dc=example -d1
Error (utilizando el modo debug d -1)
ldapsearch -ZZ -x -H ldap://servidor.dominio.example -D "cn=admin,dc=dominio,dc=example" -W -d 1 .... ldap_msgfree TLS: peer cert untrusted or revoked (0x42) ...
Solución
El certificado no está bien configurado en el servidor / cliente. Verificar:
- Que el certificado, key y CA están correctamente configurados en cn=config
- Que el certificado está bien configurado en ldap.conf (cliente y servidor)
- Que el certificado es válido-> openssl verify -CApath /etc/ldap/ssl/ servidor.pem
- Que los permisos al path y certificado sean correctos (cliente y servidor)
Mi implementación luce así:
cn=config
ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=config |less dn: cn=config objectClass: olcGlobal cn: config olcArgsFile: /var/run/slapd/slapd.args olcLogLevel: none olcPidFile: /var/run/slapd/slapd.pid olcTLSCACertificateFile: /etc/ldap/ssl/servidorCA.pem olcTLSCertificateFile: "/etc/ldap/ssl/servidor.pem" olcTLSCertificateKeyFile: /etc/ldap/ssl/servidor.key
ldap.conf (servidor)
uri ldap://servidor.dominio.example ldap://servidor1.dominio.example base dc=dominio,dc=example ldap_version 3 sizelimit 0 timeout 10 bind_timeout 10 bind_policy soft deref never loglevel 0 logfile /var/log/ldap.log nss_base_passwd ou=users,dc=dominio,dc=example?sub nss_base_shadow ou=users,dc=dominio,dc=example?sub nss_base_group ou=groups,dc=dominio,dc=example?one pam_login_attribute uid pam_password md5 pam_member_attribute memberuid pam_filter objectClass=posixAccount ssl off tls_reqcert allow tls_cacertfile /etc/ldap/ssl on TLSCACertificateFile /etc/ldap/ssl/servidor.pem #TLSCipherSuite NORMAL TLSCipherSuite +RSA:+AES-256-CBC:+SHA1
ldap.conf (cliente)
uri ldaps://servidor.dominio.example base dc=dominio,dc=example ldap_version 3 timeout 10 bind_timeout 10 bind_policy soft deref never nss_base_passwd dc=dominio,dc=example?sub nss_base_shadow dc=dominio,dc=example?sub nss_base_group dc=dominio,dc=example?one pam_login_attribute uid pam_password md5 pam_member_attribute memberuid pam_filter objectClass=posixAccount ssl on TLS_CACERT /etc/ldap/ssl/servidor.pem #TLS_CACERTDIR /etc/ldap/ssl/ # valida el certificado TLS_REQCERT demand