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

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

我有一个 nginx 反向代理,我正在尝试让一个带有登录功能的 IIS 网站在其后面工作。我发现这个问题被问过好几次了,但每个答案似乎都不一样,而且有些问题与我遇到的问题有点不同。

使用我当前的配置,我可以登录,但出现 401 错误,并且它一直要求输入凭据。

我当前的配置:

/etc/nginx/站点可用/默认

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 是我的客户端 FYI。

这些日志来自我访问网站、获取登录提示、尝试登录一次(未成功)以及退出登录提示。

/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

服务器2.mydomain.com

阿帕奇2

Ubuntu 14.04 服务器


EDIT3-也许这有效,但我做错了,....也许不行

帖子中,Fizz 写的答案。

我尝试过下面这个

/etc/nginx/站点可用/默认

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.log27 号线有问题

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

我肯定是用 ngx_stream_ssl_module 编译的,因为当我执行nginx -V我明白了configure arguments: --with-stream

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

答案1

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

NTLM 身份验证对连接进行身份验证,而不是对请求进行身份验证,这在某种程度上与 HTTP 协议相矛盾,因为 HTTP 协议应该是无状态的。因此,它通常不能通过代理(包括 nginx)工作。

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

  • 使用流代理nginx 1.9.x 中提供此功能。这会将客户端的连接映射到上游服务器,这样 NTLM 身份验证就可以正常工作。

  • 使用NTLM 目录商业 nginx 版本中提供的功能。

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

答案2

我在使用反向代理配置 YouTrack 服务器时遇到了类似的错误。

您可能想尝试添加以下行:

proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

来自以下链接:

如果 Nginx 要在将 SSL/TLS 连接转发到 YouTrack 之前终止它们,那么以下标头也是必要的:

proxy_set_header        X-Forwarded-Proto https;

这是帮助我找到解决方案的链接:https://confluence.jetbrains.com/display/YTD6/YouTrack+JAR+in+Nginx+Web+Server#

相关内容