OpenLDAP 系列5 --- 安全
一、概要
1. 承上启下
2. TLS与ldaps
LDAP同时支持TLS和ldaps两种通信方式来确保通信安全,但两者各有特点且无法同时使用:
(1) TLS
TLS又称StartTLS,它使用传统的ldap协议和389端口建立链接,该链接是明文的。这种方式要求客户端将自己的证书放在服务端,链接建立时客户端向服务端发送自己的证书,服务端进行校验。如果校验失败,链接可能(根据配置)退回到普通链接的状态。
(2) ldaps
ldaps是secure ldap协议的简称,它使用独立的636端口进行链接,但是该协议有一个致命的缺点,由于缺乏CA,客户端无法校验服务端的真实性,这就有可能导致中间人攻击问题。
设想一下,你使用某公共场所的Wifi连接LDAP1,该Wifi将请求转发至虚假的中间人LDAP2,由于你无法确认证书是属于LDAP2还是LDAP1,你信任了该证书并将敏感信息通过LDAP2传输至LDAP1,如此LDAP2就得到了你的敏感信息。
综上,推荐使用TLS而不是ldaps。
3. 准备工作
(1) 创建证书
(2) 将CA证书、OpenLDAP证书和OpenLDAP密钥复制到OpenLDAP目录中:
sudo cp -v certs/openldap.crt private/openldap.key /etc/openldap/certs/
sudo mkdir -p /etc/openldap/cacerts sudo cp -v ca.cert.pem /etc/openldap/cacerts
(3) 修改证书目录所有者:
sudo chown -R ldap:ldap /etc/openldap/certs
sudo chown -R ldap:ldap /etc/openldap/cacerts
二、TLS
1. 配置"cn=config"
我们需要修改"cn=config"内的两个属性olcTLSCertificateFile和olcTLSCertificateKeyFile的值,并添加olcTLSCACertificateFile属性。
(1) 查询olcTLSCertificateFile和olcTLSCertificateKeyFile的现值:
sudo slapcat -b "cn=config" | egrep "olcTLSCACertificateFile|olcTLSCertificateFile|olcTLSCertificateKeyFile"
(2) 创建tls.ldif
vi tls.ldif
(3) 初始化
dn: cn=config changetype: modify replace: olcTLSCACertificateFile olcTLSCACertificateFile: /etc/pki/CA/cacert.pem - replace: olcTLSCertificateKeyFile olcTLSCertificateKeyFile: /etc/pki/tls/private/key.pem - replace: olcTLSCertificateFile olcTLSCertificateFile: /etc/pki/tls/certs/ldap.example.com.cert.pem
(4) 执行修改
sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f tls.ldif
(5) 检验新值
sudo slapcat -b "cn=config" | egrep "olcTLSCACertificateFile|olcTLSCertificateFile|olcTLSCertificateKeyFile"
2. 配置slapd
(1) 打开slapd文件
sudo vi /etc/sysconfig/slapd
(2) 添加ldaps到SLAPD_URLS
SLAPD_URLS="ldapi:/// ldap:/// ldaps:///"
3. 配置ldap.conf
(1) 打开ldap.conf文件
sudo vi /etc/openldap/ldap.conf
(2) 更新
TLS_CACERT /etc/openldap/certs/cacert.pem TLS_REQCERT allow
因为我们使用的是自签名的证书而非权威CA证书,我们需要设置TLS_CACERT为ca证书路径,否则在对LDAP Client进行认证的时候将会收到“TLS negotiation failure”的报错。
如果将TLS_REQCERT 设置为never,则不对证书进行校验,此时配置TLS就没有意义了。
4. 防火墙
sudo firewall-cmd --permanent --zone=public --add-service={ldaps,ldap}
sudo firewall-cmd --reload
5. 重启服务
sudo systemctl restart slapd
6. 测试
(1) 使用ldapsearch命令建立一个TLS链接:
ldapsearch -x -ZZ
或
ldapsearch -x -b dc=example,dc=com -ZZ
如果报错,则可以打印一下详细日志:
ldapsearch -x -ZZ -d 5
(2) 查看监听
636是ldaps使用的端口,389是ldap使用的端口。
(3) 使用root密码来进行测试:
a. ldaps
ldapsearch -x -H ldaps://127.0.0.1 -b "dc=example,dc=com" -D "cn=admin,dc=example,dc=com" -w <密码>
该命令将会使用636端口连接LDAP服务器。
b. TLS
ldapsearch -x -ZZ -H ldap://127.0.0.1 -b "dc=example,dc=com" -D "cn=admin,dc=example,dc=com" -w <密码>
该命令将会使用389端口连接LDAP服务器,-ZZ参数的意思是证书校验失败后将不走普通链接,如果指定-Z参数则表明如果证书校验失败则改为普通链接。
(4) 使用普通用户来测试:
a. ldaps
ldapsearch -x -H ldaps://127.0.0.1 -b "dc=example,dc=com" -D "uid=<用户名>,ou=People,dc=example,dc=com" -w <密码>
b. TLS
ldapsearch -x -ZZ -H ldap://127.0.0.1 -b "dc=example,dc=com" -D "uid=<用户名>,ou=People,dc=example,dc=com" -w <密码>
7. 客户端
以上测试在安装了OpenLDAP服务的主机上测试是OK的,但是如果在局域网中找另外一台主机测试TLS链接则会失败,原因有以下两种:
(1) 报"certificate verify failed: self signed certificate in certificate chain",也就是自签名证书校验失败。
解决这个问题的步骤如下:
a. 将CA证书从LDAP服务端拉到客户端,在客户端主机执行:
sudo scp root@192.168.28.2:/etc/openldap/certs/cacert.pem /etc/openldap/certs
b. 修改客户端host文件,解析LDAP证书(非CA证书)中的CN地址。
比如LDAP证书中的CN为ldap.example.com,服务位于192.168.28.2主机,则需要添加以下解析:
ldap.example.com 192.168.28.2
然后通过域名访问。
(2) 报"TLS: hostname does not match name in peer certificate":
解决方案参考上面的(1).b
三、禁用匿名登录
1. 配置"cn=config"
(1) 创建anon.ldif
vi anon.ldif
(2) 初始化
dn: cn=config
changetype: modify
add: olcDisallows
olcDisallows: bind_anon
(3) 执行修改
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f anon.ldif
2. 测试
ldapsearch -x -H ldap://127.0.0.1
四、参考
1. 官方
https://www.openldap.org/doc/admin26/tls.html
https://www.openldap.org/doc/admin26/security.html
2. TLS
https://datatracker.ietf.org/doc/html/rfc2830
http://shibboleth.net/community/advisories/secadv_20120227.txt
https://www.golinuxcloud.com/configure-openldap-with-tls-certificates/
3. Anonymous Bind
https://joeho.xyz/blog-posts/disable-anonymous-bind-for-openldap-in-centos7/