我有一个 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 端将身份验证更改为“基本”。如果出于某种原因这不可行,其他可能性包括:
请注意,有一些建议使用带有 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#