n0-computer /iroh

IP addresses break, dial keys instead. A library that adds QUIC + NAT Traversal to your apps.

★ 12,919⑂ 758👁 101▤ 74
RustCreated 2022-03-15iroh.computer
12,919
stars
+0+12+268
758
forks
101
watchers
–
prs
–
issues
74
releases
–
discussions

README

less net work for networks












  
    
      Docs Site
    
     | 
    
      Rust Docs
    
  



 What is iroh?

Iroh gives you an API for dialing by public key.
You say “connect to that phone”, iroh will find & maintain the fastest connection for you, regardless of where it is.

 Hole-punching

The fastest route is a direct connection, so if necessary, iroh tries to hole-punch.
Should this fail, it can fall back to an open ecosystem of public relay servers.
To ensure these connections are as fast as possible, we [continuously measure iroh][iroh-perf].

 Built on [QUIC]

Iroh uses [noq] to establish [QUIC] connections between endpoints.
This way you get authenticated encryption, concurrent streams with stream priorities, a datagram transport and avoid head-of-line-blocking out of the box.

 Compose Protocols

Use pre-existing protocols built on iroh instead of writing your own:
- [iroh-blobs] for [BLAKE3]-based content-addressed blob transfer scaling from kilobytes to terabytes
- [iroh-gossip] for establishing publish-subscribe overlay networks that scale, requiring only resources that your average phone can handle
- [iroh-docs] for an eventually-consistent key-value store of [iroh-blobs] blobs

 Getting Started

 Rust Library

It's easiest to use iroh from rust.
Install it using cargo add iroh, then on the connecting side:

rs
const ALPN: &[u8] = b"iroh-example/echo/0";

let endpoint = Endpoint::bind().await?;

// Open a connection to the accepting endpoint
let conn = endpoint.connect(addr, ALPN).await?;

// Open a bidirectional QUIC stream
let (mut send, mut recv) = conn.open_bi().await?;

// Send some data to be echoed
send.write_all(b"Hello, world!").await?;
send.finish()?;

// Receive the echo
let response = recv.read_to_end(1000).await?;
assert_eq!(&response, b"Hello, world!");

// As the side receiving the last application data - say goodbye
conn.close(0u32.into(), b"bye!");

// Close the endpoint and all its connections
endpoint.close().await;


And on the accepting side:
rs
let endpoint = Endpoint::bind().await?;

let router = Router::builder(endpoint)
    .accept(ALPN.to_vec(), Arc::new(Echo))
    .spawn()
    .await?;

// The protocol definition:
[derive(Debug, Clone)]
struct Echo;

impl ProtocolHandler for Echo {
    async fn accept(&self, connection: Connection) - Result {
        let (mut send, mut recv) = connection.accept_bi().await?;

        // Echo any bytes received back directly.
        let bytes_sent = tokio::io::copy(&mut recv, &mut send).await?;

        send.finish()?;
        connection.closed().await;

        Ok(())
    }
}


The full example code with more comments can be found at [echo.rs][echo-rs].

Or use one of the pre-existing protocols, e.g. [iroh-blobs] or [iroh-gossip].

 Other Languages

If you want to use iroh from other languages, make sure to check out [iroh-ffi], the repository for FFI bindings.

 Links

- [Introducing Iroh (video)][iroh-yt-video]
- [Iroh Documentation][docs]
- [Iroh Examples]

Snapshot: 2026-11-04T14:00:00Z · Data license Apache-2.0 · JSON