Nginx

帶有 pam_krb5 的 PAM 用於驗證 nginx 請求

  • January 18, 2019

我知道這里和“Unix/Linux”上的 gazzilion pam / nginx 問題,但它們要麼沒有答案,要麼與我的設置無關 - 所以我再試一次:)

TL;博士

雖然該設置與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 文件的正常設置,/etc/krb5.conf 以及所有領域/default_realm 的點點滴滴。(見下文)
  • 我可以使用 keytab 文件和我的 SPN 啟動:(HTTP/wiki.kwtest.local見下文)
  • 在同一個 Debian 伺服器上使用 Apache2 + mod_kerb_auth,它完全包括票證轉發(確認 krb5.conf / keytab / KDC /infra setup 我猜是有效的)。所以我可以在我的 OSX 上使用kinit+curl --negotiate或 Safari 並立即獲得訪問權限。
  • 添加 pam 身份驗證(見下文)和 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/wiki.kwtest.local@KWTEST.LOCAL
HTTP/wiki.kwtest.local@KWTEST.LOCAL: kvno = 16

#client KVNO
klist -ke /mnt/config/kerberos/drupalwiki.keytab
Keytab name: FILE:/mnt/config/kerberos/drupalwiki.keytab
KVNO Principal
---- --------------------------------------------------------------------------
 16 HTTP/wiki.kwtest.local@KWTEST.LOCAL (arcfour-hmac)

/mnt/config/kerberos/drupalwiki.keytab來自列出 SPN 的服務 Keytab 文件

klist -ke /mnt/config/kerberos/drupalwiki.keytab
Keytab name: FILE:/mnt/config/kerberos/drupalwiki.keytab
KVNO Principal
---- --------------------------------------------------------------------------
 16 HTTP/wiki.kwtest.local@KWTEST.LOCAL (arcfour-hmac)

keytab使用 SPN 使用文件登錄

kinit -k -t /mnt/config/kerberos/drupalwiki.keytab HTTP/wiki.kwtest.local@KWTEST.LOCAL

klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: HTTP/wiki.kwtest.local@KWTEST.LOCAL

Valid starting       Expires              Service principal
01/07/2019 12:50:18  01/07/2019 22:50:18  krbtgt/KWTEST.LOCAL@KWTEST.LOCAL
   renew until 01/08/2019 12:50:18

問題(事情不工作):

票證轉發,因此現有的客戶票證,沒有經過驗證,而是提供了一個基本身份驗證表單來輸入憑據 - 如果我這樣做,我可以進行身份驗證。所以基本的 krb 身份驗證已經有效,只是不能進行票證轉發/驗證。

請注意,完全相同的客戶端(OSX Safari、OSX curl、Linux Curl),完全相同的 Debian Stretch 伺服器可以與Apache2+mod_ker_auth. keytab所以它幾乎不可能是服務文件的直接問題/etc/krb5.conf,否則 apache2 也不會工作,對吧?

我是如何測試的

使用我的 OSX 客戶端進行測試

# wikiuser is an user in the same AD/KDC ( not the user of the SPN)
kinit wikiuser@KWTEST.LOCAL

# ticket exists
klist
Credentials cache: API:34173A61-DFBB-4191-A39C-62EF67F1AC39
       Principal: wikiuser@KWTEST.LOCAL

 Issued                Expires               Principal
Jan  7 13:26:38 2019  Jan  7 23:26:20 2019  krbtgt/KWTEST.LOCAL@KWTEST.LOCAL

# 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 對所有這些東西都很複雜和敏感,我希望包括所有的點點滴滴

這個問題的簡短回答是,nginx_pam 根本不可能。

我要求的技術術語/協議是“GSSAPI”或基於 SPENGO 的 kerberos 票證身份驗證,因此如果使用者擁有現有的 kerberos 票證,則會自動登錄。

nginx_pam 沒有實現 SPENGO/GSSAPI,因此它永遠不會起作用。應該發生的是

  1. 在第一個請求中,客戶端請求資源(尚未發送任何身份驗證標頭)
  2. 我們的 nginx 將通過 nginx_pam 將其傳遞給 pam,然後 pam 應返回“未授權”(不存在 auth 標頭)。Nginx 現在應該向瀏覽器返回一個帶有“WWW-Authorize:negotiation”標頭的“401”(然後瀏覽器會自動發送一個新請求,其中包含“Authorization”標頭中的路邊票
  3. nginx 現在應該解壓該票證(基於 64 解碼等)並將票證傳遞給 pam (pam_krb)
  4. pam 將返回“ok”或“forbidden”(此使用者不允許).. 前者是 200,後者是 403,用於傳遞給客戶端的 nginx

步驟 2 不是 nginx_pam 實現的。另外,我猜(不確定),pam 只支持“授權”或“未授權”,所以是布爾值,而不是“未經身份驗證”、“授權”、“禁止”……所以第 2 步和第 4 步不能確定(相同)

**解決方案:**我切換到https://github.com/stnoonan/spnego-http-auth-nginx-module以獲得正確的基於 GSSAPI 的實現。

引用自:https://serverfault.com/questions/947900