-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Consider switching to rustls
as the default
#2025
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
Comments
Linking a good summary on the pros and cons of |
I (obviously) think it would be great to consider this for a next semver-breaking change. Should consider this in tandem with the decision what rustls crypto provider to enable by default (see #2136). |
I'll include some thoughts in here which after some discussion, could probably become better documented "design principles".
|
This feels like a simplistic way of trading off non-functional requirements; if the latter option is 100% better in 99% of cases, would you still pick the option that works in more cases? I'd argue there's some kind of expected value thing here which requires coming up with a weight for any number of non-functional requirements, like maybe:
It looks like native-tls doesn't support TLS 1.3 which seems likely to affect performance and security and it uses OpenSSL on Linux which has a pretty spotty security history. rustls doesn't support TLS 1.1 (and earlier) which are officially deprecated anyway but which I guess could come up but should be increasingly rare. Also at this stage I think rustls is in a really good situation in terms of maintenance with two full-time maintainers so it's likely that issues (that are not by design) can fixed very quickly. I would also argue that, as a Rust HTTP client built on hyper, a Rust HTTP protocol stack, all other things being equal it is nicer for integration and ergonomics (building etc) to use Rust for as much of the internals as possible, and doing so will improve quality of the Rust components over time because they get more exposure (many eyes, shallow bugs). (I find the case for trust-dns a little harder to make because it is more resource-constrained on maintenance.) As for binary size: I think it is already the cases that users who are sensitive to binary size are more likely to pick other clients (like ureq or curl), so I'm not sure it should be an important driver. |
I mean yea, including more criteria can help make a better decision. It was just an axis I started with. (It looks like native-tls supporting TLS 1.3 could be close, FWIW.) But I support much of what you said regarding rustls.
In general I'd agree with the sentiment, but in this case, I think native-tls actually has a better story here for most targets. Most users won't have to compile anything "not Rust". With rustls, whether using ring or aws-lc, you need to compile C. rustls' new default backend requires having cmake. I don't think those things are the end of the world, but they do add some friction. I'll also add, the way reqwest's features are structured, where |
That's fair! FWIW, I'm not a fan of the decision to make aws-lc-rs the default crypto provider for rustls -- I think the additional friction isn't worth the benefits for most downstream users. But of course reqwest could just decide to keep ring as the default for rustls' crypto provider.
Sure, I think you're making valid points -- I just also want to argue the other side. |
🚨 🚨 As a general call for comments, if you (any of you) need native-tls over rustls, or if the default change were to harm you, or you know of specific situations as such, please chime in here. 🚨 🚨 |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
rustls
as the default, and make openssl
optionalrustls
as the default
Since |
It is possible you might not be a part of "most people" in this particular regard. I'm sure other rustls crypto providers (as well as native-tls) will still be an option. (So far it seemed like ring is on security-only maintenance. That means no further development for things like new cipher suites -- like post-quantum cryptography.) (When is the last time you've tried aws-lc-rs? Have you filed issues against it to describe your challenges with cross-compilation?) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Three months ago when it broke our armv7 and netbsd CD builds during a release when updating dependencies. 😅 And if I remember right, there was already an issue opened for some parts of the breakage, and I think I also opened another one. |
This isn't true. |
CMake doesn't have to be necessary for building that other thing. I suggest filing an issue in its issue tracker about making it easier to build with fewer prerequisites. I don't think people should make choices like this based on ease of building. |
Will do!
While I agree with the sentiment, I need to say that when you consider the CI/CD part of it, it should be for sure a concern. Not everyone can spend hours on diagnosing build issues, when the Rust build ecosystem is usually |
@seanmonstar wrote:
I agree 100% with this. The main issue with native-tls, IMO, is that it defaults to OpenSSL when there isn't a native TLS stack. I don't think that's justified. But for targets like Windows, Android, macOS/iOS and other Apple targets, where there is a native TLS stack and where the native TLS stack is quite good, I think it isn't clear that switching away from the native TLS stack is an advantage. 10 years ago using native TLS libraries was a lot more scary than today. |
Also, I saw above a mention of rustls-platform-verifier. rustls-platform-verifier was created a for 2 particular purposes:
However, long-term the combination of Rustls + rustls-platform-verifier is questionable because certificate verification is still probably the riskiest attack surface in native crypto/TLS stacks today. For teams doing a high-risk "rewrite it in Rust" ground-up rewrite like the creators of rustls-platform-verifier, it was the right trade-off. Long-term, probably not. My understanding is that even Microsoft Edge isn't using the native certificate verifier any more. |
You made a widely advertised announcement that resulted in the rustls team taking over security-only maintenance. I have not seen an announcement from you that feature development for ring has been restarted, so as far as I understand the current status quo is still that there will be no further feature development. There has been a 0.17.13 announcement which includes a new feature, but in my view that doesn't provide a good indication of future activity.
In the absence of other significantly distinguishing features, we've seen a significant number of folks for whom ease of building is an important issue. If you think other distinctions between (for example) aws-lc-rs and ring are a better basis for selection, I'd be interested in your arguments (might make good material for the ring README, for example).
While the underlying TLS stacks might be quite good, it seems that to this day native-tls does not support TLS 1.3 which by itself seems like a substantial disadvantage.
One reason we now recommend rustls-platform-verifier is that on non-Linux (including Android) platforms, the platform verifier is likely to have more precise trust information (like precise trust before/trust after mechanics) that rustls-native-certs doesn't provide (it just has "certificate included in the OS set" or not). Additionally rustls-native-certs does not provide any mechanism for refreshing the set of trusted roots at run-time (after the initial load), which could be an issue for long-running processes. While the latter is arguably straightforward to solve, I don't know that there are good platform APIs which can be used to extract the precise trust information, nor is it necessarily clear exactly what precise trust mechanics are employed by the platform vendors. |
Most applications don't care about TLS 1.3 vs TLS 1.2 though, TBF. I updated the native-tls issue with what I found about the Windows support. Because of the popularity of old Windows and Android versions, and Linux, there definitely is a need for a non-native solution. But I don't think the typical iOS application is better off with packaging its own crypto/TLS library. RE: rustls-platform-verifier, I initiated its creation before it was open source, so I understand the trade-offs. My point was that the native certificate verifier is probably the most dangerous component of the native TLS stack. I believe subsequent to the creation of rustls-platform-verifier, the Chrome team / BoringSSL did find a way to reliably hook into the native certificate stores. Again, my understanding is that even Edge doesn't use the native API on Windows anymore; from https://textslashplain.com/2022/12/06/tls-certificate-verification-changes-in-edge/:
Anyway, subsequent to me posting my comment, I saw an announcement that this was pretty much already decided, so I won't belabor the point any further. |
On easy of building. For me easy of building is very important. Also I like static binaries, so I often compile my code with
Obviously, I support making rustls default |
🚨 🚨 Alrighty, an update: it seems pretty clear to me: We should change the default to rustls.Because native-tls means:
rustls with aws-lc doesn't require cmake on the common platforms. And for anyone who needs native-tls, well you can always set cargo features to build it. Now on to the next bikeshed: Does changing the default require a breaking change?Theoretically, I put a lot of effort into making it so the I still suspect there might be a little bit of breakage, though. Is it enough to be considered breaking according to the typical Rust library stability promises? I kind of wish there was a decent way to "try" publishing it that way, and see what breakage existed in reality (like how the Rust Project can do a crater run). Is a bump to reqwest v0.13 a big deal anyways? |
It seems to still require it on Windows |
Oh, I must have missed that. Yes, Windows is common in my assessment. Is there an issue tracking when it will no longer be needed on Windows? |
My understanding is that nasm has not been required on Windows since aws-lc-rs 1.9.0 (September 2024 - ref) |
I think not, especially if accompanied with some text on what that possible breakage is. If there is no real breakage, people would be less anxious bumping. If there is breakage where semver number implies there isn't, people would lose some trust. Better be safe, while only risking a bit of churn. |
It'll start an era with quite a bit of duplicate dependencies while library crates with limited maintenance capacity upgrade. Might not be too bad though? What will be the default verifier? |
Cool! Some notes:
[package]
name = "client-example"
version = "0.1.0"
edition = "2024"
[dependencies]
http = "1.3.1"
http-body-util = "0.1.3"
hyper = "1.6.0"
hyper-rustls = "0.27.6"
hyper-util = "0.1.13"
rustls = "0.23.27"
tokio = { version = "1.45.1", features = ["full"] }
//! Based on https://github.com/rustls/hyper-rustls/blob/e6a23710aa02b81ccf03d54801df8faace53eb68/examples/client.rs
//! Simple HTTPS GET client based on hyper-rustls
use http::Uri;
use http_body_util::{BodyExt, Empty};
use hyper::body::Bytes;
use hyper_rustls::ConfigBuilderExt;
use hyper_util::{client::legacy::Client, rt::TokioExecutor};
use std::str::FromStr;
#[tokio::main]
async fn main() {
// Set a process wide default crypto provider.
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
// Root-CA store is native cert store
// Prepare the TLS client config
// Default TLS client config with native roots
let tls = rustls::ClientConfig::builder()
.with_native_roots()
.unwrap()
.with_no_client_auth();
// Prepare the HTTPS connector
let https = hyper_rustls::HttpsConnectorBuilder::new()
.with_tls_config(tls)
.https_or_http()
.enable_http1()
.build();
// Build the hyper client from the HTTPS connector.
let client: Client<_, Empty<Bytes>> = Client::builder(TokioExecutor::new()).build(https);
// sends a GET request, inspects
// the returned headers, collects the whole body and prints it to
// stdout
let res = client
.get(Uri::from_str("https://www.rust-lang.org").unwrap())
.await
.unwrap();
println!("Status:\n{}", res.status());
println!("Headers:\n{:#?}", res.headers());
let body = res
.into_body()
.collect()
.await
.unwrap()
.to_bytes();
println!("Body:\n{}", String::from_utf8_lossy(&body));
} Docker file for build machine: FROM debian:sid
ENV LC_ALL C.UTF-8
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates gcc libc6-dev
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y
RUN . "$HOME/.cargo/env"; rustup target add x86_64-unknown-linux-musl Docker file for run machine: FROM debian:sid
ENV LC_ALL C.UTF-8
RUN apt-get update
#!/bin/bash
set -e
mkdir prog
cd prog
cargo init
cargo add --no-default-features -F aws_lc_rs rustls
cargo build
rm -r Cargo.lock target
time -p cargo build
rm -r Cargo.lock target
time -p cargo build
cargo build --release
rm -r Cargo.lock target
time -p cargo build --release
rm -r Cargo.lock target
time -p cargo build --release
cargo remove rustls
cargo add --no-default-features -F ring rustls
cargo build
rm -r Cargo.lock target
time -p cargo build
rm -r Cargo.lock target
time -p cargo build
cargo build --release
rm -r Cargo.lock target
time -p cargo build --release
rm -r Cargo.lock target
time -p cargo build --release
|
Uh oh!
There was an error while loading. Please reload this page.
I would like to propose Reqwest switches to
rustls
crate, probablyrustls-tls-native-roots
variant of it, as the new default option for tls. Rustls seems like a highly stable and secure product, and most importantly - it does not require to compile non-rust code during the build process. This would obviously be a breaking change, and would have to be discussed and coordinated appropriately. Thx!🚨 🚨 As a general call for comments, if you (any of you) need native-tls over rustls, or if the default change were to harm you, or you know of specific situations as such, please chime in here. 🚨 🚨
The text was updated successfully, but these errors were encountered: