san*_*ank 1 ssl nginx openssl sni
我刚刚开始学习 nginx 和 SSL,并且一直在尝试不同的配置。我有两个服务器块,如下所示:
server{
listen 443 ssl http2;
server_name www.a.com;
ssl_certificate a.crt;
ssl_certificate_key a.key;
....
}
server{
listen 443 ssl ;
server_name www.b.com;
ssl_certificate b.crt;
ssl_certificate_key b.key;
....
}
Run Code Online (Sandbox Code Playgroud)
在使用 www.a.com 作为我的 SNI 通过 openssl s_client 连接到 nginx 后,我使用 Host: www.b.com 发送了一个 GET 请求,它仍然有效。这是预期的吗?有人可以帮助我了解 nginx 的行为吗?
HTTP 连接归根结底只是一个 TCP 连接。所以以上对于 HTTP 连接实际上是好的(即如果你连接到 www.a.com,你实际上是连接到一个 IP 地址而不是 www.a.com,所以实际上很好并且期望该连接能够www.b.com 的地址请求)。
对于 HTTPS,就像您说的那样,您正在使用它,但它的清晰度稍差...
对于 HTTP/1.1,HTTP Over TLS RFC和超文本传输协议 (HTTP/1.1): Message Syntax and Routing RFC中没有任何内容来说明应该如何处理,因为 SNI 是 HTTP 的非强制性扩展(事实上,顺便说一句,这是绕过客户端的一种方法 - 例如 XP 上的 IE8 - 如果两个虚拟主机使用相同的证书,则可以在基于该证书协商 TLS 会话后使用适当的连接作为由默认主机提供)。然而,SNI RFC 明确指出服务器必须检查这是相同的,所以当给出服务器名称并且与主机不同时,您观察到的内容是不正确的(感谢迈克尔汉普顿指出这一点,因为我最初错过了这一点)。
HTTP/2 在这方面更清楚,实际上确实允许在某些条件下重用连接,并且有这样的说法:
只要源服务器是权威的,就可以重用连接(第 10.1 节)。对于没有 TLS 的 TCP 连接,这取决于解析到相同 IP 地址的主机。
对于 https 资源,连接重用还取决于具有对 URI 中的主机有效的证书。服务器提供的证书必须满足客户端在为 URI 中的主机形成新的 TLS 连接时执行的任何检查。
源服务器可能会提供具有多个 subjectAltName 属性或带有通配符的名称的证书,其中之一对 URI 中的授权有效。例如,一个 subjectAltName 为 *.example.com 的证书可能允许对以https://a.example.com/ 和https://b.example.com/开头的 URI 的请求使用相同的连接。
因此,如果 a.crt 还在主题备用名称字段中包含 www.b.com,那么上述实际上在 HTTP/2 下是可以的,尽管在 HTTP/1.1 下不是。
但是,可以肯定的是,当 a.crt 绝对不涵盖 www.b.com 时,我已经重复了您的观察,这确实听起来像是一个错误,也可能存在安全风险,因为对一个虚拟主机的请求可能是如果有人能够注入无效的主机标头(幸好浏览器不容易做到这一点 - 所以诚然我无法证明这一点),则由另一个虚拟主机读取(尽管无法访问用于解密消息的密钥)。这可能会将 cookie 或其他信息泄漏到辅助服务器。
我已经向 nginx 安全团队提出了这个问题,他们说这不是 nginx 的安全缺陷,由客户端来验证证书,然后不要向他们应该通过该连接访问的主机发送格式错误的请求. 我强烈不同意这一点,并说 HTTPS 的全部意义在于只允许有效的端点解密消息!所以我认为应该在客户端和服务器端进行检查,事实上,当时 TLS 工作组讨论了这个确切的场景,SNI 是特定的,这就是为什么将上述措辞添加到 RFC. 此外,nginx 安全团队表示,在这种情况下,nginx 应该为两个主机设置一个联合证书(这对我来说没有意义,因为严重限制了 nginx 中虚拟主机的实用性!),但如果 nginx 服务器运营商真的想要限制这一点,那么他们可以通过检查$ssl_server_name变量来完成(这对我来说意味着这是一个相对容易的检查,nginx 默认可以做!)。无论如何,这是他们的软件,因此他们有权发表意见,但我不同意。
还有人指出,这种技术有时用于避免在称为Domain Fronting的过程中进行审查。这很公平,但我认为应该明确启用而不是默认允许。
顺便说一句,Apache 没有这样做,并且(正确地恕我直言)在 2.4.17 之前返回“400 Bad Request”,在 2.4.17 之后返回新的“421(Misdirected Request)”——这是一个专门为此创建的新 HTTP 状态代码场景。
| 归档时间: |
|
| 查看次数: |
1501 次 |
| 最近记录: |