How PkarrPublisher Publishes iroh Endpoint Addresses to DNS

PkarrPublisher publishes iroh endpoint addresses to DNS by filtering and collecting endpoint data, encoding it into a cryptographically signed packet, and uploading it to a pkarr relay via HTTP PUT, where the data becomes resolvable through standard DNS queries.

The PkarrPublisher component in the n0-computer/iroh repository provides a decentralized mechanism for making iroh node addresses discoverable via DNS. It bridges peer-to-peer networking with traditional DNS infrastructure by publishing signed endpoint information to pkarr relays. This article explains the internal mechanics of how PkarrPublisher works for publishing iroh endpoint addresses to DNS, based on the actual implementation in the source code.

The Three-Stage Publishing Pipeline

The publishing flow in iroh/src/address_lookup/pkarr.rs operates through three distinct stages: data collection, cryptographic signing, and HTTP transmission.

Collecting Endpoint Data

The publisher begins by receiving an EndpointData structure containing the node's relay URLs, direct IP addresses, and other connectivity information. Before publication, this data passes through an AddrFilter to ensure privacy and security.

By default, the filter uses AddrFilter::relay_only(), which strips direct IP addresses to prevent leakage of public network locations. This filtering occurs in the publisher's data collection phase, ensuring only relay-mediated addresses are exposed to the public DNS record.

Encoding and Signing the Packet

Once filtered, the endpoint data transforms into an EndpointInfo structure. The critical step occurs in EndpointInfo::to_pkarr_signed_packet, which creates a SignedPacket following the pkarr specification format: <32-byte pubkey><64-byte signature><8-byte timestamp><DNS wire>.

This process, implemented in iroh-dns/src/pkarr.rs, signs the payload using the endpoint's SecretKey and appends a monotonic timestamp to prevent replay attacks. The resulting packet contains DNS TXT records encoding the reachable addresses, cryptographically bound to the node's public key.

Publishing via HTTP PUT

The PkarrRelayClient handles the network transmission, configured with optional TLS and custom DNS resolvers as shown in lines 311-316 of iroh/src/address_lookup/pkarr.rs. A background PublisherService manages the publication lifecycle, watching for endpoint data changes or triggering on a periodic republish interval.

When publishing, the service performs an HTTP PUT request to <relay-url>/<z-base-32-pubkey> with the signed packet as the request body. The pkarr relay stores this packet and, if functioning as a DNS resolver, serves it under a derived domain name (e.g., o3dks..6uyy.dns.iroh.link).

Architecture and Key Components

The implementation relies on several coordinated components working across multiple source files:

  • PkarrPublisherBuilder – Configures publication parameters including address filtering, TTL values, and republish intervals. Located in iroh/src/address_lookup/pkarr.rs (lines 150-167).

  • PublisherService – Background task managing periodic republication (defaulting to 5-minute intervals) and handling backoff strategies on network failures. Implements the HTTP PUT logic in lines 56-74.

  • PkarrResolver – The complementary component for DNS lookups, retrieving signed packets from relays or DNS resolvers and reconstructing EndpointInfo for peer connections (lines 86-94).

  • SignedPacket – The wire format defined in iroh-dns/src/pkarr.rs handling binary encoding, signature verification, and timestamp validation (lines 41-48, 81-87).

Configuration Options

The builder pattern allows customization of publication behavior beyond the privacy-preserving defaults:

use iroh::address_lookup::pkarr::{PkarrPublisher, AddrFilter};
use std::time::Duration;
use url::Url;

// Configure a publisher with custom intervals and full address disclosure
let relay_url = Url::parse("https://dns.iroh.link/pkarr").unwrap();
let publisher = PkarrPublisher::builder(relay_url)
    .ttl(60)                                        // DNS TTL in seconds
    .republish_interval(Duration::from_secs(120))   // Republish every 2 minutes
    .addr_filter(AddrFilter::unfiltered())         // Include direct IPs
    .build(secret_key.clone(), tls_config.clone());

Integrating with iroh Endpoints

In practice, you integrate the publisher directly into an iroh endpoint builder:

use iroh::endpoint::Builder;
use iroh::address_lookup::pkarr::PkarrPublisher;
use url::Url;

let relay_url = Url::parse("https://dns.iroh.link/pkarr").unwrap();

let endpoint = Builder::new()
    .address_lookup(PkarrPublisher::builder(relay_url))
    .build()
    .await?;

Manual updates trigger immediate republication through the background service:

// Trigger a fresh publication with current endpoint data
let data = endpoint.endpoint_data();
endpoint.publish(&data);

Summary

  • PkarrPublisher writes iroh endpoint data to pkarr relays, making nodes discoverable via DNS without centralized registries.
  • Privacy defaults use AddrFilter::relay_only() to avoid leaking direct IP addresses to public DNS records.
  • Cryptographic signing binds endpoint information to the node's public key using EndpointInfo::to_pkarr_signed_packet with the format <32-byte pubkey><64-byte signature><8-byte timestamp><DNS wire>.
  • HTTP transport uploads signed packets via PUT requests to <relay-url>/<z-base-32-pubkey>, handled by PkarrRelayClient and managed by the background PublisherService.
  • Automatic refresh occurs every 5 minutes by default (DEFAULT_REPUBLISH_INTERVAL), ensuring DNS records remain current.

Frequently Asked Questions

What is the default address filtering behavior in PkarrPublisher?

By default, PkarrPublisher uses AddrFilter::relay_only(), which filters out direct IP addresses and publishes only relay URLs. This prevents exposure of the node's physical network location to public DNS queries, enhancing privacy while maintaining connectivity through relay infrastructure.

How often does PkarrPublisher republish endpoint data?

The background PublisherService republishes data every 5 minutes by default, controlled by DEFAULT_REPUBLISH_INTERVAL. The builder allows customization via .republish_interval(), and the service also triggers immediate updates when endpoint data changes or manual publish() calls occur.

What format does the DNS packet use in pkarr publishing?

The signed packet follows the pkarr specification: a binary concatenation of <32-byte pubkey><64-byte signature><8-byte timestamp><DNS wire>. This format, implemented in iroh-dns/src/pkarr.rs, encodes endpoint information as DNS TXT records and cryptographically signs them with the node's SecretKey.

How does DNS resolution work after publishing with PkarrPublisher?

Once published, the pkarr relay stores the signed packet and serves it via DNS under a name derived from the z-base-32 encoded public key (e.g., o3dks..6uyy.dns.iroh.link). The complementary PkarrResolver queries these records, verifies the signatures, and reconstructs EndpointInfo for establishing peer connections.

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 →