基于GSS代理认证与LDAP授权的Apache服务故障排查
嘿,看你折腾了这么久,Kerberos认证没问题但LDAP授权卡壳,咱们一步步来拆解这个问题。先理清楚你的核心场景:RHEL 9上的Apache 2.4,域内服务器用GSS proxy做Kerberos认证,AD作为LDAP源做分级授权,第一个目录的valid-user正常,但第二个目录的LDAP组授权完全失效,用本地组文件反而能正常工作。
先复盘你的当前配置与错误现象
首先看你给出的目录配置:
# 正常工作的目录配置 <Directory /var/www/nietools.elsinor.net/html/> AuthType GSSAPI AuthName "GSSAPI Login" Require valid-user </Directory> # 授权失败的目录配置 <Directory /var/www/nietools.elsinor.net/html/tools/config_grep/> AuthType GSSAPI AuthName "GSSAPI Login" #GssapiConnectionBound On #GssapiSignalPersistentAuth On #GssapiUseSessions On #Session On #SessionCookieName gssapi_session path=/private;httponly;secure; AuthLDAPUrl "ldaps://ad.elsinor.net:636/OU=People,DC=ad,DC=elsinor,DC=net/?sAMAccountName?sub" AuthLDAPBindDN "CN=nietools,OU=Services,DC=ad,DC=elsinor,DC=net" AuthLDAPBindPassword "exec:/bin/cat /etc/httpd/conf.d/pw" Require ldap-group "CN=NIE,OU=Groups,DC=ad,DC=elsinor,DC=net" </Directory>
访问第二个目录时,Apache日志抛出两个关键错误:
2023-08-07 15:40:27.893785 ... module=authz_core, loglevel=error, message="AH01631: user testuser@AD.ELSINOR.NET: authorization failure for "/tools/config_grep": "
2023-08-07 15:40:27.992661 ... module=auth_gssapi, loglevel=error, message="INTERNAL ERROR Mechanism needs continuation but neither GssapiConnectionBound nor GssapiUseSessions are configured"
你已经试过调整注释掉的参数、切换LDAP属性、开启SELinux布尔值httpd_can_connect_ldap(审计日志干净),甚至用本地组文件验证了授权逻辑本身没问题,这些尝试都很到位。
重点排查方向
1. 先解决GSSAPI的内部会话错误
那个“Mechanism needs continuation”的错误大概率不是良性的——虽然你说常规文档里找不到这些参数,但RHEL 9的mod_auth_gssapi版本可能新增了会话相关的要求。你需要把这些参数正式启用,而不是注释掉:
GssapiConnectionBound On GssapiUseSessions On Session On SessionCookieName gssapi_session path=/;httponly;secure;
注意要先确认mod_session模块已经加载,执行httpd -M | grep session就能看到。这个错误的本质是GSSAPI需要保持会话状态,才能把认证后的用户身份正确传递给后续的LDAP授权模块,不解决这个,身份传递可能会出问题。
2. 修正Kerberos用户名到LDAP身份的映射
你在调试日志里发现Kerberos传递的是testuser@AD.ELSINOR.NET,但LDAP里的sAMAccountName是不带域后缀的testuser,这会导致LDAP查询不到匹配的用户。你可以添加GssapiLocalName On参数,让mod_auth_gssapi自动去掉Kerberos主体的@REALM部分,只传递纯用户名给LDAP模块:
<Directory /var/www/nietools.elsinor.net/html/tools/config_grep/> AuthType GSSAPI AuthName "GSSAPI Login" GssapiLocalName On # 新增这个参数 GssapiConnectionBound On GssapiUseSessions On Session On SessionCookieName gssapi_session path=/;httponly;secure; # 其余LDAP配置不变 AuthLDAPUrl "ldaps://ad.elsinor.net:636/OU=People,DC=ad,DC=elsinor,DC=net/?sAMAccountName?sub" AuthLDAPBindDN "CN=nietools,OU=Services,DC=ad,DC=elsinor,DC=net" AuthLDAPBindPassword "exec:/bin/cat /etc/httpd/conf.d/pw" Require ldap-group "CN=NIE,OU=Groups,DC=ad,DC=elsinor,DC=net" </Directory>
另外,你可以先用ldapsearch手动测试LDAP绑定和查询是否正常,排除LDAP本身的问题:
ldapsearch -H ldaps://ad.elsinor.net:636 \ -D "CN=nietools,OU=Services,DC=ad,DC=elsinor,DC=net" \ -W \ -b "OU=People,DC=ad,DC=elsinor,DC=net" \ "(sAMAccountName=testuser)"
输入绑定密码后,确认能查到testuser的信息,同时检查该用户是否确实在CN=NIE,OU=Groups,DC=ad,DC=elsinor,DC=net组里(可以看memberOf属性)。
3. 尝试递归组授权的LDAP过滤器
如果用户是嵌套在NIE组里的,默认的Require ldap-group只会检查直接成员,这时候可以用AD特有的递归查询过滤器:
Require ldap-filter "(memberOf:1.2.840.113556.1.4.1941:=CN=NIE,OU=Groups,DC=ad,DC=elsinor,DC=net)"
这个过滤器会递归检查所有嵌套组的成员,避免因为用户不在直接组里导致的授权失败。
4. 开启更详细的调试日志
把Apache的日志级别调到debug,聚焦认证授权相关模块,能看到更细节的身份传递和LDAP查询过程:
LogLevel debug auth_gssapi auth_ldap authz_core
重启Apache后再次访问目标目录,查看日志里是否有LDAP查询的具体结果——比如是否找到用户、是否检查了组成员、返回的匹配状态是什么,这些信息能直接定位授权失败的原因。
5. 确认GSS proxy配置不干扰LDAP流程
你的GSS proxy配置里有service/ldap项,不过你用的是账号密码绑定LDAP,不是Kerberos绑定,所以这个配置不会直接影响当前场景,但还是要确保gssproxy服务正常运行:
systemctl status gssproxy
另外,确认httpd进程的用户(默认是apache,UID48)能正常访问GSS proxy的缓存目录/var/lib/gssproxy/clients/。
总结
先搞定GSSAPI的会话错误,确保用户身份能正确传递给LDAP模块,再修正用户名映射的问题,最后通过手动LDAP查询和调试日志验证授权逻辑——一步步来,应该能定位到问题所在。
备注:内容来源于stack exchange,提问作者Vaito

