Search code examples
nginxsni

How to use SNI correctly? (Two Different Nginx SNI Writing Style)


What's the difference between these two different SNI writing styles? Could someone judge their differences from principle, performance, and so on?

Style1

stream{
    map $ssl_preread_server_name $backend_name{
        A.example.com A;
        B.example.com B;
    }
    upsteam A{
        server 127.0.0.1:10086
    }
    upsteam B{
        server 127.0.0.1:10087
    }
}

http{
    server{
        listen 10086 ssl http2;
        server_name A.example.com
        ...
    }
}

Style2

server {
    listen 127.0.0.1:443 ssl;
    server_name A.example.com;
    ...
}
server {
    listen 127.0.0.1:443 ssl;
    server_name B.example.com;
    ...
}

Solution

  • It seems from the question that you're trying to listen on 443 port for different hostnames. Requests coming with hostname A.example.com should get forwarded to 127.0.0.1:10086 while with hostname B.example.com would go to 127.0.0.1:10087. Let me explain what's happening behind the scenes in both styles.

    Style 1

    stream block lets you load balance over TCP/UDP. The ngx_stream_ssl_preread_module module lets you extract information from the request without ssl/tls termination. You're using map so connections coming as A.exammple.com set A in the variable $backend_name while those coming as B.example.com set B in the variable $backend_name. Based upon your upstream blocks the requests either get forwarded to 127.0.0.1:10086 or 127.0.0.1:10087. Since there is an http block with server blocks listening on port 10086 and 10087 respectively, it creates a new connection every time fulfilling those requests. The ssl termination is also happening inside the http block.

    Style 2

    Both server block are listening over 443 and depending on the hostname of the request it either goes through one of the server blocks. The ssl termination is happening before the request goes to ports where the application is actually running.

    Both styles are good to achieve this but personally I'd prefer Style 2 as the ssl termination is handled before the forwarding of the requests. Additionally, in Style 1 there's an extra connection created which is a slight performance overhead, in my opinion.