Nginx Https 跳转配置问题

2015-07-09 11:15:07 +08:00
 iyaozhen

我的需求:
http://iyaozhen.com -> https://iyaozhen.com
http://www.iyaozhen.com -> https://iyaozhen.com
这两个已经实现:

server {
        listen 80;
        listen [::]:80;

        server_name iyaozhen.com www.iyaozhen.com;

        return 301 https://iyaozhen.com$request_uri;
}

我还需要 https://www.iyaozhen.com -> https://iyaozhen.com
按理我是需要这样配置:

server {
        listen 443 ssl;
        listen [::]:443 ssl;

        server_name www.iyaozhen.com;

        return 301 https://iyaozhen.com$request_uri;
}

但我发现这样配置的话所以网站都不能访问了,而且我不配置的话同样能跳转过去(不知道为什么)。
这都是小问题,更大的问题是 https://demo.iyaozhen.com/ (或者其它有设置 DNS 解析,但没在 Nginx 里面设置 server 的域名)能访问到 iyaozhen.com 的内容(https 那里有红x)。

# prevent processing requests with undefined server names
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        server_name _;

        return 444;
}

主域 iyaozhen.com 的配置:

server {
        listen 443 ssl spdy;
        listen [::]:443 ssl spdy;

        # SSL configuration
        # don’t use SSLv3 ref: POODLE
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        # 省略其它的设置……
        ssl_prefer_server_ciphers on;
        ssl_session_timeout 1d;
        ssl_session_cache shared:SSL:10m;
        # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
        add_header Strict-Transport-Security max-age=15768000;

        server_name iyaozhen.com;
}

我发现问题的根源是简单的 listen 443 然后做跳转是不行的,必须要配置证书啥的。这怎么办?

10079 次点击
所在节点    NGINX
36 条回复
FifiLyu
2015-07-09 11:24:45 +08:00
一个IP地址正常情况是只支持一个 https vhost,所以你访问 demo 访问到了 iyaozhen.com。这个 demo 有红叉是因为访问的域名和ssl证书认证的域名不一致。访问是demo.iyaozhen.com,证书是 www.iyaozhen.com 以及 iyaozhen.com

如果要一个IP支持多个 https vhost,请开启 nginx 的 SNI 支持。但是,不建议这样做。因为可能访问https 都会出现红叉。
iyaozhen
2015-07-09 11:31:04 +08:00
@FifiLyu 嗯,这个我知道。我是单域名证书。我不是要 https://demo.iyaozhen.com/ 能访问到我的主域博客。而是 https://demo.iyaozhen.com/ 不能访问,http://demo.iyaozhen.com/ 能正常访问其本来的站点。
ryd994
2015-07-09 11:53:37 +08:00
要http正常的话只要正确填写server_name即可
https的怎么都不会正常
geekzu
2015-07-09 11:58:26 +08:00
只要你想让443 能通过https访问,必须要配置证书
geekzu
2015-07-09 11:58:41 +08:00
即使是只做跳转
iyaozhen
2015-07-09 13:01:03 +08:00
@geekzu 看来是这样。跳转这个是个小问题。但 https://demo.iyaozhen.com/ (或者其它有设置 DNS 解析,但没在 Nginx 里面设置 server 的域名)能访问到 iyaozhen.com 的内容(https 那里有红x)。这个怎么解决。
geekzu
2015-07-09 13:11:10 +08:00
@iyaozhen 这个因为是共享ip没法解决,除非你给 demo.iyaozhen.com 也配置上ssl
chon
2015-07-09 13:15:47 +08:00
@iyaozhen https连接建立是在判断server_name之前的,所以所有的https连接都会指向 iyaozhen.com
可以加一行判断host的:
if ($host !~* ^iyaozhen.com$ ) {
return 404;
}
不知道有没有更好的方案。
iyaozhen
2015-07-09 13:17:06 +08:00
@geekzu 明白了,我没有许可的证书(泛域名证书)再设置 443 端口的 default_server。单域名证书,有点略坑呀。
iyaozhen
2015-07-09 13:18:06 +08:00
@chon 嗯,谢谢。明白了。
imlonghao
2015-07-09 13:44:11 +08:00
没人用 HSTS 做 http 跳转 https 的么?
iyaozhen
2015-07-09 13:55:12 +08:00
@imlonghao 有啊,配置里面不是写了嘛。不过 IE9 等不支持 HSTS,还是要再加个 server 做跳转。
alect
2015-07-09 14:35:54 +08:00
lz自己把自己坑了,申请证书的时候加上不要用裸域名而是带www的,否则有些直接给你签发的证书就只有裸域名了
dallaslu
2015-07-09 14:47:36 +08:00
配一个 80 端口的 server:
server_name iyaozhen.com www.iyaozhen.com;
if ($host ~ ^(www\.)?iyaozhen\.com) {
rewrite ^(.*) https://iyaozhen.com$1 permanent;
}

只配一个 443 端口的 server:
server_name iyaozhen.com www.iyaozhen.com;
if ($host ~ ^www\.iyaozhen\.com) {
rewrite ^(.*) https://iyaozhen.com$1 permanent;
}
if ($host !~ ^(www\.)?iyaozhen\.com) {
rewrite ^(.*) http://$host$1 permanent;
}

(未经测试)
pupboss
2015-07-09 14:50:09 +08:00
@imlonghao HSTS 在 http 下并没卵用,已经试过了
pupboss
2015-07-09 14:52:17 +08:00
server {

listen 80;
server_name pupboss.com;
return 301 https://$server_name$request_uri;
}

server {

listen 80;
listen 443 ssl;
server_name www.pupboss.com;
rewrite ^/(.*)$ https://pupboss.com/$1 permanent;
}
iyaozhen
2015-07-09 15:02:40 +08:00
@dallaslu 谢谢,你这种方式应该也可以。目前我是这样解决的:
server {
listen 80;
listen [::]:80;

listen 443 ssl;
listen [::]:443 ssl;

server_name www.iyaozhen.com;

return 301 https://iyaozhen.com$request_uri;
}

按理说 www.iyaozhen.com 是没有配置证书的,只监听 443 端口,不过实际测试发现 https://www.iyaozhen.com 能跳转到 https://iyaozhen.com

顺带请教个问题 !~ 是 !=,~ 是 = 吗?这是什么语法?
iyaozhen
2015-07-09 15:08:27 +08:00
@pupboss 好方法,我就是像你这样配置的。

是的,HSTS 在只访问 http 时是没用的。
HSTS 的作用应该是访问了一次 https 的网站后,浏览器检测到了这个协议,当你以后输入域名时(即使手动输入 http://)会跳转到对应的 https 网站。
iyaozhen
2015-07-09 15:10:21 +08:00
@alect 应该也是给我签了带 www 的。https://www.ssllabs.com/ssltest/index.html 检测结果:
Common names iyaozhen.com
Alternative names iyaozhen.com www.iyaozhen.com
Prefix handling Both (with and without WWW)
FifiLyu
2015-07-09 15:22:57 +08:00
@iyaozhen 因为你只有一个 ssl 站点,任何域名解析到你的IP地址。都能通过https://test.abc.com 访问到 https://iyaozhen.com 的内容。这个你是关不掉的。

变通的做法是,开启 SNI 支持。然后,新建一个 nginx 的 ssl 站点,root指向一个目录,目录下没有任何东西。不过,这样肯定不好。

如果是用的 Linux ,使用 iptables 做一个域名白名单防火墙,443端口只允许 iyaozhen 域名访问。
白名单设置参考: https://github.com/fifilyu/module-http-whitelist 中的 “代替方案”

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/204420

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX