我正在尝试将http://www.example.comredirect到Nginx。 只有非www版本安装了证书。 我有两个301redirect规则:
1)从http://example.com到
server { listen 80; listen 443 ssl; server_name example.com; if ($scheme = http) { return 301 https://$server_name$request_uri; } }
2)从http://WWW.example.com到http://example.com
server { listen 80; server_name www.example.com; return 301 $scheme://example.com$request_uri; }
当我从terminal通过curl请求www.example.com时,我看到:
HTTP/1.1 301 Moved Permanently Location: http://example.com/
这是我期望发生的事情。 但是,当我从浏览器执行相同的操作时,它会将我redirect到并引发证书错误。
我通过将证书添加到www版本来修复它,但是我想知道为什么没有它,它不能正常工作? 为什么curl给了我不同的结果?
以防万一我使用的SSL参数:
ssl_session_cache shared:SSL:50m; ssl_session_timeout 5m; ssl_dhparam /etc/nginx/pki/dhparam.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; resolver 8.8.8.8; ssl_stapling on; add_header Strict-Transport-Security "max-age=31536000";
对于清除的讨论,我build议你将所有的nginx逻辑分成主节点(example.confconfiguration)和“卫星”(www_example.conf等)。 卫星不应该有一个巨大的逻辑。
如果在您的主节点中,您将所有HTTPstream量redirect到HTTPS,我build议在卫星上也这样做 – 速度要快一些:
www_example.conf
server { listen 80; server_name www.example.com; return 301 https://example.com$request_uri; }
我已经将$scheme更改为https 。
那么,如果我正确地理解你 – 你有两个问题。
1. CURL不遵循您的redirect。 默认情况下,他不这样做,你应该通过-L :
curl "http://www.example.com" -L
2.另一个问题在于nginx如何parsingSSL连接。 SSL不检查“服务器configuration”层。 在服务器接收到连接数据包并开始握手操作时,它正在检查一个更长的时间,因此,在此检查过程中,您的带server_name的configuration不会使用。
当你的服务器收到来自SSL握手的连接时,他将检索正在侦听当前ip:port第一个configuration,并尝试与ssl key,chain&certificate握手。
摘要:
如果您想通过“ https://www.example.com ”并从“ https://example.com ”获取答案,则应该同时拥有SSLconfiguration的服务器。
如果您想通过“ http://www.example.com ”并从“ https://example.com ”获取答案,您应该确保只在example.com上进行握手,而不是在进入该域之前。 你的服务器如何处理你可以通过wget输出检查的“解决步骤” – 这是一个最简单的方法。
在这里你可以find我的configuration,我用来testing你的问题:
server { listen 80; listen 443 ssl; server_name example.com; ssl on; ssl_certificate /path/to.crt; ssl_certificate_key /path/to.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4; ssl_prefer_server_ciphers on; if ($scheme = http) { return 301 https://$server_name$request_uri; } location / { add_header Content-type text/plain; return 200 "OK"; } } server { listen 80; server_name www.example.com; return 301 https://example.com$request_uri; }
为了进行debugging,我添加了return 200 "OK" location部分。
然后在CMD中:
$ curl "http://www.example.com" -L OK $ wget "http://www.example.com" -O /dev/null --2016-11-24 15:54:33-- http://www.example.com/ Resolving www.example.com (www.example.com)... 127.0.0.1 Connecting to www.example.com (www.example.com)|127.0.0.1|:80... connected. HTTP request sent, awaiting response... 301 Moved Permanently Location: https://example.com/ [following] --2016-11-24 15:54:33-- https://example.com/ Resolving example.com (example.com)... 127.0.0.1 Connecting to example.com (example.com)|127.0.0.1|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 2 [application/octet-stream]
在上次输出中,您可以发现“解决步骤”能正常工作。
在浏览器中也可以正常工作。
如果www.example.com网站以前曾经使用Strict-Transport-Security标题(或者example.com上的includeSubdomains选项),那么浏览器将会记住(很长一段时间 – 例如31536000秒),并且将始终提升http在访问www.example.com之前连接到https 。