nginx 过滤标题名称中带有点的标题,即使启用 ignore_invalid_headers 也是如此

nginx 过滤标题名称中带有点的标题,即使启用 ignore_invalid_headers 也是如此

客户端(由第三方开发)正在发送带有类似标头的请求foo.meta-digest(请注意标头名称中的“点”)。我的 nginx 反向代理正在从请求中删除这些标头,即使我添加了ignore_invalid_headers off;(请参阅http://nginx.org/r/ignore_invalid_headers)到此server { ... }虚拟主机的块:

upstream backend {
   keepalive 128;
   keepalive_requests 1000;
   keepalive_timeout 120s;
   server 127.0.0.1:32000 max_fails=0 fail_timeout=10;
}

server {

   listen 443 ssl http2;
   server_name foo.com;
   root /var/www/empty;
   ssl_certificate /etc/nginx/certs/foo.com.crt;
   ssl_certificate_key /etc/nginx/certs/foo.com.key;

   ignore_invalid_headers off;

   location / {
       proxy_pass http://backend;
       proxy_set_header        Host              $http_host;
       proxy_set_header        X-Real-IP         $remote_addr;
       proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header        X-Forwarded-Proto $scheme;
       proxy_set_header        Connection      "";
   }
}

除了这个特定的客户端之外,我无法使用任何其他客户端重现此问题,并且我无法访问该客户端的源代码,它是专有软件。

如果我使用或任何其他 Web 客户端发送相同的请求curl,则所有标头(包括名称中带有“点”的标头)都会按应有的方式传递到后端。

我甚至尝试对 nginx 主机进行 mitm 攻击,并拦截来自客户端的网络流量。客户端肯定foo.meta-digest按预期发送了标头。不知何故,nginx 正在过滤标头,但仅针对此特定客户端。

我还能做什么来调试这个问题?

答案1

刚刚遇到了类似的问题,我只需将其添加ignore_invalid_headers off到默认服务器即可解决

在我的案例中,客户做了两件奇怪(且不好)的事情:

  1. 它使用 TLSv1.2 进行连接,但是没有使用信噪比扩展名。
    客户端使用它来(以明文形式)提供它所连接的域名,以便服务器能够为正确的虚拟主机使用正确的证书。
    如果没有这个,客户端将始终获得默认虚拟主机的证书。...
    客户端已将其固定,因此即使它对于域无效,它也会被接受。

请注意,这只会影响您从服务器获得的 TLS 证书!理论上(请参阅后面的第 2 点),nginx 仍将使用标Host:头来确定哪个是正确的 vhost,以及要使用哪个 conf。

请注意,除非您将证书固定在客户端应用程序中,并且除非您确定证书,否则这样做非常不安全。您将面临 MITM 攻击。
此外,SNI 是在 12 年前开发的,对于虚拟托管来说是必不可少的。

  1. Nginx 将使用Host:Header 来了解要应用哪个 vhost 配置。
    正如您所猜到的,因为我告诉过您在默认服务器中添加ignore_invalid_headers,所以这在特殊情况下不起作用:
    RFC7230,第 5.4 节Host标题应该是您发送的第一件事。
    就我的情况而言(可能您也是这样),情况并非如此。因此,Headers
    之前的标头Host会按照默认服务器配置进行解析,然后 nginx 会找到Host并切换到正确的 vhost。

奇怪,几乎不符合标准,绝对是不好的做法,但从技术上来说并没有错。

希望能帮助到你

相关内容