How to Publish and Resolve Addresses Using PkarrPublisher and DnsAddressLookup in iroh
Use PkarrPublisher to sign and HTTP PUT endpoint data to a Pkarr relay, then use DnsAddressLookup (via PkarrResolver) to query DNS TXT records and verify the signed payload into an EndpointInfo struct.
The iroh crate provides a decentralized address discovery mechanism using Pkarr (Public-Key Addressable Resource Records) to publish endpoint information and DNS-based lookups to resolve peer addresses. By combining PkarrPublisher for publishing signed packets and DnsAddressLookup (implemented via PkarrResolver) for resolution, you can achieve stateless, cryptographically secure peer discovery without central registries. This article explores the implementation details found in iroh/src/address_lookup/pkarr.rs and demonstrates how to use these components with practical examples from the iroh-dns-server examples.
Architecture of Pkarr Publishing and Resolution
The system separates concerns into two distinct operations: publishing endpoint data via HTTP and resolving it via DNS TXT queries.
Core Components
The implementation relies on several key types across the iroh and iroh-dns crates:
PkarrPublisherBuilderandPkarrPublisher– Found iniroh/src/address_lookup/pkarr.rs, these construct and execute the publishing workflow.PkarrResolverBuilderandPkarrResolver– Also iniroh/src/address_lookup/pkarr.rs, these handle DNS-based resolution and signature verification.EndpointInfo– Defined iniroh-dns/src/pkarr.rs, this struct encapsulates endpoint IDs, relay URLs, IP addresses, and user data.SignedPacket– A cryptographically signed Pkarr packet that can be validated without trusting the relay.
Data Flow
- Publishing: The publisher constructs an
EndpointInfo, converts it to aSignedPacket, and sends it via HTTP PUT to a Pkarr relay (e.g.,https://dns.iroh.link/pkarr). - Resolution: The resolver queries DNS TXT records at
iroh.<z-base-32-id>.<origin>and validates the returnedSignedPacketagainst the endpoint's public key.
Publishing Endpoint Information with PkarrPublisher
Publishing requires creating a cryptographically signed packet that contains your endpoint's addressing information and transmitting it to a Pkarr relay.
Building the Publisher
First, instantiate a PkarrRelayClient that knows the relay URL and optional TLS configuration. This client handles the HTTP transport to the relay.
// From iroh-dns-server/examples/publish.rs
let pkarr = PkarrRelayClient::new(pkarr_relay_url, tls_config, DnsResolver::default());
Creating and Publishing Signed Packets
Construct an EndpointInfo with your endpoint ID, relay URL, IP addresses, and optional user data. Then convert this to a signed Pkarr packet using EndpointInfo::to_pkarr_signed_packet, which cryptographically signs the payload with your secret key.
// From iroh-dns-server/examples/publish.rs
let mut endpoint_info = EndpointInfo::new(endpoint_id);
if let Some(relay_url) = relay_url {
endpoint_info = endpoint_info.with_relay_url(relay_url.into());
}
endpoint_info = endpoint_info
.with_ip_addrs(args.addr.into_iter().collect())
.with_user_data(args.user_data);
let signed_packet = endpoint_info.to_pkarr_signed_packet(&secret_key, 30)?;
pkarr.publish(&signed_packet).await?;
The 30 parameter specifies the TTL (time-to-live) in seconds. The relay automatically expires stale records based on this value.
Resolving Addresses with DnsAddressLookup
Resolution uses standard DNS infrastructure to retrieve the signed packet, allowing compatibility with existing DNS tools while maintaining end-to-end cryptographic verification.
DNS Query Construction
The resolver constructs a TXT query for the domain iroh.<z32-id>.<origin>, where <z32-id> is the Z-base-32 encoded public key of the endpoint. The DnsResolver (or PkarrResolver wrapper) issues this query to the configured DNS server.
// From iroh-dns-server/examples/resolve.rs
let resolver = DnsResolver::new(dns_server_url)?;
let lookup = resolver.lookup_endpoint(&endpoint_id).await?;
Signature Verification
Upon receiving the TXT record, the resolver parses the payload into a SignedPacket and validates the signature using the endpoint's public key. This verification happens in the verify method, ensuring the data hasn't been tampered with by the relay or network intermediaries.
// From iroh-dns-server/examples/resolve.rs
let endpoint_info = lookup
.verify(&endpoint_id.public_key())?; // validates the signature
println!("Endpoint info: {endpoint_info:#?}");
The verification succeeds only if the signature matches the public key embedded in the DNS name, providing end-to-end authenticity.
Practical Implementation Examples
The iroh-dns-server crate provides complete CLI examples demonstrating both sides of the workflow.
Publishing a Record (CLI)
The publish.rs example in iroh-dns-server/examples/publish.rs demonstrates the complete publishing flow:
# Set the secret for the endpoint (once)
export IROH_SECRET=$(openssl rand -hex 32)
# Publish to the staging relay
cargo run --example publish -- --env staging \
--addr 192.0.2.10:4000 --user-data "my-service"
This command prints the DNS name you can query:
dig iroh.<z32-id>.irohdns.staging TXT
Resolving a Record (CLI)
The resolve.rs example in iroh-dns-server/examples/resolve.rs demonstrates resolution:
cargo run --example resolve -- --env staging endpoint \
<z32-id>
The resolver contacts the same relay (or any DoH server configured in the example) and prints the recovered EndpointInfo.
Summary
- Stateless publishing – The Pkarr relay stores only signed packets without maintaining private state, making the system resilient and easy to replicate.
- End-to-end security – All endpoint data is signed with the secret key and verified using the public key, preventing tampering even if the relay is compromised.
- DNS compatibility – The same
SignedPacketcan be served via standard DNS TXT records or the dedicated Pkarr HTTP endpoint, allowing flexible deployment strategies. - Automatic expiration – Packets include a TTL (default 30 seconds in the examples), ensuring stale endpoint information is automatically purged from the relay.
Frequently Asked Questions
What is the relationship between PkarrPublisher and DnsAddressLookup?
PkarrPublisher handles the publishing side by creating signed packets and sending them via HTTP PUT to a Pkarr relay. DnsAddressLookup refers to the resolution side, which is implemented by PkarrResolver (and DnsResolver) to query DNS TXT records and verify the returned signatures. Together, they form a complete publish-subscribe address discovery system.
How does the TTL parameter affect published records?
The TTL (time-to-live) parameter in to_pkarr_signed_packet specifies how long the relay should store the packet before expiration. According to the implementation in iroh-dns-server/src/http/pkarr.rs, the relay automatically removes expired records, and DNS resolvers can use this value for caching. A TTL of 30 seconds provides a balance between freshness and query efficiency.
Can I use my own DNS server instead of the iroh.link relay?
Yes. The PkarrResolver accepts any DNS server URL that can resolve the TXT records. The DNS server must either be a Pkarr relay itself (like https://dns.iroh.link) or a standard DNS server that forwards queries to the Pkarr relay. The resolution code in iroh/src/address_lookup/pkarr.rs is agnostic to the specific DNS backend as long as it returns the correctly formatted TXT records.
How is the endpoint ID encoded in the DNS query?
The endpoint ID (a public key) is encoded using Z-base-32 encoding and prepended with iroh. to form the subdomain. For example, an endpoint with public key <key> becomes iroh.<z32-encoded-key>.<origin>. This encoding is handled automatically by the EndpointInfo and PkarrResolver types in iroh-dns/src/pkarr.rs.
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 →