NGINX 反向代理“if not”语句语法?

NGINX 反向代理“if not”语句语法?

我有一个 nginx 反向代理,我想将任何不是我的特定顶级域的 url 请求重定向到 404。

到目前为止,我想在我的底部有这样的东西/etc/nginx/sites-enabled/site.conf

server {
        listen 80;
        if ($host != *domain.com) {
                return 404 http://$host$request_uri;
        }
}

但我不知道这里的确切语法。我已经有其他重定向块,我只希望任何仅针对 IP 主机名或其他域的 URL 请求立即获得 404 并且不会传递到后端服务器。

此外,我还有 TLS 直通,我想在上面做同样的事情,但我完全不知道如何在流块上实现 if 语句。我的流块如下所示/etc/nginx/nginx.conf

stream {
        map $ssl_preread_server_name $name {
                server.domain.com           server;
                www.domain.com              www;
        }
        upstream server {
                server backendip:443;
        }
        upstream www {
                server backendip2:443;
        }
        server {
                listen 443;
                proxy_pass $name;
                ssl_preread on;
        }
}

为此,我是否会在第一个服务器块下方实现类似的功能?

        server {
                listen 443;
                if ($ssl_preread_server_name != *domain.com) {
                        return 404 https://$host$request_uri;
                }
        }

我认为为了安全起见,我还应该在带有 if 语句的这两个块的监听行中包含 default_server,或者这有关系吗?

我只是在这里假设了很多语法,因此非常感激任何帮助。

答案1

我不知道如何正常关闭与流模块的连接,所以我不确定这是否是一个正确的解决方案,但值得尝试(您可以使用任何空闲端口作为虚拟服务器/上游):

stream {
    map $ssl_preread_server_name $name {
        server.domain.com           server;
        www.domain.com              www;
        default                     dummy;
    }
    upstream server {
        server backendip:443;
    }
    upstream www {
        server backendip2:443;
    }
    upstream dummy {
        backend 127.0.0.1:4343;
    }
    server {
        listen 443;
        proxy_pass $name;
        ssl_preread on;
    }
    server {
        listen 4343;
        return "";
    }
}

更新

在对上述解决方案进行测试后,我可以确认它是可行的。但是它会产生一个错误日志条目,如下所示

WSARecv() 在代理和从上游读取时失败(10053:主机中的软件中止了已建立的连接),客户端:127.0.0.1,服务器:127.0.0.1:443,上游:“127.0.0.1:4343”,来自/到客户端的字节数:517/0,来自/到上游的字节数:0/517

经过一番思考后我尝试了这个:

http {
    server {
        listen              4343 ssl;
        ssl_certificate     /path/to/selfsigned.crt;
        ssl_certificate_key /path/to/selfsigned.key;
        return              444;
    }
}
stream {
    map $ssl_preread_server_name $name {
        server.domain.com           server;
        www.domain.com              www;
        default                     dummy;
    }
    upstream server {
        server backendip:443;
    }
    upstream www {
        server backendip2:443;
    }
    upstream dummy {
        backend 127.0.0.1:4343;
    }
    server {
        listen 443;
        proxy_pass $name;
        ssl_preread on;
    }
}

可以使用以下命令创建自签名证书和密钥:

openssl req -nodes -new -x509 -subj "/CN=localhost" -keyout /path/to/selfsigned.key -out /path/to/selfsigned.crt

这样就可以正确关闭连接。

此外,即使这样也有效:

http {
    server {
        listen              80 default_server;
        return              444;
    }
}
stream {
    map $ssl_preread_server_name $name {
        server.domain.com           server;
        www.domain.com              www;
        default                     dummy;
    }
    upstream server {
        server backendip:443;
    }
    upstream www {
        server backendip2:443;
    }
    upstream dummy {
        backend 127.0.0.1:80;
    }
    server {
        listen 443;
        proxy_pass $name;
        ssl_preread on;
    }
}

当然,curl握手尝试时会抱怨 SSL 版本号不正确,并且访问日志中会出现一些有趣的条目,例如

127.0.0.1 - - [05/Nov/2021:01:04:34 +0200] "\x16\x03\x01\x02\x00\x01\x00\x01\xFC\x03\x03L\xF9[\xB2\x7F\x99\xB1(\xAC\xB4\x91}\xE2N\xC6H\xE3\xB3_\xD1\xEA\xA3C\x1D\xE5\xE5\xB6\x02\xDB\x04h\xB6 *\xCB\x0E\xC0\xF5\xB7\xAF[y|\x1B\x14_\xC2g\xEA\xA2\x1E\xB4\xC4Bj3t\xE8d\xE72vm\xF2\x1B\x00>\x13\x02\x13\x03\x13\x01\xC0,\xC00\x00\x9F\xCC\xA9\xCC\xA8\xCC\xAA\xC0+\xC0/\x00\x9E\xC0$\xC0(\x00k\xC0#\xC0'\x00g\xC0" 400 163 "-" "-"

但错误日志很清楚。

相关内容