我有一个通配符 SSL 证书和多个子域位于同一个 IP 上。现在我希望我的 nginx 只处理提到的服务器名称并断开其他服务器的连接,这样它看起来就好像 nginx
没有为未列出的服务器名称运行(没有响应、拒绝、死机、没有一个字节的响应)。我做了以下事情
ssl_certificate tls/domain.crt;
ssl_certificate_key tls/domain.key;
server {
listen 1.2.3.4:443 ssl;
server_name validname.domain.com;
//
}
server {
listen 1.2.3.4:443 ssl;
server_name _;
// deny all;
// return 444;
// return 404;
//location {
// deny all;
//}
}
我几乎尝试了最后一个服务器块中的所有方法,但都没有成功。我收到了来自已知虚拟服务器的有效响应或错误代码。请帮忙。
答案1
它不是那样工作的:SSL 握手发生在 HTTP 之前,因此在您重定向或在 nginx 配置中执行任何其他操作之前,证书上的名称将在浏览器中进行评估。
答案2
此时,该问题的答案可以更新了。
对于 Nginx ≥ 1.19.4: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_reject_handshake
server {
listen 443 ssl default_server;
ssl_reject_handshake on;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate example.com.crt;
ssl_certificate_key example.com.key;
}
对于 Nginx < 1.19.4:使用https://git.hakase.app/Hakase/openssl-patch
http {
# control options
strict_sni on;
strict_sni_header on;
# fake server block
server {
server_name localhost;
listen 80;
listen 443 ssl default_server; # "default_server" is necessary
ssl_certificate /root/cert.crt; # Can be any certificate here
ssl_certificate_key /root/cert.key; # Can be any certificate here
location / {
return 444;
}
}
# normal server blocks
server {
server_name normal_domain.tld;
listen 80;
listen 443 ssl;
ssl_certificate /root/cert.crt; # Your real certificate here
ssl_certificate_key /root/cert/cert.key; # Your real certificate here
location / {
echo "Hello World!";
}
}
}
对于不熟悉如何将补丁应用于 Nginx 的新手,你可以检查一下:https://stackoverflow.com/questions/64225024/64225025#64225025
答案3
cjc 的回答已经正确指出了启用 SSL 时尝试匹配主机名的问题。但是,可以这样做,如下所示:
server {
...
if ($host !~* ^validname\.domain\.com$ ) {
return 444;
}
...
}
注意:是的,一般来说if
是邪恶的,但在这种情况下使用是安全的if
。(如果您需要确认,请阅读链接页面。)
与建议相反,仅添加以下块是行不通的:
server {
listen 80;
listen 443 ssl;
return 444;
}
因为匹配的 SSL 证书validname.domain.com
不会匹配某个随机域名。我试过了,nginx 表现得好像根本没有阻止一样。
这也行不通:
server {
listen 443;
server_name _;
return 444;
}
因为它将使每一个端口 443 上的 HTTPS 连接失败,甚至那些应该通过的也失败了。我也试过了。wget
报告了 SSL 握手错误。
答案4
我今天实施了上述解决方案,效果非常好。现在所有未指定的 URL 都将被删除。将此服务器代码放在实际虚拟服务器条目之前是关键 - 所有格式错误的 URL 现在都会转到此“默认”服务器。
...
server {
listen 443;
server_name _;
return 444; }
server {
listen 443;
server_name [URL]