阻止对 Nginx 服务器的 SSL 访问

阻止对 Nginx 服务器的 SSL 访问

我有一台运行多个虚拟主机的服务器。其中一些站点有 SSL 组件,而其他站点没有。今天我注意到,如果我尝试通过 访问其中一个非 SSL 站点https,Nginx 只会找到一个虚拟主机使用 SSL 并尝试呈现它——在执行此操作之前给出熟悉的“不受信任”警告。

我尝试了几种解决方案,但都不太管用,我已经用尽了 Nginx 知识和/或阅读理解能力。理想情况下,如果通过网站不支持的协议访问网站,我希望看到 404 错误。

我尝试对服务器块进行各种编辑default,但都不起作用。我还尝试捕获并重定向端口 443 对该特定站点的访问,但(不出所料)也失败了。

有人能给我指明正确的方向吗?

答案1

不行。如果没有服务器名称指示 (SNI),主机名就是加密负载的一部分。即使有了 SNI,浏览器也不会接受来自 HTTPS URL 的重定向,除非先经过 HTTPS 握手 + 验证过程。

如果您愿意,您可以使用两个 IP 地址,一个用于您的安全站点,一个用于非安全站点,并且只在安全 IP 上监听 443。

答案2

我认为其他任何答案都没有涵盖整个故事:

你想要做的是可能的由于 SNI,服务器无法执行此操作。但是,尽管 nginx 支持 SNI,但它不支持执行您想要执行的操作。nginx 将对不匹配的 SNI 名称做出反应,将请求视为针对您的默认 SSL 站点(如果您未将 SSL 站点标记为默认站点,则将其视为其配置中的第一个 SSL 站点)。这通常会导致用户看到证书警告通知,因为 nginx 发送的证书上的名称与客户端请求的名称不匹配。

SNI 的 RFC指定服务器可以将无法识别的 SNI 名称视为致命错误:

如果服务器理解客户端 hello 扩展但不能识别服务器名称,它应该发送“unrecognized_name”警报(这可能是致命的)。

然而据我所知,Apache 和 nginx 都会继续连接并以与处理不匹配或丢失的“Host:”标头相同的方式处理它,即选择标记为该地址:端口的默认虚拟主机。

除非您已获得与客户端在联系您的服务器时可能使用的所有域名相匹配的 SSL 证书,否则无法阻止用户在继续操作之前看到有关证书无效的警告。即使您在用户访问网站时立即进行重定向,也只有在接受无效证书后才会进行重定向。

2017 年更新:由于现在可以轻松为所有域名获取免费 SSL 证书,因此您可以为所有域名获取 SSL 证书,即使您不打算通过 HTTPS 提供实际内容,只是为了确保任何重定向或错误消息都可以正常工作,而不会出现有关证书不匹配的任何警告。

答案3

您可以通过添加带有假(我对 localhost 使用自签名)ssl 证书的服务器条目来执行所需的操作,该证书会返回您想要的错误。这应该是第一个服务器块,或者至少在任何其他 ssl 块之前。请注意,我通常使用拒绝所有,但在这种情况下添加了 404。

server {
        listen       443 ssl default_server;
        server_name    localhost;
        ssl_certificate_key  /etc/ssl/private/localhost.key;
        ssl_certificate /etc/ssl/certs/localhost.crt;
#       deny  all;
        return 404;
}

要生成自签名证书,您可以使用以下命令

openssl genrsa 4096 > localhost.key
openssl req -new -sha256 -key localhost.key -subj "/CN=localhost" > localhost.csr
openssl x509 -req -days 3650 -in localhost.csr -signkey localhost.key -out localhost.crt
chmod 600 localhost.key
mv localhost.key /etc/ssl/private/
mv localhost.crt /etc/ssl/certs/

答案4

我不确定你到底尝试了什么,但如果你确实有 SNI 支持,一种方法是形成一个万能的方法:

server {
    listen [::]:443 default_server ssl;
    listen 443 default_server ssl;
    server_name _;
    return 444;
}

    server {
    listen  [::]:443 ssl;
        listen  443 ssl;
    server_name  ssl.site.net;
    ssl_certificate      your.crt;
    ssl_certificate_key  your.key;
....etc...

这将转储不匹配的服务器(从我以前使用的配置来看,目前我不用,因此请谨慎使用)正如其他人指出的那样,我不相信您可以通过这种方式进行重定向,只能进行删除。

对于非 SNI 支持(阅读:遗留),您可以始终获得一个便宜的通配符捕获证书,然后您将能够处理所有连接并根据需要重定向而不会出现任何问题。

编辑:再想想,如果我没记错的话,因为 nginx 支持 SNI,即使不支持 SNI 的客户端连接,它仍然会导致 nginx 在return 444尝试匹配要发送的证书时……想法?

相关内容