What Are the iroh Address Types? Understanding TransportAddr and EndpointAddr

The iroh address types are defined by the TransportAddr enum in iroh-base/src/endpoint_addr.rs, which provides three variants—Relay, Ip, and Custom—enabling endpoints to be reached via relay servers, direct IP connections, or extensible custom transports.

Network addressing in the iroh stack centers on flexible, multi-transport endpoint identification. The n0-computer/iroh repository defines these iroh address types through a non-exhaustive enum system that supports everything from traditional IP sockets to custom transport protocols. Understanding these types is essential for building applications that can connect through firewalls, NATs, and specialized network layers.

The TransportAddr Enum: Core iroh Address Types

The fundamental TransportAddr enum, defined at lines 49-62 of iroh-base/src/endpoint_addr.rs, represents every network-level addressing scheme supported by the protocol. This non-exhaustive enum abstracts the underlying transport mechanisms, allowing iroh endpoints to advertise multiple concurrent paths to reach a single node.

Relay Addresses (RelayUrl)

The Relay(RelayUrl) variant enables connectivity through relay servers, which facilitate hole-punching and NAT traversal when direct connections are impossible. The RelayUrl type, implemented in iroh-base/src/relay_url.rs (lines 7-21), wraps an HTTPS URL pointing to a specific relay infrastructure. This variant is critical for establishing initial connectivity between peers behind restrictive firewalls.

Direct IP Addresses (SocketAddr)

The Ip(SocketAddr) variant provides standard direct addressing using IPv4 or IPv6 socket addresses with port numbers. This represents the most straightforward transport path when both endpoints have public reachability or have already established NAT mappings. Direct IP addresses offer the lowest latency path when network conditions permit.

Custom Transport Addresses (CustomAddr)

The Custom(CustomAddr) variant supports extensible transport protocols through opaque addressing data. Each custom address consists of a transport ID (u64) and arbitrary binary data, enabling integration with specialized networks like Tor or Bluetooth Low Energy. The transport ID registry is documented in TRANSPORTS.md at the repository root, where protocols like Tor (0x544F52) are reserved for specific implementations.

EndpointAddr: Grouping iroh Address Types

While TransportAddr represents individual transport paths, EndpointAddr (defined in the same file) aggregates these into a complete addressing bundle. An EndpointAddr pairs an EndpointId with a collection of TransportAddr variants, allowing a single endpoint to advertise multiple concurrent paths—simultaneously offering relay, direct IP, and custom transport options.

Practical Implementation of iroh Address Types

Working with these address types in Rust involves pattern matching against the TransportAddr variants. The following example demonstrates creating all three address types and bundling them into an EndpointAddr:

use iroh_base::{EndpointAddr, TransportAddr, RelayUrl, CustomAddr};
use std::net::SocketAddr;

// 1️⃣ A relay address
let relay = RelayUrl::from(
    "https://relay.example.com".parse().unwrap()
);
let relay_addr = TransportAddr::Relay(relay);

// 2️⃣ An IP address
let ip: SocketAddr = "192.0.2.10:4000".parse().unwrap();
let ip_addr = TransportAddr::Ip(ip);

// 3️⃣ A custom transport address (e.g., Tor)
let tor_pubkey = [0u8; 32];               // placeholder 32‑byte public key
let custom = CustomAddr::from_parts(0x544F52, &tor_pubkey);
let custom_addr = TransportAddr::Custom(custom);

// Build an EndpointAddr that contains all three
let endpoint = EndpointAddr::from_parts(
    /*endpoint_id=*/ Default::default(),
    vec![relay_addr, ip_addr, custom_addr],
);

// Iterate over the stored addresses
for addr in &endpoint.addrs {
    match addr {
        TransportAddr::Relay(url) => println!("Relay: {}", url),
        TransportAddr::Ip(sa)   => println!("IP: {}", sa),
        TransportAddr::Custom(c) => println!("Custom id {} data {:?}", c.id(), c.data()),
    }
}

The code illustrates how TransportAddr serves as a discriminated union, while EndpointAddr provides the container semantics necessary for multi-homed endpoint discovery.

Summary

  • The TransportAddr enum in iroh-base/src/endpoint_addr.rs defines the three core iroh address types: Relay, Ip, and Custom.
  • Relay addresses use RelayUrl to route through relay servers for NAT traversal, defined in iroh-base/src/relay_url.rs.
  • IP addresses use standard SocketAddr for direct connectivity when network conditions permit.
  • Custom addresses use CustomAddr with registered transport IDs (documented in TRANSPORTS.md) to support protocol extensions like Tor or BLE.
  • EndpointAddr groups multiple TransportAddr instances with an EndpointId, enabling multi-path endpoint discovery.

Frequently Asked Questions

What is the difference between TransportAddr and EndpointAddr in iroh?

TransportAddr represents a single network path—such as a specific relay URL or IP address—while EndpointAddr aggregates multiple transport addresses under a single EndpointId. According to the n0-computer/iroh source code, an endpoint can advertise several TransportAddr variants simultaneously, allowing peers to choose the most appropriate connection method based on network conditions.

How do custom transport addresses work in iroh?

Custom transport addresses use the Custom(CustomAddr) variant, which stores a 64-bit transport ID and opaque binary data. The transport ID identifies the specific protocol implementation (for example, 0x544F52 for Tor), while the data contains protocol-specific addressing information like public keys. Custom transport IDs must be registered in TRANSPORTS.md to avoid collisions with other implementations.

Can an iroh endpoint have multiple address types simultaneously?

Yes, iroh endpoints routinely advertise multiple address types through EndpointAddr. An endpoint can simultaneously expose a Relay address for initial connectivity, an Ip address for direct communication after NAT traversal, and Custom addresses for specialized network protocols. This multi-address approach ensures robust connectivity across diverse network environments.

Where are iroh address types defined in the source code?

The core address types are defined in iroh-base/src/endpoint_addr.rs, which contains the TransportAddr and EndpointAddr structs. The RelayUrl type resides in iroh-base/src/relay_url.rs, while transport ID registrations for custom addresses are documented in the repository's TRANSPORTS.md file at the root level.

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 →