如何解决 PHP 中的 ldap_start_tls()“无法启动 TLS:连接错误”?

Posted

技术标签:

【中文标题】如何解决 PHP 中的 ldap_start_tls()“无法启动 TLS:连接错误”?【英文标题】:How do I solve ldap_start_tls() "Unable to start TLS: Connect error" in PHP? 【发布时间】:2011-02-10 23:45:16 【问题描述】:

我明白了:

警告:ldap_start_tls() [function.ldap-start-tls]:无法 启动 TLS:连接错误 /var/www/X.php 在 Y 行

/etc/ldap/ldap.conf:

TLS_CACERT     /etc/ssl/certs/ca.crt

ca.crt 是签署 LDAP 服务器证书的 CA。 LDAP 服务器上的证书已过期,我无法更改。

【问题讨论】:

【参考方案1】:

问题中提出的特定场景 - 具有无法更改的过期证书 - 似乎需要在 LDAP 客户端上禁用证书验证。

然而,我怀疑很多人,像我一样,访问此页面是因为其他根本原因收到不透明的 LDAP TLS 错误,其中禁用 TLS 证书验证不是一个合适的答案。

在我的例子中——在 Ubuntu 18.04 LTS 服务器上使用 Mediawiki 的 LDAP 身份验证扩展,并在 Windows Server 2012 服务器上针对 Active Directory 进行身份验证——身份验证在 2020 年 1 月/2 月停止工作。服务器证书和 CA证书仍然有效,并且来自 Mediawiki 服务器的 openssl s_client -verify 2 -connect <AD server>:636 顺利通过。

最后我注意到 AD/LDAP 服务的 SSL 证书中的签名算法是 SHA1,我记得最近遇到了first known chosen-prefix collision exploit。这使我调查了系统上最近更新的软件包的更改日志,该日志在gnutls28 changelog circa January 8th, 2020 中显示了“将 SHA1 标记为证书签名不安全”。 (Ubuntu 18.04 中 php-ldap 包的依赖链到 php7.2-ldap -> libldap-2.4-2 -> libgnutls30,其源包为 gnutls28。)

我关注了一些instructions to update the Windows CA to use SHA256,然后选择性地关注了instructions to renew the AD/LDAP cert,在我的Mediawiki服务器上安装了新的CA证书,问题就解决了!简而言之,这些步骤包括:

    在 AD 服务器上的 Admin PowerShell 中,运行 certutil -setreg ca\csp\CNGHashAlgorithm SHA256 在证书颁发机构 MMC 中,右键单击 CA -> 所有任务 -> 更新 CA 证书 在空白 MMC 中,添加证书管理单元;选择本地计算机 在个人 -> 证书下,找到 LDAPS(Kerberos 身份验证模板类型)使用的当前条目 -> 所有任务 -> 高级选项 -> 使用相同密钥续订此证书 在同一窗口中,打开新的 CA 证书 -> 详细信息 -> 复制到文件 -> 无私钥 -> base64-encoded X.509 将生成的文件复制到 Mediawiki 服务器上的 /usr/share/ca-certificates/,然后运行 ​​sudo dpkg-reconfigure ca-certificates 并选择要包含的新 CA 证书。

附言出于 SEO 目的,根据我使用的模式,错误消息包括:

HTTP 错误日志中的ldap_start_tls(): Unable to start TLS: Connect error in /var/www/mediawiki/extensions/LdapAuthentication/LdapAuthenticationPlugin.php ldap_start_tls(): Unable to start TLS: Can't contact LDAP server in [...] Failed to start TLS. 在 Mediawiki 调试日志中(当使用 wgLDAPEncryptionType = ssl,即加密的 LDAP 端口,636 时) Failed to bind as CN=foobar,CN=Users,DC=myOrgName,DC=local 在 Mediwiki 调试日志中(使用 wgLDAPEncryptionType = tls,即未加密 LDAP 端口 389 上的 STARTTLS)

【讨论】:

【参考方案2】:

您可以通过发出来忽略windows中的有效性

putenv('LDAPTLS_REQCERT=never');

在您的 php 代码中。在 *nix 中,您需要编辑您的 /etc/ldap.conf 以包含

TLS_REQCERT never

另外需要注意的是它需要版本 3(版本 2 是 php 默认的):

//$hostnameSSL example would be "ldaps://just.example.com:636" , just make sure it has ldaps://
$con = ldap_connect($hostnameSSL);
ldap_set_option($con, LDAP_OPT_PROTOCOL_VERSION, 3);

为了更好地了解正在发生的事情,您可以通过以下方式启用调试日志记录:

ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7);

这可以在ldap_connect 发生之前完成。

【讨论】:

这样做对我不起作用。我必须做的(按照mediawiki.org/wiki/Thread:Extension_talk:LDAP_Authentication/… 的线程)设置 $wgLDAPEncryptionType = array('YOUR_DOMAIN' => 'clear');在 LocalSettings.php 中。这让它立即启动并开始工作。 请注意,禁用证书验证会导致中间人攻击打开安全漏洞。您正在加密传输而不验证目的地! @svandragt 现在我什至不在乎。如果它会给我一些不是错误的东西,我将永远感激不尽。在运行 PHP 5.3 的 windows 系统上,上面的答案不起作用 这是一个糟糕的答案。他应该解决问题而不是禁用检查。 我同意修复 ssl 问题;但是,为ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7); +1,因为没有它,解决问题是行不通的。所有关于我的 win+cygwin+php ldap.conf 的查找位置都是错误的(/etc/openldap/ldap.conf 是它最终被查找的位置)。【参考方案3】:

对其他人的一些额外帮助,这里的证书解决方案解决了我的ldapsearch命令行问题,但PHP仍然抱怨**Can't contact LDAP server**

原来是 RHEL7 ( CentOS7 ) 上的 SELinux 默认阻止 HTTPD 使用 LDAP 端口 389 和 636,您可以通过以下方式取消阻止:

setsebool -P httpd_can_network_connect 1

检查您的 SELinux 审核日志文件是否有被阻止的内容。

【讨论】:

【参考方案4】:

我能够在 Amazon Linux (Elastic Beanstalk PHP 7.0) 和 MacOS Server 5 LDAP 上使用 openldap 正常工作,并根据需要设置 TLS。

在 /etc/openldap/ldap.conf 中:

TLS_REQCERT 需求

TLS_CACERT /etc/openldap/certs/yourcacert.pem

(请注意,如果您不使用 openldap,则路径将为 /etc/ldap/certs/yourcacert.pem)。在我将证书放入 certs 文件夹之前,此设置不起作用;它不适用于任何其他路径。

要放置在该路径中的证书不是服务器的 TLS 证书。它是颁发服务器/域特定 TLS 证书的颁发机构的 CA(证书颁发机构)证书。在 php.ini 中尝试 LDAP 绑定之前,只有放置在该路径中的 CA 证书才允许 TLS 工作。从您的服务器获取 CA 证书或从权威机构的站点下载,它们是免费提供的。

要测试 LDAP 绑定是否在没有 TLS 的情况下也能正常工作,请暂时设置 TLS_REQCERT(可能需要注释 #out TLS_CACERT)。如果您收到“无法连接到 LDAP”,这不是 TLS 错误;它根本无法连接到服务器,您可能需要打开端口 389(不是 TLS 的 636)。

记住每次更改配置文件或证书时都要重新启动 Apache 服务器。

【讨论】:

【参考方案5】:

    在基于 debian 的系统中:

    安装包:ldap-utils并在文件中 /etc/ldap/ldap.conf,编辑该行:

    TLS_CACERT /etc/ldap/cacerts/cacert.asc
    

    创建目录/etc/ldap/cacerts并将cacert复制到 /etc/ldap/cacerts/cacert.asc

    重启apache

    在基于 redhat 的系统中:

    安装包:openldap-clients并在文件中 /etc/openldap/ldap.conf编辑行:

    TLS_CACERT /etc/openldap/cacerts/cacert.asc
    

    创建目录/etc/openldap/cacerts并将cacert复制到 /etc/openldap/cacerts/cacert.asc

    重启httpd

【讨论】:

这看起来是正确的答案(复制我想要信任的特定证书而不是忽略证书验证)。不幸的是,我无法再验证它,因为我们已经废弃了那个特定的设置。 它提到了“编辑行”,但没有提到行中实际正在编辑的内容 我的意思是,确保提及 TLS_CACERT 的行具有该值。【参考方案6】:

ldap.conf 在 Windows 中的路径是固定的:

c:\openldap\sysconf\ldap.conf

可能需要重新启动网络服务器才能应用更改。

【讨论】:

我的系统上没有那个目录 @KolobCanyon 是的;我也没有。只需使用TLS_REQCERT never 制作文件夹和 ldap.conf 文件即可为我工作。如果您担心使用 OpenLDAP,请尝试 echo phpinfo(); 并检查您的 LDAP 版本的输出。【参考方案7】:

我的解决方案/解决方法是使用

/etc/ldap/ldap.conf:
#TLS_CACERT /etc/ssl/certs/ca.crt
TLS_REQCERT never

如果您有更好的想法,请发布另一个答案。

【讨论】:

以上是关于如何解决 PHP 中的 ldap_start_tls()“无法启动 TLS:连接错误”?的主要内容,如果未能解决你的问题,请参考以下文章

如何解决 PHP 和 MySQL 中的 UTF-8/Unicode 问题 [关闭]

无法通过 Hostgator 中的 Office365 使用 PHP (phpmailer) 发送邮件。如何解决这个问题?

php使用redis怎么解决秒杀中的超卖问题

如何解决require_once中的致命错误

如何在 PHP 中回显此 SimpleXMLElement 中的 OK 属性? [复制]

如何解决 php json_decode 中的 JSON_ERROR_UTF8 错误?