Skip to content

gh-96828: Add an ssl.OP_ENABLE_KTLS option #96830

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 24, 2022

Conversation

illia-v
Copy link
Contributor

@illia-v illia-v commented Sep 14, 2022

Copy link
Member

@gpshead gpshead left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added @tiran to confirm we want this, otherwise this looks good.

@smontanaro
Copy link
Contributor

(I'm working my way through some PRs which have been approved and are labeled "awaiting merge", hence my seemingly bolt from the blue comment. Why? Read here.)

@tiran? Do you have anything to add?

@tiran
Copy link
Member

tiran commented Nov 23, 2022

Is there any benefit in using KTLS without SSL_sendfile at all? Did you test that the feature actually works with Python's ssl module? It's definitely incompatible with MemoryBIO / asyncio.

@illia-v
Copy link
Contributor Author

illia-v commented Nov 23, 2022

@tiran let me cite your colleagues to respond about the benefit 🙂:

With suitable NIC hardware the encryption operations can be offloaded, freeing time on the main CPUs for application usage. Without offload hardware, kTLS may still improve parallelism for applications as the kernel can perform encryption operations on a differen host CPU to that running the application threads

Also, I posted about SSL_sendfile on Discuss, your response will be valuable there.


I did a test using this code and new methods of _ssl._SSLSocket:
a30a9f8

import asyncio
import socket
import ssl

import certifi


def check_ktls(sslobj):
    print(f"kTLS read {sslobj.uses_ktls_for_read()}")
    print(f"kTLS write {sslobj.uses_ktls_for_write()}")


hostname = "example.com"
request = b"GET /\r\n\r\n"

context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.load_verify_locations(certifi.where(), None, None)
context.options |= ssl.OP_ENABLE_KTLS

with socket.create_connection((hostname, 443)) as sock:
    with context.wrap_socket(sock, server_hostname=hostname) as ssock:
        ssock.send(request)
        print(ssock.recv(20))
        print(ssock.cipher())
        check_ktls(ssock._sslobj)


print()


async def check():
    print("asyncio")
    reader, writer = await asyncio.open_connection(hostname, 443, ssl=context)
    writer.write(request)
    print(await reader.read(20))
    ssl_object = writer.transport.get_extra_info("ssl_object")
    print(ssl_object.cipher())
    check_ktls(ssl_object._sslobj)
    writer.close()


asyncio.run(check())

This was the result, kTLS was used for writing when asyncio was not used:

b'HTTP/1.0 404 Not Fou'
('TLS_AES_256_GCM_SHA384', 'TLSv1.3', 256)
kTLS read False
kTLS write True

asyncio
b'HTTP/1.0 404 Not Fou'
('TLS_AES_256_GCM_SHA384', 'TLSv1.3', 256)
kTLS read False
kTLS write False

@gpshead gpshead merged commit 9dc0836 into python:main Nov 24, 2022
@gpshead
Copy link
Member

gpshead commented Nov 24, 2022

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add an ssl.OP_ENABLE_KTLS option for enabling the use of the kernel TLS
5 participants