mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 19:46:15 +00:00
docs: refresh tutorials, how-to, design, reference, and examples for v0.4.0
Pre-cut documentation pass for the 0.4.0 release, verified against current source. Corrections: - fipsctl: stale 'show identities'/'show node' -> 'show status' (host-a-service, run-as-unprivileged-user) - mesh address derivation: first 16 bytes of SHA-256(pubkey) with the leading byte set to 0xfd, not a fixed fd97: prefix (reach-mesh-services, ipv6-adapter-walkthrough) - gateway control socket mode 0660 -> 0770 (troubleshoot-gateway) - Tor example: add advertised_port: 8443 so the published port matches the prose (enable-nostr-discovery) - bloom mesh-size estimate rewritten to the OR-union-of-peer-filters algorithm; plus mtu deep-link, gateway pool wording, and a NAT failure-mode line - examples: delete orphaned nostr-rs-relay config, accept inbound to the local 8443 TCP listener, fix fd::/8 -> fd00::/8 typos, dotless wireguard alias Additions: - new Nym mixnet transport section (fips-transport-layer) and the architecture transport list - new LAN/mDNS discovery section (fips-nostr-discovery) - reference docs: Nym transport, LAN discovery, and new control/stats surfaces; drop ble from the connect transport list
This commit is contained in:
@@ -221,9 +221,11 @@ discovery protocol, and error-recovery integration view live in
|
||||
## Transport Abstraction
|
||||
|
||||
FIPS treats the communication medium as a pluggable component. UDP,
|
||||
TCP, raw Ethernet, Tor, and BLE all implement the same small datagram
|
||||
interface (send, receive, report MTU) and feed peers into a single FMP
|
||||
routing layer; radio and serial transports are in the planned set.
|
||||
TCP, raw Ethernet, Tor, BLE, and Nym all implement the same small
|
||||
datagram interface (send, receive, report MTU) and feed peers into a
|
||||
single FMP routing layer; radio and serial transports are in the
|
||||
planned set. Nym (an outbound-only mixnet transport) and Tor are
|
||||
privacy-oriented deployment modes rather than failover paths.
|
||||
Multi-transport nodes bridge between networks transparently. The
|
||||
transport-layer specification — including per-transport categories,
|
||||
the trait surface, the connection model, and implementation status —
|
||||
|
||||
@@ -180,7 +180,7 @@ network with no overlap (excluding the node itself at the split point).
|
||||
|
||||
All peers — including non-tree mesh shortcuts — still **receive**
|
||||
FilterAnnounce messages and **store** received filters locally. These
|
||||
stored filters are consulted during routing (step 3 of `find_next_hop()`)
|
||||
stored filters are consulted during routing (step 4 of `find_next_hop()`)
|
||||
for single-hop shortcut discovery. However, mesh peer filters contain
|
||||
only the mesh peer's own tree-propagated information, not transitive
|
||||
entries from the broader network.
|
||||
@@ -339,14 +339,24 @@ positions that folding produces.
|
||||
|
||||
## Mesh Size Estimation
|
||||
|
||||
Each filter's saturation can be inverted into an estimated entry count
|
||||
A filter's saturation can be inverted into an estimated entry count
|
||||
via the standard formula `n ≈ -(m/k) · ln(1 − X/m)`, where `m` is the
|
||||
filter size in bits, `k` is the hash count, and `X` is the population
|
||||
count. Combining the parent's inbound filter with the children's
|
||||
inbound filters gives an estimate of the whole network: parent + each
|
||||
child's subtree are disjoint by construction, and adding 1 for the
|
||||
node itself yields the total. The result is cached on the node and
|
||||
exposed through the control socket and `fipstop` dashboard.
|
||||
count. Rather than estimate per-filter and sum, the node first builds
|
||||
an **OR-union of every connected peer's inbound filter** — all routing
|
||||
peers, including cross-links, not just the tree parent and children —
|
||||
inserts its own address into the union, and inverts the cardinality
|
||||
**once on the resulting union**. Because filter propagation is
|
||||
split-horizon (each outgoing filter excludes the peer it routes back
|
||||
to), every routing peer advertises a near-complete "whole mesh minus
|
||||
my subtree" view, so the union covers the network. OR-ing is
|
||||
idempotent, so overlapping bits deduplicate instead of over-counting,
|
||||
and folding in all peers rather than only the tree neighborhood damps
|
||||
the count flap on a parent switch (the cross-links still carry the
|
||||
upward coverage) and removes any dependence on tree-declaration cache
|
||||
freshness. The result is cached on the node and exposed through the
|
||||
control socket and `fipstop` dashboard. (See `compute_mesh_size()` in
|
||||
`src/node/mod.rs`.)
|
||||
|
||||
The estimator refuses to produce a value when any contributing filter
|
||||
is above the antipoison FPR cap (`node.bloom.max_inbound_fpr`,
|
||||
@@ -378,7 +388,7 @@ as described above.
|
||||
| 500ms rate limiting | **Implemented** |
|
||||
| FilterAnnounce gossip (all peers) | **Implemented** |
|
||||
| Filter cardinality logging | **Implemented** |
|
||||
| Mesh size estimation (parent + children + 1) | **Implemented** |
|
||||
| Mesh size estimation (OR-union of peer filters) | **Implemented** |
|
||||
| Inbound FPR cap (antipoison) | **Implemented** |
|
||||
| Size class negotiation | Future direction |
|
||||
| Folding support | Future direction |
|
||||
|
||||
@@ -218,7 +218,7 @@ involving the DNS proxy or the pool.
|
||||
|
||||
### Virtual IP Pool
|
||||
|
||||
The pool allocates IPv6 addresses from a configured CIDR (default
|
||||
The pool allocates IPv6 addresses from a required CIDR (commonly
|
||||
`fd01::/112`). Each address maps to one mesh destination, keyed by
|
||||
`NodeAddr` rather than by hostname — different `.fips` aliases for
|
||||
the same node share a virtual IP. Address 0 (the network-equivalent)
|
||||
|
||||
@@ -251,7 +251,7 @@ would later drop.
|
||||
The adapter integrates with the MTU subsystem rather than owning it.
|
||||
The "why we clamp and what `max_mss` means" lives here in the MTU
|
||||
design; the "how the clamp is implemented at the TUN" lives in the
|
||||
[IPv6 adapter](fips-ipv6-adapter.md#tcp-mss-clamping) doc.
|
||||
[IPv6 adapter](fips-ipv6-adapter.md#tun-side-tcp-mss-clamping) doc.
|
||||
|
||||
## ICMP Packet Too Big
|
||||
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
# FIPS Nostr-Mediated Discovery and NAT Traversal
|
||||
# FIPS Discovery: Nostr-Mediated and LAN/mDNS
|
||||
|
||||
FIPS nodes have two discovery mechanisms beyond the static `peers[]`
|
||||
list. The bulk of this document describes **Nostr-mediated discovery**,
|
||||
which works across the internet using public Nostr relays as a
|
||||
signaling channel and can punch through UDP NAT. A second, much
|
||||
simpler mechanism — **LAN/mDNS discovery** — finds peers on the same
|
||||
local link with no relay, STUN, or NAT traversal at all; it is
|
||||
described in its own section near the end. The two are independent: a
|
||||
node can enable either, both, or neither.
|
||||
|
||||
Nostr-mediated discovery lets FIPS nodes find each other, and if
|
||||
necessary, punch through UDP NAT, using public Nostr relays as the
|
||||
@@ -377,6 +386,182 @@ semaphore and replay-cache layers downstream.
|
||||
advert says "I am npub X at 1.2.3.4:5678" but whose FMP handshake
|
||||
presents a different static key is rejected at the mesh layer.
|
||||
|
||||
## LAN/mDNS discovery
|
||||
|
||||
LAN discovery is a separate, link-local discovery mechanism that finds
|
||||
peers on the same broadcast domain using mDNS / DNS-SD
|
||||
([RFC 6762](https://www.rfc-editor.org/rfc/rfc6762) /
|
||||
[RFC 6763](https://www.rfc-editor.org/rfc/rfc6763)). Unlike
|
||||
Nostr-mediated discovery, it contacts no relay, runs no STUN
|
||||
observation, and performs no NAT traversal: an endpoint learned from a
|
||||
LAN advert is by construction routable from the consumer's own link.
|
||||
The result is sub-second peer pairing on the same LAN.
|
||||
|
||||
It is unrelated to the "LAN candidate" terminology used in the
|
||||
NAT-traversal sections above (which refers to a host's own
|
||||
locally-bound address offered as a hole-punch candidate). LAN/mDNS
|
||||
discovery is a distinct subsystem under `src/discovery/lan/`.
|
||||
|
||||
### Role
|
||||
|
||||
LAN discovery adds two capabilities, both confined to the local link:
|
||||
|
||||
- **Advertising.** The node publishes a `_fips._udp.local.` DNS-SD
|
||||
service advert carrying its `npub`, its protocol version, and (if
|
||||
configured) a discovery scope. The advert is multicast on the local
|
||||
link only; it does not leave the broadcast domain unless the
|
||||
operator's network bridges mDNS.
|
||||
- **Browsing.** The node concurrently browses for the same service
|
||||
type, learns the endpoints of other FIPS nodes on the link, and
|
||||
initiates a normal FMP link to each newly-seen peer.
|
||||
|
||||
The mDNS service type is `_fips._udp.local.`
|
||||
(`src/discovery/lan/mod.rs:45`). Per RFC 6763 the `_udp` label denotes
|
||||
the IP transport used for the advert, not the FIPS upper protocol —
|
||||
both UDP and TCP FIPS endpoints announce under the same service type
|
||||
because the link-layer handshake travels over UDP either way. (In
|
||||
practice LAN discovery dials only over a UDP transport; see the
|
||||
handshake subsection.)
|
||||
|
||||
### When to use it
|
||||
|
||||
- **You run several FIPS nodes on one LAN** (a lab bench, an office
|
||||
segment, a home network) and want them to find each other without
|
||||
hand-maintaining `peers[]` blocks or standing up Nostr discovery.
|
||||
- **You want the lowest-latency pairing path.** Same-link pairing
|
||||
completes in well under a second with no relay round-trip.
|
||||
|
||||
Skip it when nodes are not on a shared broadcast domain (mDNS does not
|
||||
cross routed boundaries), or when you do not want the node to multicast
|
||||
its identity on the local link. LAN discovery is **opt-in and disabled
|
||||
by default**, so doing nothing leaves it off.
|
||||
|
||||
### How it works
|
||||
|
||||
The LAN discovery runtime (`src/discovery/lan/mod.rs`) is started
|
||||
during node initialization when `node.discovery.lan.enabled` is true.
|
||||
It is independent of Nostr discovery and runs even when Nostr is
|
||||
disabled (`src/node/lifecycle.rs:1159-1162`). Startup requires an
|
||||
operational UDP transport: the node advertises the port of its
|
||||
lowest-`TransportId` operational, non-bootstrap UDP transport, chosen
|
||||
deterministically so the advertised port is stable across restarts
|
||||
(`src/node/lifecycle.rs:1169-1180`). If no such port exists, the
|
||||
runtime returns `NoAdvertisedPort` and LAN discovery does not start
|
||||
(`src/discovery/lan/mod.rs:156-158`).
|
||||
|
||||
The runtime does two things concurrently:
|
||||
|
||||
1. **Responder.** It registers a DNS-SD service with instance name
|
||||
`fips-<first-16-chars-of-npub>` and a TXT record carrying the keys
|
||||
below. `mdns-sd`'s address auto-detection appends every non-loopback
|
||||
interface address, with `127.0.0.1` seeded so same-host peers and
|
||||
integration tests can still resolve the advert
|
||||
(`src/discovery/lan/mod.rs:182-203`).
|
||||
2. **Browser.** A background pump receives `ServiceResolved` events for
|
||||
the same service type. For each resolved advert it extracts the
|
||||
`npub` and `scope` TXT values, drops adverts that echo the node's own
|
||||
npub, drops cross-scope adverts (see scope filtering), drops records
|
||||
without an `npub`, and surfaces one `LanDiscoveredPeer` per routable
|
||||
interface address (`src/discovery/lan/mod.rs:212-299`). IPv6
|
||||
unicast link-local addresses without an interface scope id are
|
||||
skipped, since they cannot be dialed unambiguously
|
||||
(`src/discovery/lan/mod.rs:348-365`).
|
||||
|
||||
The TXT record carries three keys (`src/discovery/lan/mod.rs:47-55`):
|
||||
|
||||
| TXT key | Contents |
|
||||
| --- | --- |
|
||||
| `npub` | bech32-encoded npub of the advertising node |
|
||||
| `scope` | the node's discovery scope, if one is configured (omitted otherwise) |
|
||||
| `v` | FIPS protocol version (the same `PROTOCOL_VERSION` used by the Nostr advert) |
|
||||
|
||||
Once per node tick, the node drains browser events and acts on them in
|
||||
`poll_lan_discovery()` (`src/node/lifecycle.rs:907`, called from
|
||||
`src/node/handlers/rx_loop.rs:266`). For each discovered peer it finds
|
||||
a UDP transport whose family matches the peer address, parses the
|
||||
`npub` into a `PeerIdentity`, skips peers it is already connected to or
|
||||
currently connecting to, and otherwise initiates a connection.
|
||||
|
||||
### Handshake: Noise IK
|
||||
|
||||
LAN-discovered peers are dialed through the standard FMP outbound link
|
||||
path. `poll_lan_discovery()` calls `initiate_connection()`
|
||||
(`src/node/lifecycle.rs:380`), which, for connectionless transports
|
||||
such as UDP, allocates a link and **starts the Noise IK handshake**
|
||||
(documented at `src/node/lifecycle.rs:373-374`). This is the same
|
||||
link-layer handshake used by every other FMP connection — IK at the
|
||||
link layer per the FIPS architecture — not a different pattern for LAN
|
||||
peers.
|
||||
|
||||
The mDNS advert is **unauthenticated**: anyone on the link can
|
||||
multicast a TXT claiming any `npub`. Identity is proven end-to-end by
|
||||
the Noise IK handshake against the observed endpoint. A spoofed advert
|
||||
carrying another node's npub fails the handshake — the impostor does
|
||||
not hold the matching static key — and the half-open link is dropped.
|
||||
The mDNS advert is therefore a routing hint, never an identity
|
||||
assertion, exactly as a Nostr advert is treated (a successful contact
|
||||
is not trusted until FMP's Noise IK handshake completes).
|
||||
|
||||
> Note: a stale source doc-comment at `src/node/lifecycle.rs:904-906`
|
||||
> describes this path as a "Noise XX" handshake. That comment is
|
||||
> inaccurate — the path uses Noise IK as described above. The comment
|
||||
> is flagged for a separate source fix and does not reflect actual
|
||||
> behavior.
|
||||
|
||||
### Scope filtering
|
||||
|
||||
When a discovery scope is configured, the advert carries it in the
|
||||
`scope` TXT entry and the browser surfaces only peers whose advert
|
||||
carries a matching scope. Nodes on the same physical LAN but configured
|
||||
for different mesh networks therefore do not cross-feed each other.
|
||||
|
||||
The scope is resolved by `lan_discovery_scope()`
|
||||
(`src/node/lifecycle.rs:880-902`): the explicit
|
||||
`node.discovery.lan.scope`, if non-empty, is used directly. Otherwise
|
||||
the node falls back to deriving a scope from the Nostr discovery `app`
|
||||
tag (stripping the `fips-overlay-v1:` prefix when present). This lets
|
||||
an application keep its public, relay-visible Nostr `app` tag generic
|
||||
while still isolating LAN discovery per private network, or share one
|
||||
value across both. A node with no scope on either side surfaces all
|
||||
adverts it sees on the link.
|
||||
|
||||
### Configuration
|
||||
|
||||
LAN discovery is configured under `node.discovery.lan.*`
|
||||
(`src/config/node.rs:222-227`, `src/discovery/lan/mod.rs:88-129`):
|
||||
|
||||
| Key | Type | Default | Meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| `node.discovery.lan.enabled` | bool | `false` | Master switch. LAN discovery is opt-in; default-off avoids an unexpected per-link identity multicast on upgrade. |
|
||||
| `node.discovery.lan.service_type` | string | `_fips._udp.local.` | DNS-SD service type. Overridable mainly so integration tests can isolate multiple services on one loopback interface. |
|
||||
| `node.discovery.lan.scope` | string (optional) | unset | Application/network scope carried in the LAN-only `scope` TXT record. Kept deliberately separate from the public Nostr `app` tag. When unset, the scope falls back to the derived Nostr `app` value. |
|
||||
|
||||
The identity surface published over mDNS (`npub`, version, optional
|
||||
scope) is a strict subset of what `nostr.advertise` already publishes
|
||||
publicly, so enabling LAN discovery adds no marginal privacy cost
|
||||
beyond making the node's presence observable on its own local link.
|
||||
|
||||
### Relationship to Nostr discovery
|
||||
|
||||
The two mechanisms are complementary and independent:
|
||||
|
||||
| | Nostr-mediated | LAN/mDNS |
|
||||
| --- | --- | --- |
|
||||
| Reach | Internet-wide, via relays | Same broadcast domain only |
|
||||
| Signaling channel | Public Nostr relays | mDNS multicast on the local link |
|
||||
| NAT traversal | STUN + UDP hole-punch for `udp:nat` peers | None — endpoint is link-routable by construction |
|
||||
| Identity carrier | signed kind 37195 advert (authenticated at publish) | unauthenticated mDNS TXT (routing hint only) |
|
||||
| Identity proof | FMP Noise IK on the connection | FMP Noise IK on the connection |
|
||||
| Default | disabled (`nostr.enabled: false`) | disabled (`lan.enabled: false`) |
|
||||
| Scope key | `app` tag (public) | `scope` TXT (link-local), falls back to `app` |
|
||||
|
||||
Both ultimately converge on the same trust boundary: discovery only
|
||||
supplies candidate endpoints, and no peer is trusted until FMP's Noise
|
||||
IK handshake confirms the claimed identity. A node may run both at
|
||||
once — for example, advertising globally over Nostr while also pairing
|
||||
instantly with same-LAN peers — with no interaction between the two
|
||||
beyond the shared scope fallback.
|
||||
|
||||
## See also
|
||||
|
||||
- [../how-to/enable-nostr-discovery.md](../how-to/enable-nostr-discovery.md)
|
||||
|
||||
@@ -120,6 +120,7 @@ for internet connectivity:
|
||||
| UDP/IP | host:port | 1280–1472 | Unreliable | Primary internet transport |
|
||||
| TCP/IP | host:port | Stream | Reliable | Requires length-prefix framing |
|
||||
| Tor | .onion | Stream | Reliable | High latency, strong anonymity |
|
||||
| Nym | host:port | Stream | Reliable | Mixnet, outbound-only, strong anonymity |
|
||||
|
||||
**Shared medium transports** operate over broadcast- or multicast-capable
|
||||
media:
|
||||
@@ -190,6 +191,7 @@ proceed.
|
||||
| --------- | ---------------- |
|
||||
| TCP/IP | TCP three-way handshake |
|
||||
| Tor | Circuit establishment (typically 10–60s, default timeout 120s) |
|
||||
| Nym | SOCKS5 connect through mixnet (minutes possible, default timeout 300s) |
|
||||
| BLE | L2CAP CoC or GATT connection |
|
||||
| Serial | Physical connection (static) |
|
||||
|
||||
@@ -599,6 +601,120 @@ SOCKS5-level errors, MTU rejections, accepted/rejected inbound
|
||||
connections, and Tor control-port errors. The full counter table
|
||||
lives in [../reference/transports.md](../reference/transports.md).
|
||||
|
||||
## Nym: The Mixnet Transport
|
||||
|
||||
The Nym transport routes FIPS traffic through the Nym mixnet, providing
|
||||
network-level anonymity via Sphinx packet routing and timing
|
||||
obfuscation. It uses the "mixnet-as-proxy" pattern: a node connects
|
||||
outbound through a local `nym-socks5-client` SOCKS5 proxy, which carries
|
||||
the traffic into the mixnet. The `nym-socks5-client` runs as a separate
|
||||
process alongside the fips daemon and must be started independently.
|
||||
|
||||
Like Tor, Nym is a privacy-oriented deployment mode chosen for the
|
||||
anonymity properties of the mixnet, not a failover for other transports.
|
||||
Like TCP and Tor, it is connection-oriented and reliable; the same
|
||||
TCP-over-TCP considerations apply, and cost-based parent selection
|
||||
naturally deprioritizes the high-latency Nym links.
|
||||
|
||||
### Architecture
|
||||
|
||||
The Nym transport is a separate `NymTransport` implementation. It reuses
|
||||
the FMP header-based stream reader (`tcp/stream.rs`) for packet framing
|
||||
on the underlying byte stream, and follows the same connection-pool
|
||||
pattern as the TCP and Tor transports.
|
||||
|
||||
It maintains two pools: a `ConnectingPool` for background SOCKS5
|
||||
connection attempts, and an established pool of `NymConnection` entries.
|
||||
Each `NymConnection` holds a write half, a per-connection receive task,
|
||||
the configured MTU, and a connection timestamp.
|
||||
|
||||
| Property | Value |
|
||||
| -------- | ----- |
|
||||
| Addressing | IP:port or hostname:port |
|
||||
| Default MTU | 1400 bytes |
|
||||
| Framing | FMP header-based (shared with TCP) |
|
||||
| Connection model | Outbound-only, non-blocking connect through SOCKS5 |
|
||||
| Platform | Cross-platform (requires external nym-socks5-client) |
|
||||
|
||||
### Outbound-Only
|
||||
|
||||
The Nym transport is strictly outbound. It supports no inbound service:
|
||||
`accept_connections()` returns `false` and `discover()` returns no
|
||||
peers. A node using the Nym transport can initiate links to remote peers
|
||||
through the mixnet, but cannot accept inbound connections over Nym. (A
|
||||
node can still accept inbound links over other transports it runs.)
|
||||
|
||||
### Address Types
|
||||
|
||||
The Nym transport accepts two address formats, parsed into an internal
|
||||
target address:
|
||||
|
||||
- **IP:port** — a numeric IP and port, sent to the SOCKS5 proxy as a
|
||||
numeric target.
|
||||
- **Hostname:port** — the hostname is passed through SOCKS5 so it is
|
||||
resolved on the exit side rather than locally.
|
||||
|
||||
Both forms are routed through the same SOCKS5 proxy.
|
||||
|
||||
### Connection Establishment
|
||||
|
||||
Connection setup follows the same non-blocking pattern as the TCP and
|
||||
Tor transports. When FMP needs to reach a peer, the node initiates a
|
||||
background connect (`connect_async`). The transport spawns a background
|
||||
tokio task that opens a SOCKS5 connection through the local
|
||||
`nym-socks5-client`, configures the socket (including TCP keepalive),
|
||||
splits the stream, and spawns a per-connection receive loop using the
|
||||
shared FMP stream reader. The call returns immediately while the connect
|
||||
proceeds in the background.
|
||||
|
||||
SOCKS5 connection setup through the mixnet can take much longer than a
|
||||
direct TCP connection because each connection traverses multiple mix
|
||||
nodes with timing obfuscation. Accordingly the connect timeout defaults
|
||||
to 300 seconds (`connect_timeout_ms`). Non-blocking connect is essential
|
||||
here — a blocking connect would stall the FMP event loop for the
|
||||
duration of mixnet setup. As a fallback, `send_async(addr, data)`
|
||||
performs a connect-on-send if no connection to the address yet exists.
|
||||
|
||||
Each outbound packet is checked against the configured MTU before being
|
||||
written; an oversized packet is rejected with an MTU-exceeded error
|
||||
rather than being sent.
|
||||
|
||||
### Startup Readiness
|
||||
|
||||
At startup the transport validates the configured `socks5_addr` and then
|
||||
probes the SOCKS5 port to wait for `nym-socks5-client` to become ready,
|
||||
using exponential backoff (starting at 1 second, capped at 10 seconds
|
||||
between attempts) up to `startup_timeout_secs` (default 120 seconds). If
|
||||
the proxy does not become reachable within that window, the transport
|
||||
logs a warning and starts anyway; outbound connections then fail until
|
||||
the `nym-socks5-client` becomes available.
|
||||
|
||||
### Session Independence
|
||||
|
||||
Same as TCP and Tor: loss of a Nym connection does **not** tear down the
|
||||
FIPS peer. Noise keys, MMP state, and FSP sessions survive reconnection.
|
||||
|
||||
### Configuration
|
||||
|
||||
The Nym transport block (`transports.nym.*`) has the following fields:
|
||||
|
||||
| Field | Default | Description |
|
||||
| ----- | ------- | ----------- |
|
||||
| `socks5_addr` | `127.0.0.1:1080` | Address (host:port) of the local nym-socks5-client SOCKS5 proxy |
|
||||
| `connect_timeout_ms` | `300000` | Outbound SOCKS5 connect timeout in milliseconds (300s) |
|
||||
| `mtu` | `1400` | Maximum FIPS packet size for Nym connections, in bytes |
|
||||
| `startup_timeout_secs` | `120` | Seconds to wait for nym-socks5-client to become ready at startup |
|
||||
|
||||
The Nym transport requires an external `nym-socks5-client`. Named
|
||||
instances are supported for multiple proxy endpoints. Unknown
|
||||
configuration keys are rejected.
|
||||
|
||||
### Statistics
|
||||
|
||||
The Nym transport exposes per-instance counters covering successful
|
||||
send/receive, send/receive errors, connection establishment, SOCKS5-level
|
||||
errors, connect timeouts, and MTU rejections.
|
||||
|
||||
## Discovery
|
||||
|
||||
Discovery determines that a FIPS-capable endpoint is reachable at a given
|
||||
@@ -725,7 +841,8 @@ TransportType {
|
||||
}
|
||||
```
|
||||
|
||||
Predefined types exist for UDP, TCP, Ethernet, WiFi, Tor, and Serial.
|
||||
Predefined types exist for UDP, TCP, Ethernet, WiFi, Tor, Nym, BLE, and
|
||||
Serial.
|
||||
|
||||
### Congestion Reporting
|
||||
|
||||
@@ -750,6 +867,7 @@ on all forwarded datagrams.
|
||||
| UDP | `SO_RXQ_OVFL` kernel drop counter | `recvmsg()` ancillary data on every packet |
|
||||
| TCP | Not implemented | Returns `None` (TCP handles congestion internally) |
|
||||
| Tor | Not implemented | Returns `None` (TCP handles congestion internally) |
|
||||
| Nym | Not implemented | Returns `None` (TCP handles congestion internally) |
|
||||
| Ethernet | Not implemented | Returns `None` |
|
||||
|
||||
### Transport Addresses
|
||||
@@ -780,6 +898,7 @@ transitions through `Starting` to `Up` (operational). `stop()` moves to
|
||||
| Ethernet | **Implemented** | AF_PACKET SOCK_DGRAM, EtherType 0x2121, beacon discovery, Linux only |
|
||||
| WiFi | **Implemented** (via Ethernet transport, infrastructure mode) | mac80211 translates 802.11↔802.3; broadcast beacons unreliable through APs |
|
||||
| Tor | **Implemented** | Outbound SOCKS5, inbound via onion service, .onion and clearnet addressing |
|
||||
| Nym | **Implemented** | Outbound-only SOCKS5 through nym-socks5-client, mixnet anonymity, IP/hostname addressing |
|
||||
| BLE | **Implemented** (Linux/glibc only; experimental) | L2CAP CoC, ATT_MTU negotiation, per-link MTU; musl/macOS/Windows skip |
|
||||
| Radio | Future direction | Constrained MTU (51–222 bytes) |
|
||||
| Serial | Future direction | SLIP/COBS framing, point-to-point |
|
||||
|
||||
@@ -526,7 +526,7 @@ own.
|
||||
|
||||
| Failure | Symptom | Mitigation |
|
||||
| --- | --- | --- |
|
||||
| Symmetric NAT (one side) | Punch timeout | Retry with port-prediction heuristics; otherwise fall back to a relay or different transport |
|
||||
| Symmetric NAT (one side) | Punch timeout | Retry with port-prediction heuristics; otherwise fall back to an application-level relay |
|
||||
| Symmetric NAT (both sides) | Punch timeout | Application-level relay required |
|
||||
| Relay latency > 60 s | Stale reflexive address | Use low-latency relays; consider self-hosted relay |
|
||||
| Relay does not support ephemeral kinds | Signaling events persist | Use NIP-40 expiration + NIP-09 deletion as fallback |
|
||||
|
||||
Reference in New Issue
Block a user