Skip to main content

Crate dig_nat

Crate dig_nat 

Source
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:

  1. Direct — peer publicly reachable / already port-forwarded (method::direct)
  2. UPnP/IGD port mapping (method::upnp)
  3. NAT-PMP (RFC 6886, method::natpmp)
  4. PCP (RFC 6887, method::pcp)
  5. Relay-coordinated hole-punch (RLY-007, method::hole_punch)
  6. 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::connect call. 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 a PeerConnection whose remote peer_id has 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 TraversalMethod trait, plus the TraversalKind tag 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 NatConfig deliberately 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 tokio AsyncRead + AsyncWrite duplex stream, so the SAME mTLS handshake + yamux multiplexing 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’s src/wire.rs, dig-node’s relay::RelayMessage, and dig-gossip’s relay_types (requirements RLY-001 through RLY-007).

Structs§

CapturedBlsPub
The peer’s verified BLS G1 identity pubkey, captured from the #1204 cert binding when the handshake carried a valid one. None means no valid binding was presented (a legacy peer under BindingPolicy::Opportunistic, or BindingPolicy::Off). The sealing layer seals to this key.
CapturedPeerId
The peer_id a verifier derived from the certificate the peer presented, captured for the caller. Shared via Arc<Mutex<_>> because rustls verifiers are Sync and run inside the handshake.
NodeCert
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§

BindingOutcome
The result of checking a leaf certificate for a valid BLS binding, BEFORE the policy is applied.
BindingPolicy
The verification stance for a peer’s cert binding — a LOCAL decision (never wire-negotiated).

Functions§

connect
Establish a mutually-authenticated connection to peer with 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) calls connect_with_runtime with a NatRuntime carrying 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 data NatConfig and the live NatRuntime handles, and the strategy picks the first tier that establishes an mTLS PeerConnection whose remote peer_id matches PeerTarget::peer_id.
peer_id_from_leaf_cert_der
Extract the SubjectPublicKeyInfo DER from a leaf X.509 certificate (DER-encoded) and derive the PeerId. Returns None if the certificate cannot be parsed as X.509.
peer_id_from_tls_spki_der
Derive a PeerId from a TLS SubjectPublicKeyInfo block in PKIX DER form.
verify_binding_from_leaf_cert
Verify the BLS binding carried by a DER-encoded leaf certificate.