Welcome! Log In Create A New Profile

Advanced

How to deny serving requests if Host field and SNI do not match?

March 31, 2024 08:48AM
Hello everyone!
My previous attempt at posting to mailing list failed miserably, so
forgive me
for sending this twice, please.
I'm trying to understand the behavior of nginx when it is configured to
serve
multiple domains with different certificates.
I have a single server with single IP address, and several domains, say,
domain-a.com, domain-b.com. nginx is 1.24.0, configured as follows:
server {
    listen 443 ssl http2 default_server;
    ssl_reject_handshake on;
    return 444;
}
server {
    listen 443 ssl http2;
    server_name domain-a.com sub.domain-a.com;
    ssl_certificate     /etc/certs/domain-a.com.crt; <- this is
wildcard cert
    ssl_certificate_key /etc/certs/domain-a.com.key; <- for
domain-a.com, *.domain-a.com
    return 200 "serving domain-a.com";
}
server {
    listen 443 ssl http2;
    server_name domain-b.com sub.domain-b.com;
    ssl_certificate     /etc/certs/domain-b.com.crt; <- this is
wildcard cert
    ssl_certificate_key /etc/certs/domain-b.com.key; <- for
domain-b.com, *.domain-b.com
    return 200 "serving domain-b.com";
}
Here's what happens when I send some requests with curl:
$curl https://domain-a.com
$curl https://sub.domain-a.com
$curl https://domain-b.com
$curl https://sub.domain-b.com
: these returns expected responses for matching domain names.
$curl https://domain-a.com -H 'Host: domain-b.com'
$curl https://domain-b.com -H 'Host: domain-a.com'
Here is the interesting part. nginx negotiates SSL connection for SNI
domain-a.com but the response is from domain-b's virtual server! And
vice versa.
$curl https://domain-a.com -H 'Host: not_matching_any_server_name'
This too negotiates SSL for SNI domain-a.com, but doesn't send any response.
Because it lands in the default_server block, I suppose.
The question is, when reading request Host field, does nginx validate it
against
negotiated SNI or not? Is there any setting I'm missing to deny serving
requests if Host and SNI mismatch? Or is it just impossible to implement
such
check due to protocols requirements?
I think that choosing virtual server solely based on Host field and
ignoring SNI
may pose a risk from a security research perspective. E.g. if client
negotiates
SSL for domain-a.com, I certainly do not want my server to even hint
that it can
serve domain-b.com, much less send valid responses for that domain.
The best I could come up with was to insert into each server this:
if ($ssl_server_name != $host) {
    return 421;
}
but I'm not sure whether this breaks any clients.
I looked through older threads and there were ones asking the same thing
(https://forum.nginx.org/read.php?2,281564,281564), though not sure whether
answers are up to date._______________________________________________
nginx mailing list
nginx@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx
Subject Author Posted

How to deny serving requests if Host field and SNI do not match?

arisudesu March 31, 2024 08:48AM



Sorry, only registered users may post in this forum.

Click here to login

Online Users

Guests: 222
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready