Dovecot/Postfix:如何在查询 LDAP 进行身份验证之前强制对用户名进行初始语法检查?

Dovecot/Postfix:如何在查询 LDAP 进行身份验证之前强制对用户名进行初始语法检查?

我有一个 Postfix/Dovecot 设置并使用 OpenLDAP 作为用户/密码后端。由于虚拟主机,用户必须使用其完全合格的电子邮件地址作为用户名登录,因此域部分对于身份验证是必需的,即用户名如下所示<local-part>@<fqdn-domain>

然而,不断有攻击试图使用不带域部分的用户名进行身份验证。由于这会导致 LDAP 查询中的 DN 无效,我的日志中充满了大量由于 LDAP DN 无效而产生的错误消息。

是否有任何配置选项允许 Dovecot 对提供的用户名强制执行一些初始语法检查,如果检查失败,Dovecot 会通过立即拒绝响应来简化身份验证过程,而不是查询 LDAP 服务器然后失败?

Dovecot 中的 LDAP 配置是

uris = ldapi://%2frun%2fopenldap%2fslapd.sock
auth_bind = yes
auth_bind_userdn = uid=%n,ou=users,o=%d,dc=my-host,dc=my-domain,dc=my-tld
base = ou=users,o=%d,dc=server,dc=my-host,dc=my-domain,dc=my-tld

如您所见,我的 LDAP 设置使用所谓的“连接点”为不同的托管域在 DIT 中提供不同的子分支。(o=%dDN 中的 -part。)根据Dovecot 配置手册 - 用户变量,%d如果用户名在 之后没有域部分,则为空@

当攻击者尝试使用不完整的用户名进行身份验证时,这会导致我的日志中出现多余的错误消息,例如

Dec 26 16:25:54 server dovecot[24946]: auth: Error: ldap(root,187.205.80.184): ldap_bind() failed: Invalid DN syntax

这里来自 187.205.80.184 的攻击者尝试以用户身份进行身份验证root,而 Dovecot 尝试查找,uid=root,ou=users,o=,dc=my-host,dc=my-domain,dc=my-tld这显然是无效的,因为后面没有任何内容o=

答案1

从 Dovecot v2.2.33 开始,你可以使用以下方式设置默认域条件语句

%{if;%d;eq;;example.com;%d}

这是:

  • if使用条件语句
  • %d 值 1比较
  • eq 操作员:字符串相等
  • 空的值 2为了比较
  • example.com如果条件为true;则结果值为%d空字符串(默认)
  • %d如果条件为false; 则结果值%d设置为 (非空)

您可以在 LDAP 配置中使用它,而不是%d

uris = ldapi://%2frun%2fopenldap%2fslapd.sock
auth_bind = yes
auth_bind_userdn = uid=%n,ou=users,o=%{if;%d;eq;;example.com;%d},dc=example,dc=com
base = ou=users,o=%{if;%d;eq;;example.com;%d},dc=example,dc=com

答案2

我自己找到了另一种解决方案,它不需要变量中的条件,因此也适用于较旧的 Dovecot 版本。在 -variable 的特定情况下,%d以下配置指令可以解决问题

auth_realms = <vhosted-dom-1> <vhosted-dom-2> ... <vhosted-domain-n>
auth_default_realm = nowhere.notld

第一行是受支持的身份验证领域的空格分隔列表。根据客户端选择的 SASL 身份验证方法,这会通知客户端现有的身份验证领域。当然,这并不能阻止(愚蠢的)脚本攻击者仍然使用没有域部分的用户名。但是,正确设置该配置是一种好的做法。

第二行定义了默认领域(或我这里所说的域),如果客户端未能提供,Dovecot 会自动添加该领域。这里我将其设置为虚构的名称nowhere.notld。该值实际上并不重要,它应该与任何实际域不同。

最后说明:当然,这不会阻止有关身份验证尝试失败的日志消息。但这没关系。但是,它可以防止由于无效 DN 而导致 LDAP 出现致命错误。相反,Dovevot 会发出有关身份验证失败的适当警告。

相关内容