aberoham/repro-custom-ca

★ 1Forks 0RustGitHub ↗Compare

README

Rustls Native CA Reproduction Sample

This sample code is designed to demonstrate how reqwest behaves with and without the rustls-tls-native-roots feature when attempting to connect to an HTTPS server that uses a custom Certificate Authority (CA) trusted at the operating system level. Custom root CAs are common in strict corporate network environments, both for private internal CAs or for outbound "man-in-the-middle" secure internet gateways such as Zscaler or Cloudflare Warp.

Prerequisites

  • Rust and Cargo installed (see rustup.rs)
  • (Optional but recommended for full testing) An HTTPS server endpoint that is:
    • Signed by a custom CA.
    • The custom CA certificate must be installed and trusted in your operating system's native certificate store.

Code Structure

  • src/main.rs: Contains the Rust code that uses reqwest to fetch a URL.
  • Cargo.toml: The project manifest. You will modify this file to switch between reqwest's TLS features.

How to Build and Run

  1. Clone this repository (if you haven't already):

    # git clone <repository-url>
    # cd repro-custom-ca
  2. Modify src/main.rs (Optional but Recommended for Real Test): Open src/main.rs and change the url_to_fetch variable to point to your HTTPS server that uses a custom CA.

    // src/main.rs
    let url_to_fetch = "https://your-custom-ca-protected-server.example.com/";

    If you don't have such a server, you can use the default https://self-signed.badssl.com/ or any public URL, but the specific CA issue won't be directly observable without a custom CA setup.

  3. Configure reqwest features in Cargo.toml:

    • Scenario 1: Simulating the issue (without native roots) Edit Cargo.toml to use only the rustls-tls feature:

      # Cargo.toml
      [dependencies]
      tokio = { version = "1", features = ["full"] }
      reqwest = { version = "0.11", features = ["rustls-tls"], default-features = false }
      # Comment out or remove other reqwest lines
    • Scenario 2: Simulating the fix (with native roots) Edit Cargo.toml to use the rustls-tls-native-roots feature:

      # Cargo.toml
      [dependencies]
      tokio = { version = "1", features = ["full"] }
      reqwest = { version = "0.11", features = ["rustls-tls-native-roots"], default-features = false }
      # Comment out or remove other reqwest lines
  4. Build and Run: In your terminal, from the repro-custom-ca directory, run:

    cargo run

Expected Behavior

  • Scenario 1 (with rustls-tls only): If url_to_fetch points to a server protected by a custom CA (that is trusted by your OS but not in webpki-roots), the program is expected to fail with a certificate validation error. This is because rustls by default doesn't check the OS native certificate store.

  • Scenario 2 (with rustls-tls-native-roots): If url_to_fetch points to the same server, the program is expected to succeed. The rustls-tls-native-roots feature enables reqwest (via rustls) to load CAs from the OS native certificate store, thus trusting your custom CA.

This sample helps illustrate why the rustls-tls-native-roots feature is important for applications like Next.js/Turbopack that need to operate correctly in diverse network environments, including those with custom CAs (e.g., corporate proxies or internal services).

Contributors

aberoham

Issues