|
| 1 | +--- |
| 2 | +title: "Network Diagnostics" |
| 3 | +description: "Diagnose user connectivity issues with remote diagnostic reporting" |
| 4 | +--- |
| 5 | + |
| 6 | +Net Diagnostics lets you run network connectivity reports on your endpoints from iroh-services. Reports cover NAT type, UDP connectivity, relay latency, port mapping protocol availability, and direct addresses — everything you need to debug connection issues. You can initiate reports from iroh-services, which will reach out to configured remote nodes that have authorized diagnostics, gather details about the endpoint's connectivity context, and forward the report to your project on iroh services to assess how to help your user get the best connection they can. |
| 7 | + |
| 8 | +Net Diagnostics is available on the **Enterprise plan**. |
| 9 | + |
| 10 | +## Quick Start |
| 11 | + |
| 12 | +### 1. Get your API secret |
| 13 | + |
| 14 | +Go to your project's **Settings** page and copy the API secret. In your terminal, export it as an environment variable: |
| 15 | + |
| 16 | +```bash |
| 17 | +export N0DES_API_SECRET=<your-api-secret> |
| 18 | +``` |
| 19 | + |
| 20 | +### 2. Run the diagnostics client |
| 21 | + |
| 22 | +Clone the [iroh-n0des](https://github.com/n0-computer/iroh-n0des) repo and run the `net_diagnostics` example: |
| 23 | + |
| 24 | +```bash |
| 25 | +git clone https://github.com/n0-computer/iroh-n0des.git |
| 26 | +cd iroh-n0des |
| 27 | +cargo run --example net_diagnostics --features net_diagnostics,client_host |
| 28 | +``` |
| 29 | + |
| 30 | +Leave this terminal open. The example connects to n0des, grants the diagnostics capability to your project, and waits for incoming diagnostics requests. |
| 31 | + |
| 32 | +### 3. Run a diagnostic from the dashboard |
| 33 | + |
| 34 | +Go to your project's **Endpoints** page. You should see the example client listed as an online endpoint. Click **Run Diagnostics** to generate a report. |
| 35 | + |
| 36 | +The report appears on the **Net Diagnostics** page and includes: |
| 37 | + |
| 38 | +- **NAT Type** — No NAT, Endpoint-Independent, Endpoint-Dependent, or Unknown |
| 39 | +- **UDP Connectivity** — IPv4 and IPv6 status with public addresses |
| 40 | +- **NAT Mapping** — whether mapping varies by destination (symmetric NAT detection) |
| 41 | +- **Direct Addresses** — local addresses the endpoint is listening on |
| 42 | +- **Port Mapping** — UPnP, PCP, and NAT-PMP availability |
| 43 | +- **Relay Latencies** — per-relay IPv4, IPv6, and HTTPS round-trip times |
| 44 | +- **Captive Portal** — detection of captive portal interference |
| 45 | + |
| 46 | +## Understanding the Report |
| 47 | + |
| 48 | +### NAT Types |
| 49 | + |
| 50 | +| NAT Type | What it means | Connection quality | |
| 51 | +|---|---|---| |
| 52 | +| **No NAT** | Local address matches public address | Direct connections work with correct firewall config | |
| 53 | +| **Endpoint-Independent** | One outbound UDP packet opens a port for any sender | Holepunching works reliably | |
| 54 | +| **Endpoint-Dependent** | Only the specific destination can reply (symmetric NAT) | Connections will primarily use relays | |
| 55 | +| **Unknown** | NAT behavior could not be determined | Check UDP connectivity | |
| 56 | + |
| 57 | +### Connectivity Summary |
| 58 | + |
| 59 | +The report includes a color-coded connectivity summary: |
| 60 | + |
| 61 | +- **Green** — UDP works and NAT is favorable. Direct connections should work. |
| 62 | +- **Orange** — Endpoint-Dependent NAT. Direct connections may be difficult; traffic will often be relayed. |
| 63 | +- **Red** — No UDP connectivity. Traffic will be relayed. |
| 64 | + |
| 65 | +## Integrating Net Diagnostics Into Your App |
| 66 | + |
| 67 | +To add net diagnostics support to your own iroh application, you need to: |
| 68 | + |
| 69 | +1. Connect to n0des with an `iroh_n0des::Client` |
| 70 | +2. Grant the `NetDiagnosticsCap::GetAny` capability to n0des so it can request diagnostics from your endpoint |
| 71 | +3. Run a `ClientHost` so n0des can dial back into your endpoint |
| 72 | + |
| 73 | +Here's a minimal integration: |
| 74 | + |
| 75 | +```rust |
| 76 | +use anyhow::Result; |
| 77 | +use iroh::{Endpoint, protocol::Router}; |
| 78 | +use iroh_n0des::{ |
| 79 | + ApiSecret, Client, ClientHost, CLIENT_HOST_ALPN, API_SECRET_ENV_VAR_NAME, |
| 80 | + caps::NetDiagnosticsCap, |
| 81 | +}; |
| 82 | + |
| 83 | +async fn setup_net_diagnostics(endpoint: &Endpoint) -> Result<Router> { |
| 84 | + // Parse the API secret from the environment |
| 85 | + let secret = ApiSecret::from_env_var(API_SECRET_ENV_VAR_NAME)?; |
| 86 | + let remote_id = secret.addr().id; |
| 87 | + |
| 88 | + // Build the n0des client |
| 89 | + let client = Client::builder(endpoint) |
| 90 | + .api_secret(secret)? |
| 91 | + .build() |
| 92 | + .await?; |
| 93 | + |
| 94 | + // Grant the GetAny capability so n0des can request diagnostics |
| 95 | + // from this endpoint on demand |
| 96 | + let client2 = client.clone(); |
| 97 | + tokio::spawn(async move { |
| 98 | + client2 |
| 99 | + .grant_capability(remote_id, vec![NetDiagnosticsCap::GetAny]) |
| 100 | + .await |
| 101 | + .unwrap(); |
| 102 | + }); |
| 103 | + |
| 104 | + // Set up a ClientHost so n0des can dial back into this endpoint |
| 105 | + let host = ClientHost::new(endpoint); |
| 106 | + let router = Router::builder(endpoint.clone()) |
| 107 | + .accept(CLIENT_HOST_ALPN, host) |
| 108 | + .spawn(); |
| 109 | + |
| 110 | + Ok(router) |
| 111 | +} |
| 112 | +``` |
| 113 | + |
| 114 | +Add the following to your `Cargo.toml`: |
| 115 | + |
| 116 | +```toml |
| 117 | +[dependencies] |
| 118 | +iroh-n0des = { version = "...", features = ["net_diagnostics", "client_host"] } |
| 119 | +``` |
| 120 | + |
| 121 | +### How It Works |
| 122 | + |
| 123 | +When you click **Run Diagnostics** in the dashboard, n0des dials back into your endpoint using the capability token your app granted. Your `ClientHost` receives the request, runs the diagnostics locally (probing UDP connectivity, NAT behavior, relay latency, and port mapping), and returns the report to n0des for display. |
| 124 | + |
| 125 | +The capability grant (`NetDiagnosticsCap::GetAny`) authorizes n0des to request diagnostics from your endpoint. Without this grant, the **Run Diagnostics** button will be disabled in the dashboard even if the endpoint is online. |
| 126 | + |
| 127 | +### Requirements |
| 128 | + |
| 129 | +- The `net_diagnostics` and `client_host` cargo features must be enabled on `iroh-n0des` |
| 130 | +- The `N0DES_API_SECRET` environment variable must be set before your app starts |
| 131 | +- The `ClientHost` must be registered on the `Router` with `CLIENT_HOST_ALPN` so n0des can reach it |
0 commit comments