6 ms·
Rustls Server-Side Performance
- koakuma-chan 1y agoIt's blazingly fast.
- pzmarzly 1y agoAlso in referent news: "The State of TLS Stacks" by HAProxy devs https://www.haproxy.com/blog/state-of-ssl-stacks https://www.haproxy.com/blog/state-of-ssl-stacks https://news.ycombinator.com/item?id=43912164 https://news.ycombinator.com/item?id=43912164 TLDR OpenSSL days seem to be coming to an end, but Rustls C bindings add not production ready yet.
- Twirrim 1y agoWould love to see compliance and accreditation coming through for native rusttls, like FIPS. That'll unlock a large potential market, which can in turn unlock other markets. You can get FIPS by using some of the third party back-end integration via aws-lc-rs.
- jaas 1y agoThe default cryptographic back-end for Rustls, aws-lc-rs, is FIPS compliant and integrated in a FIPS-compliant way so it's easy to get FIPS compliance with Rustls.
- jaas 1y agoRustls has two C APIs. The first is C bindings for the native Rustls API. This should work great for anyone who wants to use Rustls from C, but it means writing to the Rustls API. The second is C bindings that provide OpenSSL compatibility. This only supports a subset of the OpenSSL API (enough for Nginx but not yet HAProxy, for example), so not everything that uses OpenSSL will work with the Rustls OpenSSL compatibility layer yet. We are actively improving the amount of OpenSSL API surface that we support.
- tialaramex 1y agoI should probably help with that whole OpenSSL compat. thing. Is there guidance somewhere or should I just find something interesting to implement and send over a PR ?
- jaas 1y agoThe repository is here: https://github.com/rustls/rustls-openssl-compat https://github.com/rustls/rustls-openssl-compat We just work with normal issues/PRs, and there is a Rustls discord channel if you want to chat. We'd love your help!
- bastawhiz 1y agoI'm not a Rust guy and I probably won't be any time soon, but Rustls is such an exciting project in my eyes. Projects like BoringSSL are cool and noble in their intentions, but having something that's not just a hygienic codebase but an implicitly safer one feels deeply satisfying. I'm eagerly looking forward to this finding its way into production use cases.
- nyanpasu64 1y agoI wonder if replacing the encryption key every 6 hours would be a good use case for a crossbeam-epoch, though this may be premature optimization, and that library requires writing unsafe code as far as I can tell.
- yencabulator 1y agoYou might like https://docs.rs/arc-swap/latest/arc_swap/ https://docs.rs/arc-swap/latest/arc_swap/
- nyanpasu64 1y agoAIUI epoch GC doesn't require Arc's atomic increment/decrement operations which can be slower than naive loads (https://codeberg.org/nyanpasu64/cachebash https://codeberg.org/nyanpasu64/cachebash), but at this point we're getting into nano-optimization territory.
- dochtman 1y agoWe tried this when we were benchmarking and it was not significantly better than the Arc<RwLock<_>> that we're using now.
- toast0 1y agoI think it is worth optimizing, there's a noticable, but small, dip in handshakes per second going from 1 to 2 threads. If I were to optimize it, and the cycling rate is fixed and long, I would have the global storage be behind a simple Mutex, and be something like (Expiration, oldval, newval), on use, check a threadlocal copy, use it if it's not expired, otherwise lock the global, if the global is not expired, copy it to thread local. If the global is expired, generate a new one, saving the old value so that the previous generation tickets are still valid. You can use a simple Mutex, because contention is limited to the expiration window. You could generate a new ticket secret outside the lock to reduce the time spent while locked, at the expense of generating a ticket secret that's immediately discarded for each thread except the winning thread. Not a huge difference either way, unless you cycle tickets very frequently, or run a very large number of threads.
- toast0 1y agoI wish they included details on how they ran these benchmarks, like they did last year [1]. I'd like to take a look and try to understand why there's such a big difference in handshake performance. I wouldn't expect single threaded handshake performance to vary so much between stacks... it should be mostly limited by crypto operations. Last time, they did say something about having a cpu optimization for handshaking that the other stack might not have, but this is on a different platform and they didn't mention that. I'd also be interested in seeing what it looks like with OpenSSL 1.1.1, given the recent article from HAProxy about difficulties with OpenSSL 3 [2] [1] https://www.memorysafety.org/blog/rustls-performance-outperforms/ https://www.memorysafety.org/blog/rustls-performance-outperf... [2] https://www.haproxy.com/blog/state-of-ssl-stacks https://www.haproxy.com/blog/state-of-ssl-stacks
- jaas 1y agoThis report contains more details about the results discussed in the blog post: https://rustls.dev/perf/2024-11-28-threading/ https://rustls.dev/perf/2024-11-28-threading/
- toast0 1y agoThanks for that ... I got a little bit nerd sniped. I haven't gotten to the bottom of this one, but I dug a bit. On my machine dual-socket Intel(R) Xeon(R) CPU L5640 running 14.2-RELEASE-p3, I found similar differences in speed with the system openssl (3.0.16) and rustls from head (795ae1f5d0435dbc80dac04ec147e85d4970563c). Openssl 3.0.16 (FreeBSD base 14.2-RELEASE-p3) handshakes server TLSv1.3 TLS_AES_256_GCM_SHA384 1275.38 handshakes/s (512 / 0.401448) Rustls: (795ae1f5d0435dbc80dac04ec147e85d4970563c) handshakes TLSv1_3 EcdsaP256 TLS13_AES_256_GCM_SHA384 server server-auth no-resume 1998.39 handshakes/s I looked at a lot of stuff, but no real smoking guns. There's a difference in behavior between the two handshakes, but it's not that different. openssl-bench generates 4 application packet wrappers for the 'first flight', whereas rustls generates one which contains the 4 messages of encrypted extensions, server cert, server cert verify, server handshake finished; this seems like it could be significant, but I couldn't easily undo it to test. Also, openssl-bench generates 2 more application packets after receiving the client handshake finished; I'm pretty sure those are tickets, but turning off ticket generation was ~ 1% improvement, so whatever. However, one of my friends suggested aws-lc might just be super fast, so I ran openssl-bench linked against that and saw a big improvement. So I went ahead and tried with all the options from FreeBSD pkg. Here's my list of results: aws-lc-1.48.4 (freebsd pkg) handshakes server TLSv1.3 TLS_AES_256_GCM_SHA384 2478.93 handshakes/s (512 / 0.206541) openssl111-1.1.1w_2 (freebsd pkg) handshakes server TLSv1.3 TLS_AES_256_GCM_SHA384 1773.9 handshakes/s (512 / 0.28863) openssl-3.0.16,1 handshakes server TLSv1.3 TLS_AES_256_GCM_SHA384 1333.5 handshakes/s (512 / 0.383951) openssl31-3.1.8 handshakes server TLSv1.3 TLS_AES_256_GCM_SHA384 1387.69 handshakes/s (512 / 0.368958) openssl32-3.2.4 handshakes server TLSv1.3 TLS_AES_256_GCM_SHA384 1353.54 handshakes/s (512 / 0.378267) openssl33-3.3.3 handshakes server TLSv1.3 TLS_AES_256_GCM_SHA384 1406.62 handshakes/s (512 / 0.363994) openssl34-3.4.1 handshakes server TLSv1.3 TLS_AES_256_GCM_SHA384 1393.34 handshakes/s (512 / 0.367463) openssl35-3.5.0.b1 handshakes server TLSv1.3 TLS_AES_256_GCM_SHA384 1155 handshakes/s (512 / 0.443289) boringssl-0.0.0.0.2025.03.27.01_1 did not manage to get a matching cipher libressl-4.0.0_1 (does not compile, don't care to fix) So.... in my testing, on my machine, rustls is faster than openssl-bench linked against openssl and openssl 1.1.1 is faster than openssl 3.x, but openssl-bench linked against aws-lc is faster than rustls. I'll try to get ahold of the authors tomororow and suggest they add openssl-bench linked against aws-lc to their test.
- hardwaresofton 1y agoAt the risk of sounding like a crustacean cult member, really hope the skeptics read this post. No hype, no drama, just slow, steady high perf incremental improvement in a crucially important area without any feet blown off. I feel bad for other/new system languages, you get so much for the steeper learning curve with Rust (cult membership optional). And I think it’s genuinely difficult to reproduce Rust’s feature set.
- landl0rd 1y agoI stole these graphs for a branch of that thread ffmpeg started on twitter. The one where they were flaming rav1d vs dav1d performance to attack Rust generally. I don't like the RiiR cult. I do like smart use of a safer language and think long-term it can get better than C++ with the right work.
- LoganDark 1y ago> I don't like the RiiR cult. For certain types of people, Rust has a way of just feeling better to use. After learning Rust I just can't imagine choosing to use C or C++ for a future project ever again. Rust is just too good.
- WJW 1y agoChoosing Rust for new projects is very different than trying to rewrite an existing codebase with thousands of hours poured into it. Or worse, demanding that someone else do that for you for free.
- laerus 1y agoRewriting could also make sense if there is a chance to improve the architecture based on the experience with the existing codebase. Something that would otherwise be impossible to even consider.
- josephg 1y agoPeople keep saying this. But in my experience, directly porting code from one language to another is much easier that people think. I can do maybe about 500 lines per day depending on the language similarity. ChatGPT is great for doing a first pass - though it will add small, subtle bugs in the process. I’m not arguing that we should rewrite everything in rust. C and C++ are fine languages. But sometimes it really is better to just have your code in a different language rather than deal with FFI. For example, I have some collaborative text editing code in rust and recently I just ported the whole thing to typescript, because it’s just straight out easier to use in a browser that way, compared to dealing with a wasm bundle. I think the big mistake people make when rewriting into a different language is doing a refactor at the same time. This is the wrong way to go about it. First port directly the code you have. Then port your tests and get them passing in the new language. Then refactor. Obviously there’s always some language differences - but ideally you can confine differences within modules, and keep most of the module boundaries intact through the rewrite. You can also refactor before translating your code. If I were porting something to rust that wouldn’t pass the borrow checker, this is probably what I’d do. First refactor everything to make the borrow checker happy - so for example, make sure your structs / classes are in a strict tree. Then get tests passing. Translate between languages and cleanup. If you approach it like that, rewriting code is a largely mechanical process. It really takes a lot less time than people think to translate code, since you don’t actually have to understand every single line to do it correctly. So the time taken scales based on the number of lines of code. Not the number of hours it took to write! And then, if you want to refactor your new program at the end, go for it.
- thevivekshukla 1y agoWow this is fast. However I tried rustls with redis for my axum application, for some reason it was not working, even though my self signed ca certificate was updated in my system's local CA store. After a lot of try I gave up then thought about trying native tls, and it worked in first go.
- whizzter 1y agoThe irony is that due to CA stores (and how verification is handled) it's usually a tad more ficklish to replace TLS clients than TLS servers. Was there no way to provide a custom CA store (that only included your self signed one)?
- dochtman 1y agoDid you file an issue or ask in the rustls Discord channel? We're happy to help.
- encom 1y ago>Discord
- aberoham 1y agoDid you try rustls-tls-native-roots? rustls-tls defaulting to only use the webpki bundle caught me off guard on a system with a bespoke CA
- PoignardAzur 1y agoThat name is confusing. Reading the headline, I first thought it was about the deprecated language server and was very confused.
- jjice 1y agoThat was rls, but I can see what you mean from the name of the package once I looked at it again. https://github.com/rust-lang/rls https://github.com/rust-lang/rls
- lifeinthevoid 1y agoOut of curiosity, rustls uses aws-lc-rs which in turn uses aws-lc, which is in turn "based on code from the Google BoringSSL project and the OpenSSL project." You're trying to get rid of OpenSSL, but you're actually relying on OpenSSL code. Sounds a bit iffy imo. Can somebody provide a bit more depth here? Or is it just the OpenSSL TLS API that is hopelessly confusing and bug inducing? I can imagine that the crypto primitives in OpenSSL are very solid.
- jaas 1y agoRustls uses aws-lc-rs for cryptography, which, roughly speaking, is based on the cryptography from BoringSSL, which is a heavily modified fork of OpenSSL from a long time ago. I'm not sure how similar OpenSSL and aws-lc-rs cryptography implementations are today (maybe someone else knows?), but it's probably not accurate in a useful way to say that aws-lc-rs just uses cryptography from OpenSSL. In any case, OpenSSL does a whole bunch of things, and one of those is providing low-level cryptographic routines. When people talk about issues with OpenSSL, they're usually not (in my experience) talking about issues with its low-level cryptographic routines. They're talking about things like the TLS implementation and API. Rustls has its own Rust code for the TLS protocol and certificate parsing/validation, which doesn't come, directly or by lineage, from OpenSSL or any OpenSSL derivatives.
- tialaramex 1y agoYes the core thing everybody actually wants is the constant time cryptographic primitives, and it's not at all practical to attempt those in a high level programming language like C or Rust, they're always raw machine code, or - which is less awful to work with - assembler. So yeah it's roughly the same code in all of the projects you mentioned - the correct machine code for a high quality ChaCha20 implementation on x86-64 is the same if the rest of your TLS implementation is C (OpenSSL) or Rust (rustls) or like, hand written Perl (please tell me nobody did this) Although of course the Rust compiler has no way to inspect this ChaCha20 primitive and check it is memory safe, we can "vouch" for it, and these primitives have been eyeballed by a huge number of people since they're so widely used so it feels as reasonable as the claim that ChaCha20 itself works, which has been considered by plenty of cryptanalysis experts from government and industry. Pretty much everything else is Rust, so the bit-twiddling inside a DER implementation to parse certificates is Rust, the TLS handshake implementation is Rust, and so on.
- dlgeek 1y agoBetween this and https://www.haproxy.com/blog/state-of-ssl-stacks https://www.haproxy.com/blog/state-of-ssl-stacks, I think we need to start accepting the idea that OpenSSL is not the right way forward for anything performance sensitive. Given how aws-lc powers both of these articles, I'm curious how Rustls compares to s2n-tls - AWS's TLS library to go along with aws-lc.