How to Configure TLS and Crypto Providers in Iroh Endpoints

Iroh endpoints use the rustls TLS stack, configured through the CaTlsConfig and TlsConfig types in iroh-relay/src/tls.rs, allowing you to specify root certificates, custom verification logic, and crypto providers via default_provider() when establishing secure connections.

The iroh networking library delegates all TLS operations to the rustls crate, exposing a unified configuration API through the tls module. When you configure TLS and crypto providers in iroh endpoints, you create a CaTlsConfig that defines certificate verification behavior, then combine it with a crypto provider to build a rustls::ClientConfig that the endpoint consumes.

Core TLS Configuration Types

The TLS implementation in iroh centers on two primary types defined in iroh-relay/src/tls.rs.

CaTlsConfig

The CaTlsConfig struct controls how the client verifies server certificate chains. It stores a mode enum and an optional list of extra root certificates, supporting five distinct verification strategies:

  • EmbeddedWebPki: Uses the built-in Mozilla root store (webpki_roots::TLS_SERVER_ROOTS)
  • System: Delegates to the OS certificate store when the platform-verifier feature is enabled
  • ExtraRootsOnly: Trusts only explicitly supplied root certificates
  • CustomServerCertVerifier: Accepts a custom rustls::client::ServerCertVerifier implementation
  • InsecureSkipVerify: Bypasses verification (test builds only)

TlsConfig

The TlsConfig type bundles a socket address with either a CaTlsConfig (for clients) or a CertConfig containing a rustls::ServerConfig (for servers). This structure is attached to iroh endpoints such as relay clients or DNS resolvers.

Configuring Certificate Verification for Clients

Using Embedded Mozilla Roots

By default, iroh trusts the Mozilla root certificate store. Create this configuration using CaTlsConfig::embedded():

use iroh::tls::CaTlsConfig;

let ca_cfg = CaTlsConfig::embedded();

Leveraging the OS Certificate Store

On platforms supporting the platform-verifier feature, delegate verification to the operating system:

let ca_cfg = CaTlsConfig::system();

Trusting Custom Root Certificates

For private CAs or self-signed certificates, supply DER-encoded certificates directly:

use iroh::tls::CaTlsConfig;
use rustls::pki_types::CertificateDer;

let my_root: CertificateDer<'static> = // ... load your certificate
let ca_cfg = CaTlsConfig::custom_roots(vec![my_root]);

Even when system() is unavailable (such as on Android), the EmbeddedWebPki mode loads the Mozilla roots and appends your custom roots.

Implementing Custom Verification Logic

For advanced scenarios, provide a custom ServerCertVerifier:

let ca_cfg = CaTlsConfig::custom_server_cert_verifier(|| {
    // Return your custom verifier implementation
    Box::new(MyCustomVerifier)
});

Selecting Crypto Providers

The default_provider() Function

Iroh exports default_provider() from iroh-relay/src/tls.rs to access the global rustls::crypto::CryptoProvider. This returns either the ring or aws-lc-rs implementation depending on your feature flags:

use iroh::tls::default_provider;

let crypto_provider = default_provider();

Building Client Configurations for Endpoints

To apply TLS settings to an endpoint, convert your CaTlsConfig into a rustls::ClientConfig using the client_config() method. This method builds the configuration by calling dangerous().with_custom_certificate_verifier(...) internally when necessary:

use iroh::{tls::{CaTlsConfig, default_provider}, util::RelayBuilder};

let ca_cfg = CaTlsConfig::embedded();
let client_cfg = ca_cfg.client_config(default_provider())
    .expect("TLS client config creation failed");

let relay = RelayBuilder::new()
    .tls_config(client_cfg)
    .build();

Server-Side TLS Configuration

For server endpoints (such as relay servers), construct a TlsConfig containing a CertConfig::Manual with a rustls::ServerConfig. The implementation in iroh/tests/patchbay/util.rs demonstrates this pattern using self_signed_tls_certs_and_config():

// Example pattern from iroh/tests/patchbay/util.rs
let (tls_config, cert) = self_signed_tls_certs_and_config();
// The server stores this as: relay.tls = Some(tls_config);

Test-Only Insecure Configuration

For testing environments, iroh provides CaTlsConfig::insecure_skip_verify(), which creates a make_dangerous_client_config() helper that trusts any server certificate. This is restricted to test builds via #[cfg(test)] or test-utils feature flags:

use iroh::tls::CaTlsConfig;

let ca_cfg = CaTlsConfig::insecure_skip_verify();
let client_cfg = ca_cfg.client_config(default_provider()).unwrap();

Warning: Never use this mode in production; the crate enforces this restriction through conditional compilation.

Integration Points

The TLS configuration connects to several iroh subsystems:

  • Relay Client: The relay crate calls tls::CaTlsConfig::client_config() to obtain a ClientConfig for the underlying QUIC or hyper transport
  • DNS-over-HTTPS: The resolver in iroh-dns-server/src/http/tls.rs builds rustls::ClientConfig using the same patterns
  • Re-exports: The top-level iroh crate re-exports these symbols from iroh/src/tls/mod.rs for convenient access

Summary

  • Iroh uses rustls for all TLS operations, with configuration centralized in iroh-relay/src/tls.rs
  • CaTlsConfig controls verification via embedded(), system(), custom_roots(), or custom verifiers
  • default_provider() returns the active crypto implementation (ring or aws-lc-rs)
  • client_config() converts CaTlsConfig into a rustls ClientConfig for endpoint consumption
  • TlsConfig handles server-side configuration with CertConfig::Manual
  • Insecure skip verification is available only in test builds via insecure_skip_verify()

Frequently Asked Questions

How do I configure iroh to use my company's internal CA?

Load your CA certificate in DER format and pass it to CaTlsConfig::custom_roots(). This mode trusts only your specified roots, ignoring the Mozilla and OS stores. The configuration is created in iroh-relay/src/tls.rs and accepts a Vec<CertificateDer<'static>>.

What is the difference between CaTlsConfig and TlsConfig?

CaTlsConfig defines certificate verification behavior for clients (whether to trust Mozilla roots, OS stores, or custom certificates), while TlsConfig bundles the certificate configuration with a socket address and is used by both clients and servers. Servers use TlsConfig with CertConfig::Manual containing a rustls::ServerConfig.

Which crypto providers does iroh support?

Iroh supports the ring and aws-lc-rs crypto providers through rustls. The default_provider() function returns whichever implementation is enabled via feature flags, allowing you to configure endpoints to use hardware-accelerated cryptography where available.

Can I disable TLS certificate verification in production?

No. The insecure_skip_verify() method is gated behind #[cfg(test)] or the test-utils feature flag. The source code in iroh-relay/src/tls.rs explicitly restricts this dangerous configuration to test builds only, preventing accidental deployment of insecure endpoints.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →