V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
dx5594206
V2EX  ›  NGINX

请问 nginx 如何给单独一个子域名不加密

  •  
  •   dx5594206 · 2018-06-30 15:04:10 +08:00 · 3596 次点击
    这是一个创建于 2365 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我现在用的是 let's encrypt 的通配符证书,然后给本地的 web 服务器做一层反代套加密。

    但是现在做 hsts 的实验写课程论文,有一个需求就是要在一个子域名不能加密,现有的 DNS 解析是直接全到我服务器了,然后我配置了 SNI 如下:

    server {
    	listen 80;
    	server_name hsts.**.xyz;
    	add_header Strict-Transport-Security "max-age=31536000; preload" always;
    	location / {
    		proxy_pass http://127.0.0.1:2333;
    	}  
    }
    

    可是当我浏览器打开的时候,仍然支持 https,而且下发的是我在别的 SNI 里设置的通配符证书,之前尝试了把 https 重定向 302 到 http 也不管用,小绿锁挂的非常坚挺 2333

    请问我这应该怎么设置,可以让这个子域名强制不走 https ?

    18 条回复    2018-06-30 17:35:59 +08:00
    also24
        1
    also24  
       2018-06-30 15:12:53 +08:00
    不太理解,Strict-Transport-Security 不是强制走 https 了么…… 却又要求不加密?
    tlday
        2
    tlday  
       2018-06-30 15:14:57 +08:00 via iPhone
    首先确认修改完配置有 reload 或者 reopen nginx,
    其次,假如之前你对 http 使用过 301 跳转到 https,当再次请求该域名时,浏览器将不请求服务器,而是直接跳转 https。因为 301 是永久跳转,解决办法是清缓存,我印象中用普通的办法还不行,chrome 需要到 chrome://wwb-internals,点右上角的箭头清缓存。
    凭经验说的,没有重新考证过,只是提出个思路。
    tlday
        3
    tlday  
       2018-06-30 15:15:52 +08:00 via iPhone
    web-internals
    tlday
        4
    tlday  
       2018-06-30 15:17:25 +08:00 via iPhone
    查了下一楼说的这个 header,1 楼说的也对。涨姿势了。
    billchenchina
        5
    billchenchina  
       2018-06-30 15:20:04 +08:00 via Android
    1. preload 不要开,preload 会生效到所有二级域名

    2. nginx 可以用 if 语句把某一个域名判断掉
    dx5594206
        6
    dx5594206  
    OP
       2018-06-30 15:34:18 +08:00
    @also24
    @tlday
    我的意思是要做一个 hsts 的错误,就是指定了 hsts 还强制不加密会报什么错误
    dx5594206
        7
    dx5594206  
    OP
       2018-06-30 15:36:51 +08:00
    @billchenchina 明白了,也就是 nginx 无视掉了我这条配置。感谢
    所以我想构造这个错误除非再开一个机器,把 dns 记录到那个机器再做实验?
    另外 preload 是会生效到所有二级域名的话,那么 includeSubdom 是啥啊 23333
    kera0a
        8
    kera0a  
       2018-06-30 15:38:15 +08:00 via iPhone
    @dx5594206 你给的配置文件监听了 80 有啥用,浏览器 HSTS 早就强制走 https 了,根本不会去访问你的 80 端口
    dx5594206
        9
    dx5594206  
    OP
       2018-06-30 15:41:59 +08:00
    @kera0a 所以我就是想知道有什么办法可以让服务器对这个子域名强行不加密 23333 挺纠结的哈哈
    also24
        10
    also24  
       2018-06-30 15:46:56 +08:00
    @dx5594206 #6
    感觉你是不是对 hsts 有什么误解,hsts 头被浏览器收到以后,会 307 到相应的 https 地址,也就是访问同个主机的 443 端口。

    所以这时的情况是:
    浏览器访问了你这个 ip 的 443 端口,hsts.**.xyz 这个子域名

    由于你服务器上有其他的 vhost 配置,nginx 此时是有监听 443 端口的, 但是匹配不到 server_name,所以会下发第一个 server 段的证书以及内容。

    如果是一台 “干净” 的服务器,那么此时应该没有人监听 443 端口,估计会直接连接失败。
    kera0a
        11
    kera0a  
       2018-06-30 15:46:56 +08:00 via iPhone
    @dx5594206 先在浏览器中关掉 HSTS,不然怎么都是强制 https
    billchenchina
        12
    billchenchina  
       2018-06-30 15:48:58 +08:00
    @dx5594206 印象中 nginx 的配置文件中是可以写

    if($host = "www.example.com") {
    # something here
    }

    的,但具体不太清楚,可以查查资料。
    dx5594206
        13
    dx5594206  
    OP
       2018-06-30 15:58:17 +08:00
    @kera0a
    @also24
    感谢解答

    我想做的实验就是,看看 HSTS 错误的时候,浏览器会怎么报错,能不能 bypass 掉。
    因为印象中前一阵子淘宝在我这就出现过 HSTS 错误,他签发给 alicdn 的证书出了问题,隔天正常了我一看已经换成 tmall 的证书了。

    所以,我的理解是,浏览器访问 hsts.**.xyz ,因为我有 HSTS 的缓存,所以浏览器会主动把我 http://hsts.**.xyz 的请求转变成 https://我的 IP:443 这样的地址。nginx 因为有在监听 443 端口,但是 SNI 并没有在 443 端口上对应的配置,所以 nginx 只好给我下发了通配符证书,即使 server_name 不一样,也给我塞过去了。

    嗯。。。所以我应该在起更多 web 服务器,分别是 2333,2334,2335 这样的端口,然后看看 nginx 到底给我塞到哪了 2333
    also24
        14
    also24  
       2018-06-30 16:07:31 +08:00
    @dx5594206 #13
    应该是浏览器先访问:
    http://hsts.**.xyz
    然后根据返回的 header,把请求 307 到了
    https://hsts.**.xyz

    这之后怎么处理,其实就只是 nginx 如何处理 https://hsts.**.xyz 这个请求了,再深究起来其实就是在玩儿 nginx 了
    dx5594206
        15
    dx5594206  
    OP
       2018-06-30 16:14:11 +08:00
    @billchenchina
    @also24

    嗯。。。感谢解答。。。我决定,换个主机 2333
    if 那个看不懂 2333
    inkedawn
        16
    inkedawn  
       2018-06-30 17:17:39 +08:00
    什么强行加密不加密的……你对 hsts 有什么误解

    > HSTS 的作用是强制客户端(如浏览器)使用 HTTPS 与服务器创建连接。
    —— 《维基百科》

    HSTS 是用来限制客户端的,服务器只起到一个通知作用而已。
    HSTS 的效果也完全由客户端实现(一旦客户端收到服务器的 HSTS 信息,则有效期内一定会通过 https 连接)。
    只要客户端遵守这个规范,就一定会通过 https
    inkedawn
        17
    inkedawn  
       2018-06-30 17:32:18 +08:00
    换言之,
    即使你开启了 hsts,只要你不做额外限制,服务器也根本不会管你用 http 还是 https 的,对服务器而言两者都可以。
    限制你的是客户端(浏览器),收到了 hsts,就拒绝你继续用 http,而一定要通过 https。
    所以选择加不加密跟服务器没关系,而浏览器也并不会报错,遵不遵守 hsts、加不加密都是浏览器自己的决定,没有意外的理由报错。
    你说的淘宝出现 HSTS 错误,则是因为按照 HSTS,浏览器不允许用户忽略证书错误。(事实上此时如果浏览器无视 HSTS 不遵守这个限制,也能正常继续建立连接)
    likuku
        18
    likuku  
       2018-06-30 17:35:59 +08:00 via iPhone
    服务器另外加一个 IP,这个独立的子域名单独 A 记录指向这个单独 IP,可以这样试试
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2128 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 00:56 · PVG 08:56 · LAX 16:56 · JFK 19:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.