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
proposal: crypto/tls: support kernel-provided TLS #44506
Comments
cc @FiloSottile |
I would love to have this happen as well! It's a major use case for L7 load balancers written in golang, and could transparently provide significant performance boosts for a lot of systems (including Kubernetes) |
Can we get some benchmarks and numbers for the performance improvement? My patch linked above might be a good starting point. It's a lot of complexity and it would have to be justified by very good numbers. |
Hi, all I have updated kernel tls support based on @FiloSottile's original code. It now supports more ciphers like AES_GCM_256, AES_CCM_128 and CHACHA20_POLY1305. Code: https://github.com/jim3ma/go/tree/dev.ktls.1.16.3. And I have fixed some kernel issues when in coding: torvalds/linux@974271e, torvalds/linux@d8654f4 In my simple tests, when enable kernel tls, I have got 30% time cost decreased. |
I made some real-world tests with one of our internal applications (CDN node specialised in delivering video segments for DASH and HLS streams).
I compared https vs http, vs http + sendfile and ktls + sendfile. Most of the TLS stuff is working, except TLS 1.3 with Chrome and k6. k6 reports With ktls, the latency is increased - but this can also be related to the difference in the used Go-Versions. The ktls implementation reduces overall CPU usage, around 10%. We'll deploy the Nvidia ConnectX-6 (200 Gbit/s) in our latest hardware setup, and we hope we can use the TLS NIC offloading in the future. https://docs.google.com/spreadsheets/d/1XaiFczae9GLixu__8y2kuKPsw7RGqW9vMDkYxuTLx28/edit#gid=0 |
@totallyunknown If the latency issue is related to the kernel implementation (rule out golang side) we can take a look at kernel side improvements. We've been using the openssl implementation lately so I'll check there as well, but I don't recall extra latency last time I did metrics. Having a golang implementation would be very useful on my side as well. fwiw I'm one of the ktls maintainers on kernel side so we shouldn't have trouble getting improvements there as needed and happy to help where I can to get this moving forward. |
Which version do you test ? I have update some go code for http with ktls. |
@jim3ma Your branch: https://github.com/jim3ma/go/tree/dev.ktls.1.16.3 |
Okay, I will merge some optimized code into this branch tomorrow. |
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
@jim3ma are there any plans to introduce the changes into the Go code? |
Sorry for busy work. I will rebase kTLS code in latest branch and test it again. |
any updates? |
@jim3ma curious about the updates too been checking here @FiloSottile i've been watching ktls progress for golang since you started the blog in 2021. once this is ktls-ed, i believe will be one of golang's greatest milestone ever. |
I did some rough benchmarks late last year where I had Golang call into rust's TLS library via CGO to do the handshake and then handed off the established TCP connection to Golang. I found that the performance (throughput/latency on sustained traffic) ended up being about the same as golang's built-in TLS or slightly worse. I'm not sure why to be honest - maybe I did something wrong? But I would like to see some numbers hopefully from someone else on the actual performance of the kTLS implementation in the linux kernel. |
@ShivanshVij u hv the code for helping to debug? but ktls is better for sure. |
Based on my understanding, kTLS does not magically works, it's used for zero copy, so you have to send a fd through syscall |
Yep - so the implementation was really straight forward.
Start a TCP listener, wait for a TCP connection to get accepted, and read some N bytes from it and send them to `rustls` via CGO. If we needed more bytes the `rustls` library would signal that, otherwise it would give us some bytes to write back to the connection - which we would do in Go by blindly writing the byte slice into the `net.Conn`.
Once the handshake was complete, we'd pull out the required kTLS secrets from the handshake in `rustls`, and then do the required syscalls in Go to tell the kernel that the `fd` that backed the `net.Conn` is a kTLS `fd`.
After that, future reads/writes on the `net.Conn` would result in proper TLS encryption/decryption without any userspace overhead.
|
One more thing - many better network card have crypto-acceleration and this can be accessed by ktls API, so supporting ktls in golang we are able to offload encryption to network card |
i've used gnet's ktls and other ktls version but i found that if going through cgo, and with multiple goroutines, it seems to crash. e.g. 1000000 goroutines calling cgo seemed not possible. u can probably do 80k max. |
This proposal has been added to the active column of the proposals project |
It looks like rustls (for Rust) makes kTLS possible by allowing access to the key material after the handshake completes. Could that be the right stance for Go as well, to allow use of kTLS without the crypto/tls maintainers needing to take on ownership of all of the moving parts? The QUIC support in crypto/tls is in a similar position, where crypto/tls does the initial handshake and then hands the key material over to its caller. From what I can tell, the discussion at rustls/rustls#198 led to https://docs.rs/rustls/latest/rustls/struct.ExtractedSecrets.html, which in turn enables users to provide their own kTLS wiring. (There's support in crypto/tls already for a Config.KeyLogWriter — but as the rustls maintainers also discovered, that format doesn't include all of the information that the kernel needs to continue the symmetric encryption.) |
Lots of background and a implementation, albeit from 3+ years ago: https://blog.filippo.io/playing-with-kernel-tls-in-linux-4-13-and-go/
Basically, Linux now supports handling TLS encryption in the kernel. The primary benefit here is the possibility of
sendfile
/splice
to work with TLS. Currently, we need to choose between TLS andsplice
(or a custom TLS implementation, I suppose).It would be great to have first class support in go for this.
The text was updated successfully, but these errors were encountered: