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

2018-06-30 15:04:10 +08:00
 dx5594206

我现在用的是 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 ?

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

2. nginx 可以用 if 语句把某一个域名判断掉
dx5594206
2018-06-30 15:34:18 +08:00
@also24
@tlday
我的意思是要做一个 hsts 的错误,就是指定了 hsts 还强制不加密会报什么错误
dx5594206
2018-06-30 15:36:51 +08:00
@billchenchina 明白了,也就是 nginx 无视掉了我这条配置。感谢
所以我想构造这个错误除非再开一个机器,把 dns 记录到那个机器再做实验?
另外 preload 是会生效到所有二级域名的话,那么 includeSubdom 是啥啊 23333
kera0a
2018-06-30 15:38:15 +08:00
@dx5594206 你给的配置文件监听了 80 有啥用,浏览器 HSTS 早就强制走 https 了,根本不会去访问你的 80 端口
dx5594206
2018-06-30 15:41:59 +08:00
@kera0a 所以我就是想知道有什么办法可以让服务器对这个子域名强行不加密 23333 挺纠结的哈哈
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
2018-06-30 15:46:56 +08:00
@dx5594206 先在浏览器中关掉 HSTS,不然怎么都是强制 https
billchenchina
2018-06-30 15:48:58 +08:00
@dx5594206 印象中 nginx 的配置文件中是可以写

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

的,但具体不太清楚,可以查查资料。
dx5594206
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
2018-06-30 16:07:31 +08:00
@dx5594206 #13
应该是浏览器先访问:
http://hsts.**.xyz
然后根据返回的 header,把请求 307 到了
https://hsts.**.xyz

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

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

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

HSTS 是用来限制客户端的,服务器只起到一个通知作用而已。
HSTS 的效果也完全由客户端实现(一旦客户端收到服务器的 HSTS 信息,则有效期内一定会通过 https 连接)。
只要客户端遵守这个规范,就一定会通过 https
inkedawn
2018-06-30 17:32:18 +08:00
换言之,
即使你开启了 hsts,只要你不做额外限制,服务器也根本不会管你用 http 还是 https 的,对服务器而言两者都可以。
限制你的是客户端(浏览器),收到了 hsts,就拒绝你继续用 http,而一定要通过 https。
所以选择加不加密跟服务器没关系,而浏览器也并不会报错,遵不遵守 hsts、加不加密都是浏览器自己的决定,没有意外的理由报错。
你说的淘宝出现 HSTS 错误,则是因为按照 HSTS,浏览器不允许用户忽略证书错误。(事实上此时如果浏览器无视 HSTS 不遵守这个限制,也能正常继续建立连接)
likuku
2018-06-30 17:35:59 +08:00
服务器另外加一个 IP,这个独立的子域名单独 A 记录指向这个单独 IP,可以这样试试

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

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

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

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

© 2021 V2EX