如何在HTTP/2下的Nginx中使用server_name?

How to use server_name in Nginx under HTTP/2?

我想使用 2 个服务器块。 第一个是:

    server {
    listen 443 ssl http2 fastopen=3 reuseport;
    server_name a.example.xyz;
    include server_safe.conf;
    root /home/www/blog/;
    }

第二个是:

  server {
    listen 443 ssl http2;
    server_name b.example.xyz;
    include server_safe.conf;
}

我想要的: 我希望 server_name 有效,也就是说,如果我使用 c.example.xyz 访问我的网站,那么 a.example.xyz,b.example.xyz,c.example.xyz 是相同的IP ,服务器应该阻止 c.example.xyz 请求,因为它不在 server_name.

但是,如果我输入https://c.example.xyz,Nginx仍然会收到请求和响应a.example.xyz

我知道 HTTP/2 在其 header 中没有主机,它有一个 :authority

我的问题是:我怎样才能拒绝任何其他请求?我只想接受 host(:authority) = a(b).example.xyz

下的请求

问题是如果没有其他名称匹配,则默认使用第一个服务器块。

因此,要实现您想要的效果,您需要创建一个默认块,其他两个块之前,让它块或重定向,或显示错误页面。

这样做的缺点是:

  1. 除非您拥有所有域名的 HTTPS 证书(或使用涵盖此内容的通配符证书),否则他们在访问您网站的 https 版本并使用此默认配置时会出错.尽管这无论如何都会在您当前的设置下发生。 AFAIK 无法在 HTTPS 协商发生之前 发送阻止消息。

  2. 不支持 SNI 的旧客户端(主要是 Windows XP)将使用默认配置,而以前它们会通过服务器 A,因为它是默认配置(尽管不适用于服务器 B)。

另一种方法是根据提供的主机名编写重定向规则。老实说,不是 100% 确定如何在 nginx 上执行此操作,但如果默认情况下不可能,那么使用 ModSecurity 是可能的。同样,它只会在 HTTPS 协商发生后生效,因此仍然会给您留下潜在的错误证书问题。