我的需求:
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 然后做跳转是不行的,必须要配置证书啥的。这怎么办?
1
FifiLyu 2015-07-09 11:24:45 +08:00 1
一个IP地址正常情况是只支持一个 https vhost,所以你访问 demo 访问到了 iyaozhen.com。这个 demo 有红叉是因为访问的域名和ssl证书认证的域名不一致。访问是demo.iyaozhen.com,证书是 www.iyaozhen.com 以及 iyaozhen.com。
如果要一个IP支持多个 https vhost,请开启 nginx 的 SNI 支持。但是,不建议这样做。因为可能访问https 都会出现红叉。 |
2
iyaozhen OP @FifiLyu 嗯,这个我知道。我是单域名证书。我不是要 https://demo.iyaozhen.com/ 能访问到我的主域博客。而是 https://demo.iyaozhen.com/ 不能访问,http://demo.iyaozhen.com/ 能正常访问其本来的站点。
|
3
ryd994 2015-07-09 11:53:37 +08:00 via Android 1
要http正常的话只要正确填写server_name即可
https的怎么都不会正常 |
4
geekzu 2015-07-09 11:58:26 +08:00 via Android 1
只要你想让443 能通过https访问,必须要配置证书
|
5
geekzu 2015-07-09 11:58:41 +08:00 via Android
即使是只做跳转
|
6
iyaozhen OP @geekzu 看来是这样。跳转这个是个小问题。但 https://demo.iyaozhen.com/ (或者其它有设置 DNS 解析,但没在 Nginx 里面设置 server 的域名)能访问到 iyaozhen.com 的内容(https 那里有红x)。这个怎么解决。
|
7
geekzu 2015-07-09 13:11:10 +08:00 via Android 1
@iyaozhen 这个因为是共享ip没法解决,除非你给 demo.iyaozhen.com 也配置上ssl
|
8
chon 2015-07-09 13:15:47 +08:00 1
@iyaozhen https连接建立是在判断server_name之前的,所以所有的https连接都会指向 iyaozhen.com 。
可以加一行判断host的: if ($host !~* ^iyaozhen.com$ ) { return 404; } 不知道有没有更好的方案。 |
9
iyaozhen OP @geekzu 明白了,我没有许可的证书(泛域名证书)再设置 443 端口的 default_server。单域名证书,有点略坑呀。
|
11
imlonghao 2015-07-09 13:44:11 +08:00 via Android
没人用 HSTS 做 http 跳转 https 的么?
|
12
iyaozhen OP @imlonghao 有啊,配置里面不是写了嘛。不过 IE9 等不支持 HSTS,还是要再加个 server 做跳转。
|
13
alect 2015-07-09 14:35:54 +08:00 1
lz自己把自己坑了,申请证书的时候加上不要用裸域名而是带www的,否则有些直接给你签发的证书就只有裸域名了
|
14
dallaslu 2015-07-09 14:47:36 +08:00 1
配一个 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; } (未经测试) |
16
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; } |
17
iyaozhen OP @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。 顺带请教个问题 !~ 是 !=,~ 是 = 吗?这是什么语法? |
18
iyaozhen OP @pupboss 好方法,我就是像你这样配置的。
是的,HSTS 在只访问 http 时是没用的。 HSTS 的作用应该是访问了一次 https 的网站后,浏览器检测到了这个协议,当你以后输入域名时(即使手动输入 http://)会跳转到对应的 https 网站。 |
19
iyaozhen OP @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) |
20
FifiLyu 2015-07-09 15:22:57 +08:00 1
@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 中的 “代替方案” |
21
iyaozhen OP @FifiLyu 嗯,谢谢。目前采用的是更粗暴的方法。
把 iyaozhen.com 的 server 设置为 default_server 然后在里面做判断: if ($host != iyaozhen.com) { return 444; } |
23
iyaozhen OP @pupboss 有个小小的疑问。像你那样配置,按理说 www.iyaozhen.com 是没有配置证书的,只监听 443 端口,不过实际测试发现 https://www.iyaozhen.com 能跳转到 https://iyaozhen.com。 这是为什么?
|
24
alect 2015-07-09 16:52:47 +08:00 1
倒是对lz已经成功实现的一个功能提一个建议
lz想把http请求都转换为https请求,个人不建议用301,而是用hsts实现 然后就只要考虑把www请求转发到裸域就行了 |
25
pupboss 2015-07-09 18:24:35 +08:00 1
@iyaozhen 我觉得这个类似脚本语言,一行一行运行,上面没错误就不报错,如果上面写了证书信息,而且是错误的,我觉得会报错,直接给 rewrite 掉,差不多就相当于程序里面的 return 了,下面再错误都没关系
|
26
iyaozhen OP |
27
iyaozhen OP @pupboss 嗯,好像是的。而且我域名证书带 www 和不带的都可以。或者说是 Nginx 自己智能做了处理。比如说我访问 https://xxx.iyaozhen.com 用的是主域的证书,显示连接(算法)没问题,但域名没有公审记录。
|
28
pupboss 2015-07-09 19:08:09 +08:00
|
31
dallaslu 2015-07-09 21:36:19 +08:00 1
@iyaozhen ~ 是正则匹配的意思,!~ 就是不匹配后面的正则。上面有位V友的回复提到 !~*,其中*的意思是不区分大小写。
|
32
dallaslu 2015-07-09 21:41:57 +08:00
@iyaozhen 如果 http 协议通过 301 跳转到 https,那么浏览器会记住这个选择,以后再访问 http://iyaozhen.com 时,就会直接访问 https://iyaozhen.com 而不再经过服务器跳转,这里并没有任何问题。
问题在于,如果初次通过 https 访问,但是没有设置HSTS;然后再访问 http 链接,浏览器就会正常执行一次 http 请求,顺带把之前从 https 中获取的 cookie 发出去了,这时就可能会被嗅探到。 所以 HSTS 要比单纯的 301 要好。 以上是个人理解。 |
33
dallaslu 2015-07-09 21:47:16 +08:00
|
34
iyaozhen OP @dallaslu 原来 Nginx 正则语法是这样的。谢谢
“顺带把之前从 https 中获取的 cookie 发出去了,这时就可能会被嗅探到。”——这个倒是没有考虑到。不过我 301 和 HSTS 都配置了。 |
35
caola 2015-07-09 23:21:47 +08:00 1
为什么要把 80 的 443 端口的分开写两次呢?
下面是我自己的主要配置,并开启了SPDY(www的跳转到根域名) ================================ server { listen 80; listen 443 ssl spdy; server_name cao.la www.cao.la; index index.php index.html; root /home/wwwroot/caola; ssl_certificate cert/cao.la.crt; ssl_certificate_key cert/cao.la.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #允许的协议 ssl_ciphers AES128:AES256:GCM:!DH:!RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS; #加密算法 ssl_session_timeout 10m; #客户端会话缓存时间 ssl_session_cache builtin:1000 shared:SSL:10m; #SSL会话缓存类型和大小 ssl_prefer_server_ciphers on; #优化SSL,服务器密码优先于客户端 ssl_buffer_size 1400; # 1400 bytes to fit in one MTU spdy_headers_comp 6; #SPDY报头压缩级别[0-9] add_header X-Frame-Options SAMEORIGIN; #拒绝被嵌入框架(iframe…) add_header Strict-Transport-Security "max-age=8640000; includeSubDomains"; #子域没有全部部署https请去掉includeSubDomains add_header X-Content-Type-Options: nosniff; #禁用浏览器的类型猜测 if ($ssl_protocol = "") { return 301 https://$server_name$request_uri; } if ($host != 'cao.la' ) { return 301 https://cao.la$request_uri; } } |