How iroh’s PkarrResolver Enables Public‑Key‑Only Connections
The PkarrResolver resolves an EndpointId (public key) into verified network addresses by fetching a cryptographically signed packet from a pkarr relay and verifying it against the known public key, enabling connections without prior address configuration.
The PkarrResolver in the n0-computer/iroh repository provides a decentralized address lookup mechanism that allows peers to connect using only a public key. By querying a pkarr relay for signed endpoint information and cryptographically verifying the returned packet, this component eliminates the need for out-of-band address distribution, making public-key-only connectivity possible in the iroh networking stack.
How PkarrResolver Works Under the Hood
The resolution process follows a strict three-phase pattern that bridges the gap between cryptographic identity and network reachability.
Step 1: Building the Resolver with PkarrResolverBuilder
In iroh/src/address_lookup/pkarr.rs, the PkarrResolverBuilder::new function (line 442) constructs the resolver with the URL of a pkarr relay, such as the production relay at https://dns.iroh.link/pkarr. The builder accepts optional configurations including a custom DNS-over-HTTPS resolver, TLS settings, and an AddrFilter that restricts which addresses the resolver exposes to the application. Once configured, the builder produces a PkarrResolver instance ready to perform lookups.
Step 2: Querying the Public Key via HTTP
When the application calls PkarrResolver::resolve (line 499 in pkarr.rs), the resolver performs an HTTP GET request to the endpoint {relay}/pkarr/{endpoint_id}. The endpoint_id is the target peer’s public key. The relay returns a SignedPacket containing the public key, a TTL, and a list of EndpointInfo entries that hold the actual socket addresses (IP and port combinations) and optional QUIC or relay information.
Step 3: Cryptographic Verification and Address Extraction
Before returning any addresses, the resolver must verify the packet’s authenticity. According to the implementation in iroh-dns/src/pkarr.rs, the resolver calls SignedPacket::verify to validate the signature against the public key provided in the EndpointId. If verification succeeds, the payload is decoded into EndpointInfo structures. The resolver then applies any configured address filters and returns the verified list of reachable network addresses to the caller.
Key Design Features of PkarrResolver
The PkarrResolver implements several architectural decisions that make it suitable for decentralized networking.
Stateless HTTP Transport. Each lookup is a single, stateless request to the relay, making the resolver NAT-friendly and easy to cache without maintaining persistent connections.
TTL-based Caching. The SignedPacket includes its own TTL; the resolver respects this expiration and can cache results until the packet becomes stale, reducing redundant network requests.
Pluggable DNS Resolution. The resolver can be configured with a custom DNS resolver, allowing it to function in environments with restrictive DNS policies or requiring DNS-over-HTTPS.
Address Filtering. The optional AddrFilter trait enables applications to hide private or undesired addresses before they are handed to the transport layer, providing security and routing control.
Code Example: Connecting by Public Key Only
The following Rust example demonstrates how to instantiate a PkarrResolver and resolve a peer’s address using only their public key.
use iroh::{
address_lookup::{pkarr::{PkarrResolver, PkarrResolverBuilder}, AddressLookup},
endpoint::EndpointId,
};
use url::Url;
// 1. Build the resolver targeting the production pkarr relay
let resolver: PkarrResolver = PkarrResolverBuilder::new(
Url::parse("https://dns.iroh.link/pkarr").unwrap(),
)
// Optional: configure custom DNS-over-HTTPS resolver
// .dns_resolver(my_dns_resolver)
.build()
.await
.expect("failed to build PkarrResolver");
// 2. Resolve the remote endpoint using only its public key
let remote_pubkey: EndpointId = // obtain from your protocol
let endpoint_infos = resolver
.resolve(remote_pubkey)
.await
.expect("pkarr lookup failed");
// 3. Use the verified addresses to establish a connection
if let Some(info) = endpoint_infos.first() {
// EndpointInfo implements ToSocketAddrs for direct use
println!("Connecting to: {:?}", info);
// Proceed with transport.connect(info).await?;
}
For higher-level integration, supply the resolver to an EndpointBuilder via EndpointBuilder::address_lookup(resolver) to enable automatic address resolution for all outgoing connections.
Summary
- PkarrResolver bridges public keys to network addresses via signed packets stored on pkarr relays.
- Resolution workflow: Build resolver → HTTP GET to relay → Verify
SignedPacket→ ReturnEndpointInfoaddresses. - Security guarantee: Cryptographic verification in
iroh-dns/src/pkarr.rsensures only the private key holder can publish valid addresses for a given public key. - Configuration options: Custom relays, DNS resolvers, and address filters allow deployment in diverse network environments.
- Entry points:
PkarrResolverBuilder::new(line 442) andPkarrResolver::resolve(line 499) iniroh/src/address_lookup/pkarr.rs.
Frequently Asked Questions
What is a pkarr relay and why is it needed?
A pkarr relay is a server that stores signed DNS records indexed by public key. It acts as a decentralized directory service, allowing peers to publish their network addresses under their cryptographic identity. When you only know a peer’s public key, the relay provides the signed packet containing their current addresses without requiring a centralized authority.
How does PkarrResolver ensure the returned addresses are authentic?
The resolver verifies the signature inside the SignedPacket using the SignedPacket::verify method implemented in iroh-dns/src/pkarr.rs. Because the packet is signed by the private key corresponding to the public key you queried, verified addresses are cryptographically guaranteed to belong to the key holder, preventing man-in-the-middle attacks during the lookup phase.
Can I use a custom or private pkarr relay instead of the default?
Yes. The PkarrResolverBuilder accepts any valid URL when calling PkarrResolverBuilder::new. You can point the resolver to a private relay, a staging environment, or a self-hosted instance, making the resolution infrastructure configurable for private networks or testing scenarios.
What happens if the pkarr relay is unavailable or the public key is not found?
If the relay is unreachable or returns a 404 for the given EndpointId, PkarrResolver::resolve returns an error indicating the lookup failure. The application must handle this case by retrying with exponential backoff, falling back to alternative address sources, or reporting the connectivity issue to the user.
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 →