我知道这里和“Unix/Linux”上的 gazzilion pam / nginx 问题,但它们要么没有答案,要么与我的设置无关 - 所以我再试一次:)
总结
虽然设置与Apache+mod_kerb_auth
组合完美配合,但使用时我无法使自动票证转发正常工作nginx+pam_krb5
- 但是针对 Kerberos 的基本身份验证却有效。问题是,可能是什么原因以及/或者如何进一步调试它。
以下是所有详细信息、配置和环境
我的设置:
- 实验室中的 Windows 2012 DC(全新安装并配置 KDC)
- Debian Stretch Linux 作为我们的“服务”
- 在那个 Debian 盒子上我有:kerb-client MIT、Apache2+mod_kerb_auth 和 nignx+nginx_pam+pam
- MacOS 客户端
正在运行的是:
- 我有通常的设置,包括 keytab-file、/etc/krb5.conf 以及所有的 realm/default_realm 部分。(见下文)
- 我可以使用 keytab 文件和我的 SPN 进行 kinit:(
HTTP/wiki.kwtest.local
见下文) - 在同一个 Debian 服务器上使用 Apache2 + mod_kerb_auth,它完全可以工作,包括票证转发(我猜这确认了 krb5.conf / keytab / KDC /infra 设置可以工作)。因此,我可以在我的 OSX 上使用
kinit
+curl --negotiate
或 Safari 并立即获得访问权限。 - 添加 pam auth(见下文)和 pam 设置后,我可以通过 safari 访问时输入 AD 用户凭据进行身份验证(由于 curl 立即获得 401
-u
)...但票证转发/验证不起作用
设置详情:
Kerberos 客户端配置/etc/krb5.conf
[libdefaults]
default_realm = KWTEST.LOCAL
kdc_timesync = 1
# https://web.mit.edu/kerberos/krb5-1.12/doc/basic/ccache_def.html
# we do not want the keyring due to docker
ccache_type = 3
forwardable = true
proxiable = true
# no reverse lookup
rdns = false
[realms]
KWTEST.LOCAL = {
kdc = kdc.kwtest.local
admin_server = kdc.kwtest.local
}
[login]
krb4_convert = true
krb4_get_tickets = false
[logging]
default = FILE:/var/log/kdc.log:SYSLOG
kdc = FILE:/var/log/kdc.log:SYSLOG
# https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html?highlight=appdefaults#appdefaults
[appdefaults]
forwardable = true
# https://manpages.debian.org/stretch/libpam-heimdal/pam_krb5.5.en.html
pam = {
ignore_k5login=true
debug=true
forwardable = true
proxiable = true
minimum_uid = 0
realm = KWTEST.LOCAL
keytab = /mnt/config/kerberos/drupalwiki.keytab
}
Pam 配置/etc/pam.d/dw-kerb-nginx
cat /etc/pam.d/dw-kerb-nginx
auth required pam_krb5.so keytab=/mnt/config/kerberos/drupalwiki.keytab minimum_uid=20 forwardable=true realm=KWTEST.LOCAL trace=/var/log/pamtrace silent=false debug=true
account required pam_unix.so keytab=/mnt/config/kerberos/drupalwiki.keytab minimum_uid=20 forwardable=true realm=KWTEST.LOCAL trace=/var/log/pamtrace silent=false debug=true
该默认服务器的 Nginx 配置为/etc/nginx/sites-enabled/default
cat /etc/nginx/sites-enabled/default
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
error_log /var/log/nginx/error.log debug;
location / {
auth_pam "Secure Zone";
auth_pam_service_name "dw-kerb-nginx";
try_files $uri $uri/ =404;
}
}
KVNO 数字匹配
#kdc KVNO
kvno HTTP/[email protected]
HTTP/[email protected]: kvno = 16
#client KVNO
klist -ke /mnt/config/kerberos/drupalwiki.keytab
Keytab name: FILE:/mnt/config/kerberos/drupalwiki.keytab
KVNO Principal
---- --------------------------------------------------------------------------
16 HTTP/[email protected] (arcfour-hmac)
服务 Keytab 文件/mnt/config/kerberos/drupalwiki.keytab
列出了 SPN
klist -ke /mnt/config/kerberos/drupalwiki.keytab
Keytab name: FILE:/mnt/config/kerberos/drupalwiki.keytab
KVNO Principal
---- --------------------------------------------------------------------------
16 HTTP/[email protected] (arcfour-hmac)
keytab
使用 SPN登录文件
kinit -k -t /mnt/config/kerberos/drupalwiki.keytab HTTP/[email protected]
klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: HTTP/[email protected]
Valid starting Expires Service principal
01/07/2019 12:50:18 01/07/2019 22:50:18 krbtgt/[email protected]
renew until 01/08/2019 12:50:18
问题(不起作用):
票证转发,即现有的客户端票证,不经过验证,而是提供基本身份验证表单以输入凭据 - 如果我这样做,我就可以进行身份验证。因此,基本 krb 身份验证已经起作用,只是票证转发/验证不起作用。
请注意,完全相同的客户端(OSX Safari、OSX curl、Linux Curl)和完全相同的 Debian Stretch 服务器都可以使用。因此,这几乎不可能是服务文件或的Apache2+mod_ker_auth
直接问题,否则 apache2 也无法工作,对吗?keytab
/etc/krb5.conf
我如何测试
使用我的 OSX 客户端进行测试
# wikiuser is an user in the same AD/KDC ( not the user of the SPN)
kinit [email protected]
# ticket exists
klist
Credentials cache: API:34173A61-DFBB-4191-A39C-62EF67F1AC39
Principal: [email protected]
Issued Expires Principal
Jan 7 13:26:38 2019 Jan 7 23:26:20 2019 krbtgt/[email protected]
# the actual test
curl -u : --negotiate http://wiki.kwtest.local/index.html
<html>
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.10.3</center>
</body>
</html>
做同样的测试,同时停止 nginx 并启动 apache2
# on the Debian Service box
service nginx stop && service apache2 start
现在在我的 OSX 盒子上
kinit
curl -u : --negotiate http://wiki.kwtest.local/index.html
worked!%
我尝试修复它
- 尝试使用 rsyslog 和 debug=true / trace=/var/log/pamtrace 设置尽可能详细地记录 pam,但我从未在其中得到任何输出。PAM 似乎根本无法记录身份验证尝试。只有当我填写基本表单并实际成功验证时,我才会在日志中看到此尝试 - 但使用现有票证的失败尝试根本没有记录任何内容
- 尝试了各种
pam_krb5
参数和设置realm
,但还是无法让它工作 - 使用 Linux 客户端通过 curl 进行测试,结果相同
如果我忘记了设置细节或信息中的任何内容,请告诉我,我完全清楚 Kerberos 很复杂,而且对所有这些事情都很敏感,我希望已经包含了所有的点点滴滴
答案1
这个问题的简短回答是,nginx_pam 根本不可能做到这一点。
我要求的技术术语/协议是“GSSAPI”或基于 SPENGO 的 Kerberos 票证认证,因此如果用户有现有的 Kerberos 票证,他就会自动登录。
nginx_pam 不实现 SPENGO/GSSAPI,因此这永远不会起作用。应该发生的是
客户端在第一次请求时请求资源(尚未发送任何身份验证标头)
我们的 nginx 会通过 nginx_pam 将其传递给 pam,然后 pam 应该返回“未授权”(不存在身份验证标头)。Nginx 现在应该向浏览器返回带有标头“WWW-Authorize:negotiate”的“401”(然后浏览器会自动发送带有“Authorization”标头中的 kerb 票证的新请求
nginx 现在应该解压该票证(based64 解码等)并将票证传递给 pam(pam_krb)
pam 将返回“ok”或“forbidden”(不允许此用户)。前者是 200,后者是 403,用于传递给客户端的 nginx
步骤 2 不是由 nginx_pam 实现的。另外,我猜(不确定),pam 只支持“授权”或“未授权”,所以是布尔值,而不是“未经身份验证”、“授权”、“禁止”……因此无法确定步骤 2 和步骤 4(相同)
解决方案:我换成了https://github.com/stnoonan/spnego-http-auth-nginx-module以获得正确的基于 GSSAPI 的实现。