将非 SNI 浏览器重定向到 nginx 中的仅 HTTP 警告页面

Redirecting non-SNI browsers to HTTP-only warning page in nginx

使用仅 SNI 证书(Let's Encrypt,CloudFlare 免费)时,使用 Windows XP 和 Chrome 或 IE 的用户是 not able to connect to your site。 XP 上的 Firefox 运行良好。

我想测试用户代理是 XP 上的 Chrome 还是 XP 上的 IE(或 XP 上不是 Firefox 的任何东西),并将它们重定向到一个 HTTP 警告页面,告诉他们使用XP 上的 Firefox。

在 nginx 下你会怎么做?

目前,我正在使用此块将所有 http 链接重定向到 https。

if ($http_cf_visitor ~ '{"scheme":"http"}') {
    return 301 https://$server_name$request_uri;
}

如何将上述用户代理检测合并到此块中,以便将非 SNI 用户重定向到仅 HTTP 警告页面?

您可以使用 nginx 用户代理映射来检测和重定向非 SNI 客户端(IE 和 Chrome XP 上的浏览​​器)。只需将其放入站点配置文件(服务器块外部):

map $http_user_agent $is_xp {
    default 0;
    "~Windows NT 5.1" 1;
}

map $http_user_agent $whitelist_browser {
    default 0;
    "~Firefox" 1;
}

map $is_xp$whitelist_browser $no_sni {
    default 0;
    "10" 1;
}

第一个映射在用户代理字符串 (=Windows XP) 中检查 Winhdows NT 5.1,但是因为 Firefox 不依赖 XP 的 SSL 实现并且有自己的支持 SNI 的库,我们最好将其列入白名单浏览器甚至在 XP 上,这就是第二张地图所做的。第三张地图只是将这两个条件结合在一起。

所以现在我们可以在服务器块中使用它来做我们想做的事了:

    if ($no_sni = 1) {
        # do whatever (redirect...???)
    }

但是!!! 此解决方案仅适用于直接在地址栏中输入 URL 的访问者(浏览器默认为 HTTP)。想象一下 Google(或任何人)抓取您的网站,将其检测为 HTTPS(机器人的用户代理既不是 XP 也不是 IE)并且当然 将其索引为 HTTPS 的情况,它会在搜索结果页面上显示为 HTTPS!因此,使用非 SNI 客户端的用户将从搜索中直接重定向到 HTTPS,你又遇到麻烦了。

唯一的解决方法 是从 CA (letsencrypt, ...) 请求一个大证书,将您服务器上托管的所有域列为 SAN,并将此证书用作默认 SSL证书。因此,如果任何非 sni 客户端访问您的服务器,它将获得包含所有域的通用证书,一切都会正常。