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-verifierfeature is enabled - ExtraRootsOnly: Trusts only explicitly supplied root certificates
- CustomServerCertVerifier: Accepts a custom
rustls::client::ServerCertVerifierimplementation - 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 aClientConfigfor the underlying QUIC or hyper transport - DNS-over-HTTPS: The resolver in
iroh-dns-server/src/http/tls.rsbuildsrustls::ClientConfigusing the same patterns - Re-exports: The top-level
irohcrate re-exports these symbols fromiroh/src/tls/mod.rsfor 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →