nginx default_server 默认服务器
什么是 default_server
nginx 可以提供多个虚拟主机。对于发送到同一个物理主机的 Web 请求,最后会根据请求中请求头的“Host”字段(address:port
)返回对应 server_name
及 port
中定义的响应内容。而有些请求中“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 thedefault_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
}