Nginx

允許通過反向代理登錄 IIS 站點的正確方法是什麼?

  • December 5, 2018

我有一個 nginx 反向代理,我正在嘗試讓一個帶有登錄名的 IIS 網站在它後面工作。我發現這個問題被問了好幾次,但每個答案似乎都不一樣,而且有些問題與我遇到的問題有點不同。

使用我目前的配置,我可以登錄,但是我收到 401 錯誤,並且它一直在詢問憑據。

我目前的配置:

/etc/nginx/sites-available/default

server {
   listen 80 default;
   server_name _;
   return 301 https://$host$request_uri;
}

server {
   listen 443 ssl;
   server_name server2.mydomain.com;

   ssl_certificate /usr/local/nginx/conf/mydomain.com.crt;
   ssl_certificate_key /usr/local/nginx/conf/mydomain.com.key;
   ssl_session_cache shared:SSL:10m;

   ssl_session_timeout 5m;

   ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
   ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
   ssl_prefer_server_ciphers on;

   location / {
       proxy_pass http://192.168.0.20:80;
       proxy_set_header Host $host;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto https;
       proxy_redirect http:// $scheme://;

   }
}

我的問題是,這應該工作的正確方法是什麼?

以下是我迄今為止研究過的內容:

這個連結,說這是不可能的。

這個連結說我應該在上游使用keepalive。這可能是答案,但是每當我在其中添加upstream server2.mydomain.com任何配置時,nginx 都無法重新啟動。我確定我有一些語法不正確,但我已經嘗試了幾件事。我會發布我嘗試過的所有內容,但我什至不確定這是正確的方法,而且我已經嘗試了很多東西,我想問問普通人是如何做到的會更容易。

這個連結說你可以只添加proxy_pass_request_headers on;一行,它會以某種方式工作……但它不適合我。

這個連結,似乎最有可能工作,但在試圖弄清楚如何使用這個連結編碼為 base64 之後,我一無所獲。

任何幫助是極大的讚賞。 是我之前問過的一個問題,與此相關,但問題不同。


編輯1

我很抱歉這麼晚了,已經走了一點。

這是我對 nginx 反向代理伺服器的訪問日誌。192.168.0.5 是我的客戶僅供參考。

這些日誌來自我訪問該站點、獲得登錄提示、嘗試登錄一次(未成功)並登出提示。

/var/log/nginx/access.log

192.168.0.5 - - [09/Feb/2016:14:04:14 -0600] "GET / HTTP/1.1" 401 1293 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:42.0) Gecko/20100101 Firefox/42.0"
192.168.0.5 - - [09/Feb/2016:14:04:31 -0600] "GET / HTTP/1.1" 401 341 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:42.0) Gecko/20100101 Firefox/42.0"
192.168.0.5 - - [09/Feb/2016:14:04:31 -0600] "GET / HTTP/1.1" 401 1293 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:42.0) Gecko/20100101 Firefox/42.0"
192.168.0.5 - - [09/Feb/2016:14:04:34 -0600] "GET /favicon.ico HTTP/1.1" 401 1293 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:42.0) Gecko/20100101 Firefox/42.0"

/var/log/nginx/error.log

This file is empty

IIS 日誌

2016-02-11 19:39:22 192.168.0.20 GET /login - 80 - 192.168.0.10 Mozilla/5.0+(X11;+Linux+x86_64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Ubuntu+Chromium/45.0.2454.101+Chrome/45.0.2454.101+Safari/537.36 401 2 5 125
2016-02-11 19:39:28 192.168.0.20 GET /login - 80 - 192.168.0.10 Mozilla/5.0+(X11;+Linux+x86_64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Ubuntu+Chromium/45.0.2454.101+Chrome/45.0.2454.101+Safari/537.36 401 1 21480424 0
2016-02-11 19:39:36 192.168.0.20 GET /login - 80 - 192.168.0.10 Mozilla/5.0+(X11;+Linux+x86_64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Ubuntu+Chromium/45.0.2454.101+Chrome/45.0.2454.101+Safari/537.36 401 1 21480724 0
2016-02-11 19:40:16 192.168.0.20 GET /login - 80 - 192.168.0.10 Mozilla/5.0+(X11;+Linux+x86_64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Ubuntu+Chromium/45.0.2454.101+Chrome/45.0.2454.101+Safari/537.36 401 1 21407424 15
2016-02-11 19:40:22 192.168.0.20 GET /login - 80 - 192.168.0.10 Mozilla/5.0+(X11;+Linux+x86_64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Ubuntu+Chromium/45.0.2454.101+Chrome/45.0.2454.101+Safari/537.36 401 1 21480742 0

登錄沒有安全錯誤,所以我猜它從來沒有真正將登錄送出到系統。每次我點擊“登錄”時,它都會再次給我登錄彈出視窗。

實時 HTTP 標頭外掛輸出

https://server2.mydomain.com/

GET / HTTP/1.1
Host: server2.mydomain.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:42.0) Gecko/20100101 Firefox/42.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

HTTP/1.1 401 Unauthorized
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 09 Feb 2016 19:21:04 GMT
Content-Type: text/html
Content-Length: 1293
Connection: keep-alive
WWW-Authenticate: NTLM
WWW-Authenticate: Negotiate
X-Powered-By: ASP.NET
----------------------------------------------------------
https://server2.mydomain.com/

GET / HTTP/1.1
Host: server2.mydomain.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:42.0) Gecko/20100101 Firefox/42.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Authorization: NTLM TlRNTVMTUAAAB4IIAAAAAAAAAAAAACDAFGAAAAAAAAAAAAAAAAA=

HTTP/1.1 401 Unauthorized
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 09 Feb 2016 19:22:00 GMT
Content-Type: text/html; charset=us-ascii
Content-Length: 341
Connection: keep-alive
WWW-Authenticate: NTLM TlRMTVNTUAACAAAAGgAaADgAAuzKir6ADucAAAAAAAAAAL4A&%$DSDADvgBSAAAABgGxHQAAAA9HAEUARQBLAFMAQQBOAEQATgBFAFIARABTAAIAGgBHRQBLAFMAQQBOAEQATgBFDFAFIARABTAAEADABLAEUATABWAEkATgAEACIAZwBlAGUAawBzAGEAbgBkAG4AZQByAGQAcwAuAGMAbwBtAAMAMABLAEUATABWAEkATgAuAGcAZQBlAGsAcwBhAG4AZABuAGUAcgBkAHMALgBjAG8AbQAFACIAZwBlAGUAawBzAGEAbgBkAG4AZQByAGQAcwAuAGMAbwBtAAcACAABRuM1b2PRAQAAAAA=
----------------------------------------------------------
https://server2.mydomain.com/

GET / HTTP/1.1
Host: server2.mydomain.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:42.0) Gecko/20100101 Firefox/42.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHAAAADqAOoAiAAAAAAAAAAGgAaAEAAAAAWABYAWgAAAAAAAAAAAAAABYIIAGEAbQBhAG4AZABhAC4AYgBsAG8AdQBuAHQAVwBPAFIASwBTAFQAQQBUAEkATwBOAHorEf/j46zta4wONTUAADAA-98uH//ZL0Am16vGzdWutoAAAAGAAYAHQAAAAAAAACFdzVEB9QHmLWLCuQQAAAAAAgAaAEcARQBFAEsAUwBBAE4ARABOAEUAUgBEAFMAAQAMAEsARQBMAFYASQBOAAQAIgBnAGUAZQBrAHMAYQBuAGQAbgBlAHIAZABzAC4AYwBvAG0AAwAwAEsARQBMAFYASQBOAC4AZwBlAGUAawBzAGEAbgBkAG4AZQByAGQAcwAuAGMAbwBtAAUAIgBnAGUAZQBrAHMAYQBuAGQAbgBlAHIAZABzAC4AYwBvAG0ABwAIAAFG4zVvY9EBAAAAAA==

HTTP/1.1 401 Unauthorized
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 09 Feb 2016 19:22:00 GMT
Content-Type: text/html
Content-Length: 1293
Connection: keep-alive
WWW-Authenticate: NTLM
WWW-Authenticate: Negotiate
X-Powered-By: ASP.NET
----------------------------------------------------------

EDIT2 - 為清楚起見,這裡是 IP 設置。


客戶端機器

192.168.0.5

Ubuntu 14.04 桌面


反向代理伺服器

192.168.0.10

nginx 1.4.6

Ubuntu 14.04 伺服器


伺服器 2

192.168.0.20

server2.mydomain.com

阿帕奇2

Ubuntu 14.04 伺服器


EDIT3 - 也許這有效,我做錯了,….也許不是

這篇文章中,Fizz 寫了答案。

我在下面試過這個

/etc/nginx/sites-available/default

server {
   listen 80 default;
   server_name _;
   return 301 https://$host$request_uri;
}

upstream server2.mydomain.com {
       server 192.168.0.20:80
keepalive 16;
}

server {
   listen 443 ssl;
   server_name server2.mydomain.com;

   ssl_certificate /usr/local/nginx/conf/mydomain.com.crt;
   ssl_certificate_key /usr/local/nginx/conf/mydomain.com.key;
   ssl_session_cache shared:SSL:10m;

   ssl_session_timeout 5m;

   ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
   ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
   ssl_prefer_server_ciphers on;

   location / {
       proxy_pass http://192.168.0.20:80;
       proxy_http_version 1.1;
       proxy_set_header Connection "";
       proxy_set_header Host $host;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto https;
       proxy_redirect http:// $scheme://;

   }
}

結果相同。基於其他答案….也許 apache2 是更好的選擇?


EDIT4 - 根據 Maxim Dounin 的回答進行編輯

我現在正在嘗試使用 Nginx 1.9.9,以及 Maxim Dounin 的回答中提到的流代理方法。

我從原始碼編譯,所以我的文件位置現在不同了。

/opt/nginx/nginx.conf

worker_processes 1;
events {
   worker_connections 1024;
}

stream {
   upstream backend {
      hash $remote_addr consistent;

      server server2.mydomain.com:80 weight=5;
      server 192.168.0.20:80            max_fails=3 fail_timeout=30s;

   }

   server {
       listen 443 ssl;        #Line 27
       server_name server2.mydomain.com;

       ssl_certificate /usr/local/nginx/conf/mydomain.com.crt;
       ssl_certificate_key /usr/local/nginx/conf/mydomain.com.key;
       ssl_session_cache shared:SSL:10m;

       ssl_session_timeout 5m;

       proxy_connect_timeout 1s;
       proxy_timeout 3s;
       proxy_pass backend;
   }

#    server {
#        listen [::1]:12345;
#        proxy_pass unix:/tmp/stream.socket;
#    }
}

我註釋掉了最後一個推薦的伺服器行,因為我不知道該怎麼做,但是由於其他錯誤,我的配置文件無論如何都沒有到達那裡。現在我的**/opt/nginx/logs/error.log**第 27 行有問題

the "ssl" parameter requires ngx_stream_ssl_module in /opt/nginx/nginx.conf:27

我肯定是用 ngx_stream_ssl_module 編譯的,因為當我執行nginx -V時,我得到了configure arguments: --with-stream

希望我走在正確的軌道上。

問題是NTLM 身份驗證(注意WWW-Authenticate: NTLM ...),也就是 Windows 身份驗證。

NTLM 身份驗證對連接而不是請求進行身份驗證,這與 HTTP 協議有些矛盾,HTTP 協議預計是無狀態的。因此,它通常不能通過代理工作,包括 nginx。

最簡單的解決方案是將 IIS 端的身份驗證更改為“基本”。如果由於某種原因這不是一個選項,其他可能性包括:

  • 使用nginx 1.9.x 中可用的流代理。這會將連接從客戶端映射到上游伺服器,因此 NTLM 身份驗證將起作用。
  • 使用商業 nginx 版本中可用的ntlm功能。

請注意,有一些建議將上游與 keepalive 一起使用,以使 NTLM 身份驗證正常工作。這些建議是不正確且有害的 - 除非您只為一位使用者使用代理。最糟糕的是,它可能看起來工作正常。問題是上游伺服器的keepalive連接保存在一個公共記憶體中,這些連接可以用於所有客戶端。因此,如果記憶體中存在經過身份驗證的連接,則碰巧使用此連接的無關客戶端將能夠繞過身份驗證。

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