Summary
External TLS clients (curl, OpenSSL s_client) cannot complete the TLS 1.3 handshake with tigrcorn's custom pure-Python TLS record layer. The error from curl is:
OpenSSL SSL_read: error:0A0001BB:SSL routines::bad record type
Environment
- macOS (darwin-arm64)
- curl 8.x with OpenSSL 3.6.1
- Python 3.14.2 with OpenSSL 3.5.4
- tigrcorn master (076aa46)
Root cause
tigrcorn uses a custom pure-Python TLS 1.3 implementation (src/tigrcorn/security/tls.py + src/tigrcorn/security/tls13/) rather than Python's stdlib ssl module. The handshake completes successfully when the client is:
- tigrcorn's own
QuicTlsHandshakeDriver (internal driver-to-driver)
- Python's
asyncio.open_connection(ssl=...) (verified working)
But fails with:
- curl (any version using OpenSSL 3.5+)
- Any external OpenSSL-based client
The bad record type error indicates curl's OpenSSL rejects something in the TLS record format that tigrcorn sends. The record headers appear correct (type=23, version=0x0303, valid length), so the issue is likely in the encrypted record content or framing that newer OpenSSL versions are stricter about.
Reproduction
# Generate Ed25519 certs with proper extensions (AKI, SKI, KeyUsage)
# Start server
tigrcorn app:app --host 127.0.0.1 --port 8443 \
--ssl-certfile server.pem \
--ssl-keyfile server-key.pem
# Fails
curl --cacert ca.pem https://localhost:8443/
# OpenSSL SSL_read: error:0A0001BB:SSL routines::bad record type
Proposed fix
Add a --ssl-backend CLI flag (custom | stdlib). The TCPListener.start() method (lines 55-67 of listeners/tcp.py) already supports two code paths:
custom (default): ServerTLSContext → pure-Python TLS 1.3 handshake
stdlib: ssl.SSLContext → passed directly to asyncio.start_server(ssl=...)
The fix is to allow build_server_ssl_context() to return a stdlib ssl.SSLContext when --ssl-backend=stdlib is specified. No changes needed to TCPListener itself.
Workaround
Pass a stdlib ssl.SSLContext to TCPListener directly via a launcher script:
import ssl
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain('server.pem', 'server-key.pem')
listener = TCPListener('127.0.0.1', 8443, ssl=ctx)
Additional findings
Demo certs also needed X.509 extensions (Authority Key Identifier, Subject Key Identifier, Key Usage) that OpenSSL 3.5+ requires for certificate chain validation. Without these, even Python's ssl module rejects the certs.
Expected behavior
External TLS clients like curl should be able to connect to tigrcorn over HTTPS.
Summary
External TLS clients (curl, OpenSSL
s_client) cannot complete the TLS 1.3 handshake with tigrcorn's custom pure-Python TLS record layer. The error from curl is:Environment
Root cause
tigrcorn uses a custom pure-Python TLS 1.3 implementation (
src/tigrcorn/security/tls.py+src/tigrcorn/security/tls13/) rather than Python's stdlibsslmodule. The handshake completes successfully when the client is:QuicTlsHandshakeDriver(internal driver-to-driver)asyncio.open_connection(ssl=...)(verified working)But fails with:
The
bad record typeerror indicates curl's OpenSSL rejects something in the TLS record format that tigrcorn sends. The record headers appear correct (type=23, version=0x0303, valid length), so the issue is likely in the encrypted record content or framing that newer OpenSSL versions are stricter about.Reproduction
Proposed fix
Add a
--ssl-backendCLI flag (custom|stdlib). TheTCPListener.start()method (lines 55-67 oflisteners/tcp.py) already supports two code paths:custom(default):ServerTLSContext→ pure-Python TLS 1.3 handshakestdlib:ssl.SSLContext→ passed directly toasyncio.start_server(ssl=...)The fix is to allow
build_server_ssl_context()to return a stdlibssl.SSLContextwhen--ssl-backend=stdlibis specified. No changes needed toTCPListeneritself.Workaround
Pass a stdlib
ssl.SSLContexttoTCPListenerdirectly via a launcher script:Additional findings
Demo certs also needed X.509 extensions (Authority Key Identifier, Subject Key Identifier, Key Usage) that OpenSSL 3.5+ requires for certificate chain validation. Without these, even Python's
sslmodule rejects the certs.Expected behavior
External TLS clients like curl should be able to connect to tigrcorn over HTTPS.