Nginx Https 跳转配置问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iyaozhen
V2EX    NGINX

Nginx Https 跳转配置问题

  •  2
     
  •   iyaozhen
    iyaozhen 2015-07-09 11:15:07 +08:00 10549 次点击
    这是一个创建于 3746 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我的需求:
    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 然后做跳转是不行的,必须要配置证书啥的。这怎么办?

    36 条回复    2015-07-09 23:58:57 +08:00
    mN71eOOprFyMsnPx
        1
    mN71eOOprFyMsnPx  
       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 都会出现红叉。
    iyaozhen
        2
    iyaozhen  
    OP
       2015-07-09 11:31:04 +08:00
    @FifiLyu 嗯,这个我知道。我是单域名证书。我不是要 https://demo.iyaozhen.com/ 能访问到我的主域博客。而是 https://demo.iyaozhen.com/ 不能访问,http://demo.iyaozhen.com/ 能正常访问其本来的站点。
    ryd994
        3
    ryd994  
       2015-07-09 11:53:37 +08:00 via Android   1
    要http正常的话只要正确填写server_name即可
    https的怎么都不会正常
    geekzu
        4
    geekzu  
       2015-07-09 11:58:26 +08:00 via Android   1
    只要你想让443 能通过https访问,必须要配置证书
    geekzu
        5
    geekzu  
       2015-07-09 11:58:41 +08:00 via Android
    即使是只做跳转
    iyaozhen
        6
    iyaozhen  
    OP
       2015-07-09 13:01:03 +08:00
    @geekzu 看来是这样。跳转这个是个小问题。但 https://demo.iyaozhen.com/ (或者其它有设置 DNS 解析,但没在 Nginx 里面设置 server 的域名)能访问到 iyaozhen.com 的内容(https 那里有红x)。这个怎么解决。
    geekzu
        7
    geekzu  
       2015-07-09 13:11:10 +08:00 via Android   1
    @iyaozhen 这个因为是共享ip没法解决,除非你给 demo.iyaozhen.com 也配置上ssl
    chon
        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;
    }
    不知道有没有更好的方案。
    iyaozhen
        9
    iyaozhen  
    OP
       2015-07-09 13:17:06 +08:00
    @geekzu 明白了,我没有许可的证书(泛域名证书)再设置 443 端口的 default_server。单域名证书,有点略坑呀。
    tr>
    iyaozhen
        10
    iyaozhen  
    OP
       2015-07-09 13:18:06 +08:00
    @chon 嗯,谢谢。明白了。
    imlonghao
        11
    imlonghao  
       2015-07-09 13:44:11 +08:00 via Android
    没人用 HSTS 做 http 跳转 https 的么?
    iyaozhen
        12
    iyaozhen  
    OP
       2015-07-09 13:55:12 +08:00
    @imlonghao 有啊,配置里面不是写了嘛。不过 IE9 等不支持 HSTS,还是要再加个 server 做跳转。
    alect
        13
    alect  
       2015-07-09 14:35:54 +08:00   1
    lz自己把自己坑了,申请证书的时候加上不要用裸域名而是带www的,否则有些直接给你签发的证书就只有裸域名了
    dallaslu
        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;
    }

    (未经测试)
    pupboss
        15
    pupboss  
       2015-07-09 14:50:09 +08:00   1
    @imlonghao HSTS 在 http 下并没卵用,已经试过了
    pupboss
        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;
    }
    iyaozhen
        17
    iyaozhen  
    OP
       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
        18
    iyaozhen  
    OP
       2015-07-09 15:08:27 +08:00
    @pupboss 好方法,我就是像你这样配置的。

    是的,HSTS 在只访问 http 时是没用的。
    HSTS 的作用应该是访问了一次 https 的网站后,浏览器检测到了这个协议,当你以后输入域名时(即使手动输入 http://)会跳转到对应的 https 网站。
    iyaozhen
        19
    iyaozhen  
    OP
       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)
    mN71eOOprFyMsnPx
        20
    mN71eOOprFyMsnPx  
       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 中的 “代替方案”
    iyaozhen
        21
    iyaozhen  
    OP
       2015-07-09 15:28:55 +08:00
    @FifiLyu 嗯,谢谢。目前采用的是更粗暴的方法。

    iyaozhen.com 的 server 设置为 default_server 然后在里面做判断:
    if ($host != iyaozhen.com) {
    return 444;
    }
    mN71eOOprFyMsnPx
        22
    mN71eOOprFyMsnPx  
       2015-07-09 15:30:20 +08:00
    @iyaozhen 233 确实粗暴。
    iyaozhen
        23
    iyaozhen  
    OP
       2015-07-09 15:37:43 +08:00
    @pupboss 有个小小的疑问。像你那样配置,按理说 www.iyaozhen.com 是没有配置证书的,只监听 443 端口,不过实际测试发现 https://www.iyaozhen.com 能跳转到 https://iyaozhen.com。 这是为什么?
    alect
        24
    alect  
       2015-07-09 16:52:47 +08:00   1
    倒是对lz已经成功实现的一个功能提一个建议
    lz想把http请求都转换为https请求,个人不建议用301,而是用hsts实现
    然后就只要考虑把www请求转发到裸域就行了
    pupboss
        25
    pupboss  
       2015-07-09 18:24:35 +08:00   1
    @iyaozhen 我觉得这个类似脚本语言,一行一行运行,上面没错误就不报错,如果上面写了证书信息,而且是错误的,我觉得会报错,直接给 rewrite 掉,差不多就相当于程序里面的 return 了,下面再错误都没关系
    iyaozhen
        26
    iyaozhen  
    OP
       2015-07-09 18:55:12 +08:00 via Android
    @alect 嗯,我看过说不建议用 301,但我不太明白,可否解释下。我觉得这表示我的资源都是在 https 上,感觉没问题呀。

    hsts 有些浏览器不支持。其它原因在18楼有说明。
    iyaozhen
        27
    iyaozhen  
    OP
       2015-07-09 19:02:46 +08:00 via Android
    @pupboss 嗯,好像是的。而且我域名证书带 www 和不带的都可以。或者说是 Nginx 自己智能做了处理。比如说我访问 https://xxx.iyaozhen.com 用的是主域的证书,显示连接(算法)没问题,但域名没有公审记录。
    pupboss
        28
    pupboss  
       2015-07-09 19:08:09 +08:00
    @iyaozhen 哈哈,公审记录我也不知道是啥,和 Nginx 设置没多大问题,我猜有可能是 EV 证书之类的,绿色地址框,因为 Github,cat.net ,是 EV 证书,没有 '但域名没有公审记录'
    iyaozhen
        29
    iyaozhen  
    OP
       2015-07-09 19:18:47 +08:00 via Android
    @pupboss 额,我说错了,是不受信任。没有公审记录是你说的那样,另外一回事了。
    pupboss
        30
    pupboss  
       2015-07-09 19:40:27 +08:00 via iPhone
    @iyaozhen 不信任一般是证书链不对,浏览器肯定信任根的,中间的链你要手动添加到你域名证书后面
    dallaslu
        31
    dallaslu  
       2015-07-09 21:36:19 +08:00   1
    @iyaozhen ~ 是正则匹配的意思,!~ 就是不匹配后面的正则。上面有位V友的回复提到 !~*,其中*的意思是不区分大小写。
    dallaslu
        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 要好。

    以上是个人理解。
    dallaslu
        33
    dallaslu  
       2015-07-09 21:47:16 +08:00
    @iyaozhen 没有做配置的情况下, www.iyaozhen.com 跳转到 iyaozhen.com,可能是因为 WordPress 的默认功能。
    iyaozhen
        34
    iyaozhen  
    OP
       2015-07-09 2:33:09 +08:00
    @dallaslu 原来 Nginx 正则语法是这样的。谢谢

    “顺带把之前从 https 中获取的 cookie 发出去了,这时就可能会被嗅探到。”这个倒是没有考虑到。不过我 301 和 HSTS 都配置了。
    caola
        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; }

    }
    iyaozhen
        36
    iyaozhen  
    OP
       2015-07-09 23:58:57 +08:00
    @caola 嗯,你这样也是好办法,在 server 配置内部做判断,然后跳转。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2662 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 35ms UTC 15:09 PVG 23:09 LAX 08:09 JFK 11:09
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86