nginx default_server 默认服务器

nginx default_server 默认服务器

January 25, 2025

什么是 default_server

nginx 可以提供多个虚拟主机。对于发送到同一个物理主机的 Web 请求,最后会根据请求中请求头的“Host”字段(address:port)返回对应 server_nameport 中定义的响应内容。而有些请求中“Host”并不在我们定义的一系列虚拟主机中,那么 nginx 就会将其交给请求端口的 default_server 处理。

那么,谁是 default_server 呢,官方文档原文是

The default_server parameter, if present, will cause the server to become the default server for the specified _address_:_port_ pair. If none of the directives have the default_server parameter then the first server with the _address_:_port_ pair will be the default server for this pair. default_server参数(如果存在)将使服务器成为指定地址:端口对的默认服务器。如果没有一个指令有default_server参数,那么第一个有地址:端口对的服务器将是这个对的默认服务器。

以 Nginx 官方提供 deb 包和容器镜像为例,其默认会加载 /etc/nginx/conf.d/*.conf 的配置。

各个发行版可能会自定义路径,如 Debian 是 sites-enabled/*,Alpine 是 http.d/*.conf

其中自带一个 default.conf,主要内容为:

server {
    listen       80;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
    }
}

我的要求

我想让其默认无响应,防止那些扫描器扫描。这个其实挺好解决,nginx 文档中有提到

我稍微改了一下,加了 IPv6,并显式指定 default_server,防止被其他顶替(如 localhost 排在前面)。内容如下:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    return 444;  # 不发送任何响应,直接关闭连接
}

HTTP 好说,上面就已经可以,但是 HTTPS 就不一样了。HTTPS 在握手时交换证书会验证域名(SNI),这就导致访问 https://your-ip 可能会暴露你的域名。

之前有个解决办法是自签一个假证书/无用证书,但是总归不够优雅。这段时间正好看到有人提这件事,nginx 在 1.19.4 中加入了 ssl_reject_handshake 功能,可以禁用 SSL/TLS 握手,算是有了较好的解决办法。

最终 default.conf 中默认服务器配置如下:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    return 444;  # 不发送任何响应,直接关闭连接
    # https://nginx.org/en/docs/http/request_processing.html#how_to_prevent_undefined_server_names
}
server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    ssl_reject_handshake on; # 禁用 ssl 握手
    # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_reject_handshake
}