mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-16 08:35:48 +08:00
ssl_ktls asks OpenSSL to hand TLS to the kernel (SSL_OP_ENABLE_KTLS) on the connections of the services which follow, both to clients and to servers; ssl_noktls, the default, keeps it in 3proxy. Where the library, the kernel and the cipher allow it, the kernel then encrypts and decrypts, and SSL_read/SSL_write go on working over it. What a service got is logged on its first TLS connection. Reading ahead is left off where the kernel took receiving, which reads a record at a time. A build whose library has no kernel TLS (wolfSSL, OpenSSL before 3.0 or without it) warns and ignores the command. splice() is not used for TLS services yet. Tested on AlmaLinux 10 (OpenSSL 3.5.8, tls module): both directions of both legs of a TLS chain in the kernel, the suite passing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
77 lines
2.5 KiB
Python
77 lines
2.5 KiB
Python
"""Kernel TLS (ssl_ktls): a TLS chain works the same whether or not the
|
|
kernel takes the encryption, and the proxy says which it did.
|
|
|
|
Whether it does depends on the TLS library (OpenSSL built with enable-ktls),
|
|
the kernel (the tls module on Linux) and the cipher, so the case checks the
|
|
data and the report, not that the kernel took it.
|
|
"""
|
|
|
|
|
|
def run(t):
|
|
certs = t.certs()
|
|
if not certs:
|
|
t.skip("kernel TLS (openssl is not available to generate certificates)")
|
|
return
|
|
if not certs.verified:
|
|
t.fail("the generated certificate chain verifies", "OK",
|
|
certs.verify_output or "openssl verify failed")
|
|
return
|
|
|
|
origin = t.free_port()
|
|
parent = t.free_port()
|
|
client = t.free_port()
|
|
|
|
server = t.start("ktls", f"""
|
|
log
|
|
auth iponly
|
|
allow *
|
|
http echo * /echo**
|
|
http data * /data
|
|
httpsrv -p{origin}
|
|
|
|
flush
|
|
ssl_ktls
|
|
ssl_server_cert {certs.server}
|
|
ssl_server_key {certs.server_key}
|
|
ssl_serv
|
|
auth iponly
|
|
allow *
|
|
proxy -p{parent}
|
|
|
|
flush
|
|
ssl_noserv
|
|
auth iponly
|
|
allow *
|
|
parent 1000 connects 127.0.0.1 {parent}
|
|
ssl_client_mode 3
|
|
ssl_client_ca_file {certs.ca}
|
|
ssl_client_verify
|
|
ssl_cli
|
|
proxy -p{client}
|
|
""", ports=[origin, parent, client])
|
|
|
|
out = server.output()
|
|
if "Unknown command" in out:
|
|
t.skip("kernel TLS (this build has no SSL support)")
|
|
return
|
|
|
|
through = f"127.0.0.1:{client}"
|
|
r = t.http(f"http://127.0.0.1:{origin}/echo", proxy=through)
|
|
t.eq(200, r.status, "a request through the TLS chain with ssl_ktls arrives")
|
|
t.contains(r, "path=/echo", "the origin sees it")
|
|
|
|
# many records, both ways through both TLS legs
|
|
for size in (100000, 3000000):
|
|
t.eq(size, t.http(f"http://127.0.0.1:{origin}/data?size={size}",
|
|
proxy=through).length,
|
|
f"a {size} byte body survives the kernel TLS chain")
|
|
t.eq(200000, t.http(f"http://127.0.0.1:{origin}/data?size=200000&chunked=1",
|
|
proxy=through).length,
|
|
"a chunked body survives the kernel TLS chain")
|
|
|
|
if "not supported by this TLS library" in server.output():
|
|
t.skip("the kernel TLS report (this TLS library has no kernel TLS)")
|
|
return
|
|
log = t.wait_output(server, "kernel TLS:")
|
|
t.contains(log, "kernel TLS: sending", "the proxy says whether the kernel took TLS")
|