允许通过反向代理登录 IIS 站点的正确方法是什么?

tru*_*ype 7 iis password nginx reverse-proxy

我有一个 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://;

    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,这应该起作用的正确方法是什么?

这是我迄今为止研究的内容:

这个链接说这是不可能的。

这个链接说我应该在上游使用 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"
Run Code Online (Sandbox Code Playgroud)

/var/log/nginx/error.log

This file is empty
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

登录没有安全错误,因此我猜它实际上从未将登录提交到系统。每次我点击“登录”时,它都会再次显示登录弹出窗口。

实时 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
----------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

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 - 也许这行得通,但我做错了,....也许不是

这篇文章中,菲兹写的答案。

我在下面试过这个

/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://;

    }
}
Run Code Online (Sandbox Code Playgroud)

结果一样。基于其他答案....也许 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;
#    }
}
Run Code Online (Sandbox Code Playgroud)

我注释掉了最后推荐的服务器行,因为我不知道如何处理它,但是由于其他错误,我的配置文件无论如何都没有到达那里。现在我的/opt/nginx/logs/error.log第 27 行有问题

the "ssl" parameter requires ngx_stream_ssl_module in /opt/nginx/nginx.conf:27
Run Code Online (Sandbox Code Playgroud)

我肯定是用 ngx_stream_ssl_module 编译的,因为当我做nginx -V 时我得到configure arguments: --with-stream

希望我走在正确的轨道上。

Max*_*nin 15

问题是NTLM 身份验证(注意WWW-Authenticate: NTLM ...),AKA Windows 身份验证。

NTLM 身份验证是对连接而不是请求进行身份验证,这有点与 HTTP 协议相矛盾,HTTP 协议应该是无状态的。因此,它通常不通过代理工作,包括 nginx。

最简单的解决方案是在 IIS 端将身份验证更改为“基本”。如果由于某种原因这不是一个选项,其他可能性包括:

  • 使用nginx 1.9.x 中可用的流代理。这会将连接从客户端映射到上游服务器,因此 NTLM 身份验证将起作用。

  • 使用商业 nginx 版本中可用的ntlm功能。

请注意,有一些建议将上游与 keepalive 结合使用,以使 NTLM 身份验证正常工作。这些建议是不正确和有害的 - 除非您只为一个用户使用代理。最糟糕的是它可能看起来工作正常。问题是与上游服务器的保活连接保存在一个公共缓存中,这些连接可用于所有客户端。因此,如果缓存中有经过身份验证的连接,碰巧使用此连接的无关客户端将能够绕过身份验证。