我正在尝试让 nginx 反向代理设置工作。我设置了两个 Web 服务器,一个使用 nginx,另一个使用 apache2。目前我无法仅使用 nginx 服务器使其工作,所以这就是我现在正在尝试的全部,但我补充说我最终会尝试使用两个,以防影响设置。
我在这种设置下有四台机器。
1. 客户端机器
192.168.0.5
Ubuntu 14.04 桌面
2. 反向代理服务器
192.168.0.10
nginx 1.4.6
Ubuntu 14.04 服务器
3.服务器1
192.168.0.15
服务器1.mydomain.com
nginx 1.4.6
Ubuntu 14.04 服务器
4.服务器 2
192.168.0.20
服务器2.mydomain.com
阿帕奇2
Ubuntu 14.04 服务器
在我的客户端机器上,我已将 hosts 文件设置为指向每个 Web 服务器的反向代理服务器,如下所示
/etc/hosts在客户端 192.168.0.5 127.0.0.1 localhost 192.168.0.10 server1.mydomain.com 192.168.0.10 server2.mydomain.com
我有 server1 和 server2 的 SSL 证书,已将其放在反向代理服务器 (192.168.0.10) 上。我们将它们称为 server1.crt、server1.key,以及 server2.crt、server2.key。
我相信我必须进行这样的设置,并且证书的工作方式如下:
client(192.168.0.5) ---https---> reverseProxy(192.168.0.10 holds ssl certs) ---http---> server1 or server2
我现在两台服务器都运行正常,使用 http,我只需要修复 192.168.0.10 上的 nginx 反向代理设置。
这是我尝试过的方法,但它无法正确重定向。再次重申,我希望与反向代理服务器建立 https 连接,然后在反向代理和服务器之间建立 http 连接。
/etc/nginx/nginx.conf
user www-data;
worker_processes 4;
pid /run/nginx.pid;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
##
# nginx-naxsi config
##
# Uncomment it if you installed nginx-naxsi
##
#include /etc/nginx/naxsi_core.rules;
##
# nginx-passenger config
##
# Uncomment it if you installed nginx-passenger
##
#passenger_root /usr;
#passenger_ruby /usr/bin/ruby;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
/etc/nginx/站点可用/默认
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /usr/share/nginx/html;
index index.html index.htm;
# Make site accessible from http://localhost/
server_name localhost;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
# Uncomment to enable naxsi on this location
# include /etc/nginx/naxsi.rules
}
server {
listen 443;
server_name server1.mydomain.com;
ssl on;
ssl_certificate /usr/local/nginx/conf/server1.crt;
ssl_certificate_key /usr/local/nginx/conf/server1.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.15:80;
proxy_set_header Host server1;
proxy_redirect http:// https://;
}
}
我假设我的/etc/nginx/sites-available/default
文件中存在错误,但我已经阅读了几个教程,这似乎非常接近。此设置显然只尝试使用服务器 1,而忽略了服务器 2,但我认为如果我能让一个服务器工作,我就可以添加任意数量的其他服务器。我发现了类似的问题,例如这一个,但我仍然无法让这个配置在单个服务器上工作。
当前情况
目前,当我访问 server1.mydomain.com 时,我获得了标准“欢迎使用 nginx!”来自反向代理服务器 (192.168.0.10) 的页面。没有进行转发。
我接近了吗?提前谢谢
编辑1
在尝试了 Capile 发布的解决方案后,我遇到了另一个问题(对于比我更有网络知识的人来说,这可能是意料之中的)。
当我将/etc/nginx/sites-available/default
文件更改为如下内容时:
/etc/nginx/站点可用/默认(关于反向代理)
server {
listen 80 default_server;
listen 443 ssl default_server;
server_name server1.mydomain.com;
ssl on;
ssl_certificate /usr/local/nginx/conf/server1.com.crt;
ssl_certificate_key /usr/local/nginx/conf/server1.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.15:80;
proxy_set_header Host server1;
proxy_redirect http:// https://;
}
}
通过此配置,我得到了
400 错误请求
普通 HTTP 请求已发送到 HTTPS 端口
我想也许我应该尝试一下https://server1.mydomain.com
,但结果却并非如此。
另外,我不介意对两个服务器使用相同的 SSL 证书。我认为这不会成为问题。
编辑2
首先,感谢您的所有帮助。
我删除了ssl on;
Capile 推荐的那一行,并将该proxy_redirect http:// https://;
行更改为proxy_redirect http:// $scheme://;
Richard Smith 推荐的那一行。
这修复了 http 流量的错误请求。所以现在,如果我去http://server1.mydomain.com我已成功重定向到该网站(耶!)
如果我尝试去https://server1.mydomain.com我也被重定向了,这很好,但我收到了无法连接错误。如果反向代理将 http 流量转发到 http,将 https 流量转发到 https,则这种情况是有道理的,因为后端服务器没有 https 配置。
我的目标是http://server1.domain.com它使用 https 连接到反向代理,然后使用 http 转发到后端服务器。这似乎没有发生...看起来它只是转发它而从未使用 https。
另一方面,如果我去https://server1.domain.com它应该使用 https 连接到反向代理,然后使用 http 转发到后端服务器。
所以我从来不希望从客户端到反向代理服务器建立 http 连接。
不过,curl 的表现正如预期的那样。当我 curl http 或 https 站点时,我得到了以下信息:
curl -ihttps://server1.mydomain.com或者curl -ihttp://server1.mydomain.com
HTTP/1.1 302 Found
Server: nginx/1.4.6 (Ubuntu)
Date: Thu, 21 Jan 2016 16:34:29 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 92
Connection: keep-alive
Cache-Control: no-cache
Location: http://test1/users/sign_in
Set-Cookie: session=336e109ad711; path=/; expires=Thu, 28 Jan 2016 16:34:36 -0000; HttpOnly
Status: 302 Found
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: ad65f-f6ds204-9fs8d-bdsdfa43-df5583266sdf87
X-Runtime: 0.005358
X-Xss-Protection: 1; mode=block
<html><body>You are being <a href="http://test1/users/sign_in">redirected</a>.</body></html>
因此,对于任何类型的连接,重定向肯定会发生,但我不认为客户端和反向代理服务器之间的 https 连接的 SSL 证书被使用过。
答案1
你已经接近了,但没有为 http 配置反向代理,只为 https 配置了反向代理(在上面的设置中)——因此它应该显示来自文档根目录的默认内容。第一个服务器也缺少结尾}
。
您可以在同一个块中配置 http 和 https,只需使用ssl
listen 指令中的关键字(在 ssl 端口下,因此无需设置指令ssl on
):
server {
listen 80 default_server;
listen 443 ssl default_server;
...
ssl_certificate /usr/local/nginx/conf/server1.crt;
ssl_certificate_key /usr/local/nginx/conf/server1.key;
ssl_session_cache shared:SSL:10m;
...
我必须提醒,在同一个 IP 中使用两个不同的 SSL 证书有一定的限制和复杂性 — 这是因为它需要 HTTP 重新协商(因为在请求正确的主机之前需要使用证书加密请求),所以您可能需要按server
块分隔证书。为此,请使用更具体的 IP listen
:
server {
listen 192.168.0.10:443 ssl; # for server1.mydomain.com
...
server {
listen 192.168.0.11:443 ssl; # for server2.mydomain.com
...
我还建议您使用Mozilla SSL 配置生成器了解 SSL 安全的最佳实践。
编辑1
要避免 400 错误,只需删除该指令ssl on;
并重新加载。它导致 http 流量需要 SSL — 您已在该行中指示使用 ssl:listen 443
ssl
default_server;
(这意味着在这个端口上打开 ssl)。
其余配置都很好,但根据您的服务器响应,您可能需要调整代理设置。
首先,检查旋转是在客户端还是服务器端:使用以下方式访问它卷曲或者在您的浏览器上打开 Web 开发人员工具并检查网络:如果您的浏览器被重定向,您可能需要调整proxy_redirect
甚至在服务器响应中进行一些字符串替换。
使用 cURL 按照以下方式检查:
curl -i http://server1.mydomain.com
如果您Location:
在响应中看到标头,则需要微调代理设置(这取决于响应)。例如,您可能以 https 形式访问它,然后您的代理转发为 http,而您的后端服务器应用程序重定向到 https(但当响应通过代理时,它会返回到 http 到浏览器)。有几种方法可以修复它,通过使用proxy_set_header
甚至调整您的后端服务器。
例如你可以使用:
proxy_set_header X-Forwarded-Proto $scheme;
但是您的后端 http 服务器或应用程序需要正确理解这一点。
或者,如果没有重定向,但也没有响应(或者请求超时 30 秒后没有网关响应),请检查您的后端服务器是否正确响应代理服务器。
还请注意,您不需要在后端使用 http 服务器,您可以直接使用 FastCGI 服务器 — — 这有时会减少故障。
编辑2
根据 cURL 响应,我看到配置按预期工作 - 后端服务器响应要求您登录。如果 SSL 证书不起作用,您将无法登录curl -i https://server1.mydomain.com
。
前端(代理)和后端之间的流量仅通过 http 进行(参见proxy_pass
指令),这通常也是预期的(另一种加密可能会增加不必要的开销)。
现在,如果你只想使用 https,你有两个选择:要么在你的后端进行配置(这样它会将你转发到https://test1/users/sign_in) 或者对 nginx 使用不同的设置,剥离 http:80 服务器,让其将所有内容重定向到 https:443。类似这样的设置(务必listen 80
从下一个服务器块中删除):
server {
listen 80 default;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
...
答案2
使用新的 (EDIT1) 配置,任何使用 http(而不是 https)访问机器 #2 的行为都将被代理。这消除了原来的“欢迎使用 nginx!”副作用,该副作用(可能)是由重定向到 http 方案引起的。
接下来,我认为问题的根源是机器#3(真实服务器 1)生成了一个重定向,当它返回到客户端时,该重定向没有被正确映射。
您可能需要检查机器 #2 和机器 #3 上的访问日志,以充分了解交互。您可能需要调整日志格式了解每次交互使用哪种方案(http 与 https)。
您可能需要暂时禁用proxy_redirect
,以便您可以使用客户端的开发人员工具来准确了解机器#3 在其 http 3xx 响应中发出了哪些 URL。
由于您现在正在代理这两种方案,因此您的proxy_redirect
指令对于 EDIT1 配置来说是错误的,因此这可能更合适:
proxy_redirect http:// $scheme://
话虽如此,但更具体一点proxy_redirect
可能更合适。文档状态,您可以使用多个proxy_redirect rules. I am not an expert on
proxy_redirect` 规则,但最终可能会得到如下结果:
proxy_pass http://192.168.0.15;
proxy_set_header Host server1;
proxy_redirect http://192.168.0.15 $scheme://
proxy_redirect http://server1 $scheme://