# How to Configure DNS Resolution Settings in the iroh Endpoint Builder

> Configure DNS resolution settings in iroh by calling Builder::dns_resolver() and passing a custom DnsResolver instance. Learn how to use with_nameserver() for seamless setup.

- Repository: [number zero/iroh](https://github.com/n0-computer/iroh)
- Tags: how-to-guide
- Published: 2026-06-22

---

**To configure DNS resolution settings in iroh, call `Builder::dns_resolver()` on the endpoint builder and pass a custom `DnsResolver` instance created via `DnsResolver::builder()` or the `with_nameserver()` helper.**

The iroh networking library (n0-computer/iroh) exposes DNS configuration through its endpoint builder pattern defined in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs). While the default configuration automatically uses the host operating system's DNS settings, you can inject a custom resolver to specify nameservers, enable DNS-over-HTTPS (DoH), or share resolution caches across multiple endpoints.

## Understanding the DNS Resolution Components

The DNS configuration API spans two primary modules. The `Builder` struct in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) (lines 74-87) holds an optional `dns_resolver` field and exposes the `dns_resolver()` setter method. The actual resolution logic lives in [`iroh-dns/src/dns.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/dns.rs), where the `DnsResolver` type wraps a `hickory-dns` resolver and provides the `builder()` entry point (lines 349-351) for fine-tuned configuration.

### The Role of DnsResolver

`DnsResolver` is an `Arc`-wrapped handle to an asynchronous DNS client. When you customize DNS resolution settings, you construct this resolver first, then inject it into the endpoint builder before calling `bind()`. The resolver is used for all hostname lookups, including relay hostnames and PKARR address resolutions.

## Using the Default System DNS Resolver

If you do not explicitly call `dns_resolver()`, the endpoint builder automatically creates a default resolver that reads the system's DNS configuration from [`/etc/resolv.conf`](https://github.com/n0-computer/iroh/blob/main//etc/resolv.conf) (or the platform-specific equivalent).

```rust
use iroh::endpoint::{Builder, Preset};

let endpoint = Builder::new(Preset::default())
    .bind()
    .await?;

```

This default requires no additional code and follows the host system's resolver behavior.

## Configuring a Single Custom Nameserver

To route DNS queries through a specific UDP nameserver, use the `DnsResolver::with_nameserver()` convenience helper implemented in [`iroh-dns/src/dns.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/dns.rs) (lines 342-347). This creates a resolver configured for a single upstream server.

```rust
use iroh::{endpoint::Builder, dns::DnsResolver};
use std::net::SocketAddr;

let nameserver: SocketAddr = "1.1.1.1:53".parse().unwrap();

let dns_resolver = DnsResolver::with_nameserver(nameserver);
let endpoint = Builder::new(Preset::default())
    .dns_resolver(dns_resolver)
    .bind()
    .await?;

```

## Advanced DNS Resolution Settings (Multiple Nameservers and DoH)

For production deployments requiring redundant nameservers or encrypted DNS, use the full `DnsResolver::builder()` API exposed in [`iroh-dns/src/dns.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/dns.rs) (lines 340-368). This builder allows you to specify multiple nameservers with different protocols—including UDP, TCP, and TLS (for DNS-over-HTTPS).

```rust
use iroh::dns::{DnsResolver, DnsProtocol, Builder as DnsBuilder};
use std::net::SocketAddr;

let ns1: SocketAddr = "8.8.8.8:53".parse().unwrap();
let ns2: SocketAddr = "8.8.4.4:53".parse().unwrap();
let doh_addr: SocketAddr = "1.1.1.1:443".parse().unwrap();

let dns_resolver = DnsBuilder::default()
    .with_nameserver(ns1, DnsProtocol::Udp)
    .with_nameserver(ns2, DnsProtocol::Udp)
    .with_nameserver(doh_addr, DnsProtocol::Tls)
    .build();

let endpoint = Builder::new(Preset::default())
    .dns_resolver(dns_resolver)
    .bind()
    .await?;

```

The `DnsProtocol` enum (defined in [`iroh-dns/src/attrs.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/attrs.rs)) specifies whether to use **Udp**, **Tcp**, or **Tls** for each upstream server. You can also configure custom TLS client configurations via the builder's `tls_client_config()` method.

## Sharing DNS Resolvers Across Endpoints

Because `DnsResolver` is wrapped in an `Arc` internally, you can share a single resolver instance across multiple endpoints to reduce socket overhead and maintain a consistent DNS cache.

```rust
use iroh::{endpoint::Builder, dns::DnsResolver};
use std::sync::Arc;

let resolver = Arc::new(DnsResolver::with_nameserver("9.9.9.9:53".parse().unwrap()));

let ep1 = Builder::new(Preset::default())
    .dns_resolver((*resolver).clone())
    .bind()
    .await?;

let ep2 = Builder::new(Preset::default())
    .dns_resolver((*resolver).clone())
    .bind()
    .await?;

```

Sharing the resolver ensures that DNS cache entries and connection pools are reused between endpoints according to the n0-computer/iroh source code implementation.

## Summary

- Use **`Builder::dns_resolver()`** in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) to inject a custom resolver into the endpoint builder.
- Create resolvers via **`DnsResolver::builder()`** (lines 349-351 in [`iroh-dns/src/dns.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/dns.rs)) for multi-server or TLS configurations.
- Use **`with_nameserver()`** (lines 342-347) for quick single-nameserver setups.
- Reference **`DnsProtocol`** in [`iroh-dns/src/attrs.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/attrs.rs) to specify Udp, Tcp, or Tls transport protocols.
- Wrap resolvers in **`Arc`** to share them efficiently across multiple endpoint instances.

## Frequently Asked Questions

### How do I change the DNS server for an iroh endpoint?

Call `Builder::dns_resolver()` and pass a `DnsResolver` created with `DnsResolver::with_nameserver()` or the full `DnsResolver::builder()` API. This overrides the default system resolver with your specified upstream server.

### Does iroh support DNS-over-HTTPS?

Yes. When building a custom `DnsResolver`, use `DnsProtocol::Tls` with the `with_nameserver()` method to configure DNS-over-HTTPS (DoH) endpoints. You may also need to configure TLS settings via the builder's `tls_client_config()` method.

### Can I share a DNS resolver between multiple iroh endpoints?

Yes. `DnsResolver` is designed to be cloneable and internally uses `Arc` for reference counting. Create the resolver once, then clone it (or dereference from an `Arc`) to pass into multiple `Builder::dns_resolver()` calls before binding each endpoint.

### Where is the default DNS resolver configured in iroh?

The default resolver logic resides in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) within the `Builder` implementation (lines 74-87). When no custom resolver is provided, the builder automatically instantiates a `DnsResolver` that reads the system's DNS configuration using platform-specific defaults.