<!DOCTYPE html>
<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <div
style="color: #000000;background-color: #ffffff;font-family: 'Fira Code', Consolas, 'Courier New', monospace, Consolas, 'Courier New', monospace;font-weight: normal;font-size: 13px;line-height: 18px;white-space: pre;"><div><span
    style="color: #000000;">Hello everyone!</span></div>
<div><span style="color: #000000;">My previous attempt at posting to mailing list failed miserably, so forgive me</span></div><div><span
    style="color: #000000;">for sending this twice, please. </span></div>
<div><span style="color: #000000;">I'm trying to understand the behavior of nginx when it is configured to serve</span></div><div><span
    style="color: #000000;">multiple domains with different certificates.</span></div>
<div><span style="color: #000000;">I have a single server with single IP address, and several domains, say,</span></div><div><span
    style="color: #000000;">domain-a.com, domain-b.com. nginx is 1.24.0, configured as follows:</span></div>
<div><span style="color: #000000;">server {</span></div><div><span
    style="color: #000000;">    listen 443 ssl http2 default_server;</span></div>
<div><span style="color: #000000;">    ssl_reject_handshake on;</span></div>
<div><span style="color: #000000;">    return 444;</span></div><div><span
    style="color: #000000;">}</span></div>
<div><span style="color: #000000;">server {</span></div><div><span
    style="color: #000000;">    listen 443 ssl http2;</span></div><div><span
    style="color: #000000;">    server_name domain-a.com sub.domain-a.com;</span></div>
<div><span style="color: #000000;">    ssl_certificate     /etc/certs/domain-a.com.crt; <- this is wildcard cert</span></div><div><span
    style="color: #000000;">    ssl_certificate_key /etc/certs/domain-a.com.key; <- for domain-a.com, *.domain-a.com</span></div>
<div><span style="color: #000000;">    return 200 "serving domain-a.com";</span></div><div><span
    style="color: #000000;">}</span></div>
<div><span style="color: #000000;">server {</span></div><div><span
    style="color: #000000;">    listen 443 ssl http2;</span></div><div><span
    style="color: #000000;">    server_name domain-b.com sub.domain-b.com;</span></div>
<div><span style="color: #000000;">    ssl_certificate     /etc/certs/domain-b.com.crt; <- this is wildcard cert</span></div><div><span
    style="color: #000000;">    ssl_certificate_key /etc/certs/domain-b.com.key; <- for domain-b.com, *.domain-b.com</span></div>
<div><span style="color: #000000;">    return 200 "serving domain-b.com";</span></div><div><span
    style="color: #000000;">}</span></div>
<div><span style="color: #000000;">Here's what happens when I send some requests with curl:</span></div>
<div><span style="color: #000000;">$</span><span style="color: #000000;"> curl <a class="moz-txt-link-freetext" href="https://domain-a.com">https://domain-a.com</a></span></div><div><span
    style="color: #000000;">$</span><span style="color: #000000;"> curl <a class="moz-txt-link-freetext" href="https://sub.domain-a.com">https://sub.domain-a.com</a></span></div><div><span
    style="color: #000000;">$</span><span style="color: #000000;"> curl <a class="moz-txt-link-freetext" href="https://domain-b.com">https://domain-b.com</a></span></div><div><span
    style="color: #000000;">$</span><span style="color: #000000;"> curl <a class="moz-txt-link-freetext" href="https://sub.domain-b.com">https://sub.domain-b.com</a></span></div><div><span
    style="color: #000000;">: these returns expected responses for matching domain names.</span></div>
<div><span style="color: #000000;">$</span><span style="color: #000000;"> curl <a class="moz-txt-link-freetext" href="https://domain-a.com">https://domain-a.com</a> -H 'Host: domain-b.com'</span></div><div><span
    style="color: #000000;">$</span><span style="color: #000000;"> curl <a class="moz-txt-link-freetext" href="https://domain-b.com">https://domain-b.com</a> -H 'Host: domain-a.com'</span></div>
<div><span style="color: #000000;">Here is the interesting part. nginx negotiates SSL connection for SNI</span></div><div><span
    style="color: #000000;">domain-a.com but the response is from domain-b's virtual server! And vice versa.</span></div>
<div><span style="color: #000000;">$</span><span style="color: #000000;"> curl <a class="moz-txt-link-freetext" href="https://domain-a.com">https://domain-a.com</a> -H 'Host: not_matching_any_server_name'</span></div>
<div><span style="color: #000000;">This too negotiates SSL for SNI domain-a.com, but doesn't send any response.</span></div><div><span
    style="color: #000000;">Because it lands in the default_server block, I suppose.</span></div>
<div><span style="color: #000000;">The question is, when reading request Host field, does nginx validate it against</span></div><div><span
    style="color: #000000;">negotiated SNI or not? Is there any setting I'm missing to deny serving</span></div><div><span
    style="color: #000000;">requests if Host and SNI mismatch? Or is it just impossible to implement such</span></div><div><span
    style="color: #000000;">check due to protocols requirements?</span></div>
<div><span style="color: #000000;">I think that choosing virtual server solely based on Host field and ignoring SNI</span></div><div><span
    style="color: #000000;">may pose a risk from a security research perspective. E.g. if client negotiates</span></div><div><span
    style="color: #000000;">SSL for domain-a.com, I certainly do not want my server to even hint that it can</span></div><div><span
    style="color: #000000;">serve domain-b.com, much less send valid responses for that domain.</span></div>
<div><span style="color: #000000;">The best I could come up with was to insert into each server this:</span></div>
<div><span style="color: #000000;">if ($ssl_server_name != $</span><span
    style="color: #000000;">host) {</span></div><div><span
    style="color: #000000;">    return 421;</span></div><div><span
    style="color: #000000;">}</span></div>
<div><span style="color: #000000;">but I'm not sure whether this breaks any clients.</span></div>
<div><span style="color: #000000;">I looked through older threads and there were ones asking the same thing</span></div><div><span
    style="color: #000000;">(<a class="moz-txt-link-freetext" href="https://forum.nginx.org/read.php?2,281564,281564">https://forum.nginx.org/read.php?2,281564,281564</a>), though not sure whether</span></div><div><span
    style="color: #000000;">answers are up to date.</span></div>

</div>
  </body>
</html>