Expand description
§dig-nat — abstract NAT traversal for DIG Node peer connections
One API, connect, establishes a mutually-authenticated (mTLS) connection to a peer using
the best available NAT-traversal method, transparently. The caller never chooses the method —
they describe the peer once and get back a verified PeerConnection; which technique got there
is reported for observability but is not something the caller handles.
§Traversal order (first success wins, relay last)
Internally the strategy attempts, in this order:
- Direct — peer publicly reachable / already port-forwarded (
method::direct) - UPnP/IGD port mapping (
method::upnp) - NAT-PMP (RFC 6886,
method::natpmp) - PCP (RFC 6887,
method::pcp) - Relay-coordinated hole-punch (RLY-007,
method::hole_punch) - Relayed transport via
relay.dig.net— the LAST resort (relay)
stun (RFC 5389) discovers this node’s reflexive address for candidate advertisement +
hole-punch coordination.
§Streaming-first + multiplexed transport
Whatever tier establishes the connection, the result is uniform: a PeerConnection wrapping a
single mTLS byte stream in yamux multiplexing. The caller opens many cheap concurrent
logical streams (PeerConnection::open_stream) with no head-of-line blocking, and
byte-range streams (PeerConnection::open_range_stream) scoped to [offset, len) of a
resource — so a downloader fetches DIFFERENT ranges from DIFFERENT peers in parallel and
reassembles. The API is streaming (read bytes as they arrive), never buffer-the-whole-response.
§Identity + mTLS — delegated to dig-tls
Every peer connection is mutual TLS, and the entire certificate model is owned by the canonical
dig-tls crate (L00): peer_id = SHA-256(TLS SPKI DER), the #1204 BLS-G1 cert
binding, and the ready rustls mutual-auth configs. dig-nat presents this node’s NodeCert
and uses dig_tls::client_config_spki_pinned for the outbound handshake, authenticating the
remote peer by its SPKI peer_id pin (matched to the peer::PeerTarget::peer_id the caller
specified), rustls proof-of-possession, and the #1204 BLS cert binding — with NO DigNetwork-CA
chain requirement; live self-signed peer leaves are accepted (the DIG-CA-everywhere migration
#1378 is deferred). dig-nat holds NO cert/binding/peer_id code of its own (it was extracted to
dig-tls in 0.6.0); the names below are re-exports for convenience.
§Graceful fallback + relay resilience
Each method is bounded by a per-method timeout; if ALL fail, connect returns a clear
NatError::AllMethodsFailed (never panics, never hangs). The relay client — used both as
the last-resort transport and as a node’s persistent reachability channel — establishes and
maintains its session with keepalive + capped-exponential-backoff reconnect, tolerates the relay
being down (retries in the background, never crashes the node), logs once per state change, and
honours the DIG_RELAY_URL=off opt-out. See relay::RelayStatus.
§Example
let peer = PeerTarget::with_addr(peer_id, addr, "DIG_MAINNET");
let conn = connect(&peer, &node, &NatConfig::default()).await?;
println!("connected to {} via {:?}", conn.peer_id, conn.method);Re-exports§
pub use config::NatConfig;pub use config::NatConfigBuilder;pub use error::MethodError;pub use error::NatError;pub use fast_connect::connect_fast;pub use fast_connect::FastPeerConnection;pub use fast_connect::FastPeerStream;pub use method::hole_punch::HolePunchCoordinator;pub use method::hole_punch::HolePunchMethod;pub use method::relayed::RelayedDialMethod;pub use method::relayed::RelayedDialer;pub use method::relayed::RelayedTransport;pub use method::relayed::ReservationRelayedTransport;pub use method::upnp::IgdGateway;pub use method::upnp::RealIgd;pub use method::upnp::UpnpMethod;pub use method::TraversalKind;pub use method::TraversalMethod;pub use mux::AvailabilityAnswer;pub use mux::AvailabilityItem;pub use mux::AvailabilityRequest;pub use mux::AvailabilityResponse;pub use mux::ClosedHandle;pub use mux::PeerSession;pub use mux::PeerStream;pub use mux::RangeFrame;pub use mux::RangeRequest;pub use peer::PeerConnection;pub use peer::PeerTarget;pub use relay_descriptor::verify_relay_descriptor;pub use relay_descriptor::RelayDescriptor;pub use relay_descriptor::RelayDescriptorError;pub use runtime::NatRuntime;pub use runtime::NatRuntimeBuilder;
Modules§
- config
- Connection configuration — the enabled methods, per-method timeout, relay/STUN endpoints, and the
cert-binding policy that shape a
crate::connectcall. Built with a fluent builder; the caller never selects the traversal method (only which ones are enabled). - dialer
- The production
Dialer— performs the real rustls mTLS dial to a reachable address and returns aPeerConnectionwhose remotepeer_idhas been verified. - error
- Error + status types for NAT traversal.
- fast_
connect - Fast-connect — start on the fastest usable transport, then live-promote to a better one.
- method
- Traversal methods — one module per NAT-traversal technique behind a common
TraversalMethodtrait, plus theTraversalKindtag the strategy orders them by. - mux
- Stream multiplexing + byte-range streams over a single established peer connection.
- peer
- The peer the caller wants to reach (
PeerTarget) and the connection they get back (PeerConnection). - relay
- Relay client — the LAST-RESORT transport + the node’s persistent reachability channel.
- relay_
descriptor - Relay descriptor verification (#1199) — a self-authenticating (peer_id, addrs, BLS_pub) record.
- runtime
- The runtime-handle carrier — the LIVE transport handles + discovery inputs the data-only
NatConfigdeliberately cannot hold. - strategy
- The traversal strategy — orders the enabled methods (direct-first, relay-last), tries each with a bounded timeout, and returns the FIRST connection that establishes. This is where “the caller doesn’t choose the method” is realised.
- stun
- Minimal STUN (RFC 5389) client — discover this node’s reflexive (public) transport address.
- tunnel
- Byte-stream adapter over a relay tunnel — turns the message-oriented
RelayTunnel(RLY-002 send/recv of opaque payloads) into a tokioAsyncRead+AsyncWriteduplex stream, so the SAME mTLS handshake +yamuxmultiplexing that runs over a direct TCP connection runs UNCHANGED over the tier-6 relayed path. - wire
- Relay protocol wire types — vendored, byte-identical to
dig-relay’ssrc/wire.rs,dig-node’srelay::RelayMessage, anddig-gossip’srelay_types(requirements RLY-001 through RLY-007).
Structs§
- Captured
BlsPub - The peer’s verified BLS G1 identity pubkey, captured from the #1204 cert binding when the
handshake carried a valid one.
Nonemeans no valid binding was presented (a legacy peer underBindingPolicy::Opportunistic, orBindingPolicy::Off). The sealing layer seals to this key. - Captured
Peer Id - The
peer_ida verifier derived from the certificate the peer presented, captured for the caller. Shared viaArc<Mutex<_>>because rustls verifiers areSyncand run inside the handshake. - Node
Cert - A peer’s mTLS identity certificate + private key, plus its derived
peer_id. - PeerId
- A peer’s stable network identity: the 32-byte SHA-256 of its TLS SPKI DER.
Enums§
- Binding
Outcome - The result of checking a leaf certificate for a valid BLS binding, BEFORE the policy is applied.
- Binding
Policy - The verification stance for a peer’s cert binding — a LOCAL decision (never wire-negotiated).
Functions§
- connect
- Establish a mutually-authenticated connection to
peerwith an empty runtime — the convenience entry point for a caller that holds NO live transport handles (a publicly-reachable node). Only the Direct tier is composable without runtime handles; a NAT’d node that needs the full ladder (UPnP/NAT-PMP/PCP/hole-punch/relayed) callsconnect_with_runtimewith aNatRuntimecarrying the gateway/port/relay handles. - connect_
with_ runtime - Establish a mutually-authenticated connection to
peer, auto-composing the FULL NAT-traversal ladder — direct → UPnP → NAT-PMP → PCP → hole-punch → relayed — trying each in rank order, first success wins, relay last. The caller never chooses the method: it supplies the dataNatConfigand the liveNatRuntimehandles, and the strategy picks the first tier that establishes an mTLSPeerConnectionwhose remotepeer_idmatchesPeerTarget::peer_id. - peer_
id_ from_ leaf_ cert_ der - Extract the SubjectPublicKeyInfo DER from a leaf X.509 certificate (DER-encoded) and derive the
PeerId. ReturnsNoneif the certificate cannot be parsed as X.509. - peer_
id_ from_ tls_ spki_ der - Derive a
PeerIdfrom a TLS SubjectPublicKeyInfo block in PKIX DER form. - verify_
binding_ from_ leaf_ cert - Verify the BLS binding carried by a DER-encoded leaf certificate.