我在 CentOS 6.5 下运行 Apache 2.2.15。该模块mod_authnz_ldap
用于针对 Microsoft AD 服务器进行身份验证。以下是 Apache 中的 LDAP 配置:
AuthType Basic
AuthBasicProvider ldap
AuthzLDAPAuthoritative on
AuthLDAPURL ldap://[ad server ip address]/[basedn]?mail
AuthLDAPBindDN [binddn]
AuthLDAPBindPassword [bindpass]
AuthName "LDAP: myhost.example.com"
Require ldap-group cn=[foo],ou=Permissions,ou=Groups,ou=[bar],dc=[baz],dc=com
大多数情况下,浏览器对此 Apache 主机的请求都可以正常工作;它可以针对 AD 服务器正确进行身份验证并且页面可以正常加载。
然而,平均每隔几分钟,请求就会从浏览器端挂起一次。tcpdump 显示 Apache 正在发送 TCP RST 数据包,显然是为了响应来自 AD 主机的 PSH ACK 数据包。交换如下所示:
53 600.408744 Apache AD TCP 74 42804 > ldap [SYN] Seq=0 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=2665219285 TSecr=0 WS=128
55 600.469478 AD Apache TCP 66 ldap > 42804 [PSH, ACK] Seq=1 Ack=3457841362 Win=65093 Len=0 TSval=4832637 TSecr=2664621718
56 600.469524 Apache AD TCP 54 42804 > ldap [RST] Seq=3457841362 Win=0 Len=0
65 601.409434 Apache AD TCP 74 [TCP Retransmission] 42804 > ldap [SYN] Seq=0 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=2665220285 TSecr=0 WS=128
67 601.470951 AD Apache TCP 78 [TCP Previous segment not captured] ldap > 42804 [SYN, ACK] Seq=252322338 Ack=1 Win=16384 Len=0 MSS=1380 WS=1 TSval=0 TSecr=0 SACK_PERM=1
此时之后,在此连接上不会发送任何其他数据包,因此线程似乎处于挂起状态。strace 没有提供任何说明,它仅显示使用 LDAP 绑定请求进行的 write() 调用。
我还让一个运行时间较长的 tcpdump 会话捕获了一个 Apache 进程,该进程试图从不属于任何打开连接的 TCP 端口发送 LDAP 请求。它看起来像是来自较早的连接(类似于上面转储中显示的类型),不知何故 Apache 进程认为该连接仍处于打开状态。
我认为其中一个 LDAP 缓存可能有问题,因此我按如下方式禁用了它们:
LDAPSharedCacheSize 0
LDAPCacheEntries 0
LDAPOpCacheEntries 0
但这并没有什么不同;问题仍然存在。
目前修复此问题的唯一方法是每隔几分钟重启 Apache。由于服务器负载较大,重启几分钟后问题就会出现。