SSL: Implement SNI #13

Open
opened 2025-08-25 21:14:19 -07:00 by swee · 0 comments
Owner

Currently, IRCat and SweeNet would need a wildcard certificate to work with multiple domains (i.e. irc.domain.tld and server.domain.tld)

There's a feature in SSL/TLS that allows clients' handshakes to report what hostname they're trying to connect with, the server can optionally use this information to provide the correct certificate.

Python's built-in ssl module already has SNI support since Python 3.7 (fits with our target of Python 3.12) by setting ctx.sni_callback.

It can also check if the system's OpenSSL build supports SNI (since 3.2) using ssl.HAS_SNI

Example code:

def handleCerts(sock, host, oldctx):
    # Temporarily create a new context
    newctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)

    if host == "1.example.com":
        # Load cert in new context and replace context
        newctx.load_cert_chain("/path/to/1.example.com/chain.pem", keyfile="/path/to/1.example.com/privkey.pem")
        sock.context = newctx
        return
    elif host == "2.example.com":
        newctx.load_cert_chain("/path/to/2.example.com/chain.pem", keyfile="/path/to/2.example.com/privkey.pem")
        sock.context = newctx
        return

# Later in the code where it uses SSL contexts
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain("/path/to/irc.example.com/chain.pem", keyfile="/path/to/irc.example.com/privkey.pem")
# Make the context use the callback function if supported by OpenSSL
if ssl.HAS_SNI:
    ctx.sni_callback = handleCerts

Because SNI is only supported in TLS version 1.1 and up, the server has two options for older SSL/TLS versions:

  1. Remove support for those old versions entirely
  2. Provide a wildcard cert

This is also an IRCv3 feature: https://ircv3.net/docs/sni

Currently, IRCat and SweeNet would need a wildcard certificate to work with multiple domains (i.e. irc.domain.tld and server.domain.tld) There's a feature in SSL/TLS that allows clients' handshakes to report what hostname they're trying to connect with, the server can optionally use this information to provide the correct certificate. Python's built-in `ssl` module already has SNI support since Python 3.7 (fits with our target of Python 3.12) by setting [`ctx.sni_callback`](https://docs.python.org/3/library/ssl.html#ssl.SSLContext.sni_callback). It can also check if the system's OpenSSL build supports SNI (since 3.2) using [`ssl.HAS_SNI`](https://docs.python.org/3/library/ssl.html#ssl.HAS_SNI) Example code: ```python def handleCerts(sock, host, oldctx): # Temporarily create a new context newctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) if host == "1.example.com": # Load cert in new context and replace context newctx.load_cert_chain("/path/to/1.example.com/chain.pem", keyfile="/path/to/1.example.com/privkey.pem") sock.context = newctx return elif host == "2.example.com": newctx.load_cert_chain("/path/to/2.example.com/chain.pem", keyfile="/path/to/2.example.com/privkey.pem") sock.context = newctx return # Later in the code where it uses SSL contexts ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) ctx.load_cert_chain("/path/to/irc.example.com/chain.pem", keyfile="/path/to/irc.example.com/privkey.pem") # Make the context use the callback function if supported by OpenSSL if ssl.HAS_SNI: ctx.sni_callback = handleCerts ``` Because SNI is only supported in TLS version 1.1 and up, the server has two options for older SSL/TLS versions: 1. Remove support for those old versions entirely 2. Provide a wildcard cert This is also an IRCv3 feature: https://ircv3.net/docs/sni
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: swee/IRCat#13
No description provided.