04. Discovery and Transport¶
Status: Draft.
1. Intent¶
Devices connect to each other directly over application-level QUIC (RFC 9000), authenticating with their LP device keys. Locally they find each other with mDNS/DNS-SD and BLE and need no server at all. When apart they use a small set of helpers for discovery, hole-punch coordination and relaying. Helpers are replaceable and untrusted. No traffic of any kind routes through a server LP depends on. See ADR 0011, ADR 0012 and ADR 0013.
2. Design rule for helpers¶
Any helper may be operated by anyone, is listed in the user's own records, and is never trusted with plaintext or identity.
A malicious helper can at worst deny service; clients route around it. Every other section of this chapter is constrained by this rule.
3. Transport: QUIC¶
3.1 Connections and streams¶
There is one QUIC connection per device pair and one stream per capability (clipboard,
files, remote input, notifications, media control, and so on), so a large file transfer
never stalls an interactive stream. The TLS handshake carries the ALPN token ligature/1,
which is the protocol version; no message carries one. Every stream is bidirectional and
its first frame is a stream header
(org.ligatureprotocol.stream) naming its purpose:
gossip, manifest, pairing (chapter 02 section 4), or a capability type. Whichever
peer needs a stream opens it; the dialer opens the gossip stream first. A receiver resets a
stream, and nothing else, with a transport code: 1 for a purpose it does not understand, 2
for a peer not yet admitted (section 3.2), 3 for a first message it will not act on from
this peer, 4 for a frame or header it cannot decode; a capability's own codes start at 16
(ADR 0038). A message on a stream is a
frame: a 4-byte big-endian length and one CBOR map with a type field, at most 1 MiB
unless the capability says otherwise
(ADR 0036). A capability may use
several streams of its purpose at once: files (chapter 05 section 3d) opens a control
stream per transfer and a data stream per file in flight, the receiver's descriptor
bounding how many, so a large file never stalls a small one or the clipboard.
3.2 Authentication¶
Peers authenticate with their LP device keys using TLS raw public keys (RFC 7250). There
are no certificate authorities. A connection proceeds past authentication only if the
presented key is a binding of mine, a principal I use, or a binding of a known person
(chapter 02); otherwise the only thing offered is the pairing ceremony. The handshake
accepts any well-formed raw public key; recognition is decided afterwards from the local
store, so a device learned through gossip is recognised the first time it connects and a
revoked one is refused on its next connection; a session already open with a device whose
revocation arrives, by gossip or by the user's own hand, is closed at once
(ADR 0039). Until that decision a
receiver dispatches only the pairing purpose: every other stream the peer opens waits in a small bounded
queue, to be dispatched if the peer is admitted and reset with code 2 if it is dropped, so
a stranger kept for a ceremony learns nothing from the streams it opened
(ADR 0038).
3.3 Connection migration¶
QUIC connection migration keeps a session alive when a device changes network (Wi-Fi to mobile data, roaming between access points). Open question: how migration interacts with relay paths and with the per-epoch local identifiers in section 4.1.
3.4 End to end¶
The QUIC/TLS session is the end-to-end layer (chapter 03). A relay forwards packets and terminates nothing, so it sees only ciphertext whether the path is direct or relayed.
4. Local path¶
4.1 mDNS/DNS-SD¶
Each device advertises a DNS-SD service instance of type _ligature._udp, the QUIC port in
the SRV record (ADR 0037). The record carries
nothing identifying: no key, no display name, no host name, nothing stable across restarts.
Its TXT record has two keys, v (the protocol version, the same number as the ALPN token)
and id (16 hex characters drawn at random when the daemon starts), and lp-<id> is both
the instance name and the SRV target host. id is a hint for telling instances apart and
backing off after a failed authentication, never a credential: a device dials every
instance whose version it supports and the raw-public-key handshake decides. Open question:
a per-epoch derivation of id that lets devices in one set recognise each other before
dialling, without revealing anything to bystanders.
4.2 BLE¶
BLE advertisements let phones and low-power devices be discovered and woken, and are the path to iPhone accessory profiles (chapter 08). Open question: whether LP defines its own GATT service or only uses BLE to bootstrap a QUIC connection over IP.
4.3 Direct QUIC¶
Once a peer is found locally the device dials it directly. No helper is involved.
5. Remote path: three helper roles¶
5.1 Discovery: where is device X now?¶
Two options, both allowed and both usable together:
- Signed address records in a DHT. A device publishes a record of its current reachable addresses and relays, signed by its device key and keyed by that key's public part, to a DHT such as BitTorrent Mainline via pkarr, as iroh does. Anyone can look it up; only the key holder can publish a valid record.
- Gossip. Relays a device uses are signed facts gossiped like any other (chapter 06), so my devices learn each other's relays when they meet.
Open question: record lifetime, refresh cadence, and what a device does when the two sources disagree.
5.2 Hole-punch coordination¶
When both peers are behind NAT, a coordinator exchanges their observed addresses so they can attempt a direct QUIC connection. The coordinator learns public addresses and timing but nothing else. Open question: whether the relay (5.3) always doubles as coordinator or whether the roles can be split.
5.3 Relay¶
When hole punching fails (common on mobile and CGNAT networks) traffic is relayed. The relay forwards QUIC packets it cannot decrypt. Anyone can run a relay. The default personal relay is the user's always-on home hub, the same box that hosts their Matter controller or media server. Clients can list several relays; a project-run relay may exist as a swappable convenience default. Open question: relay selection and failover order, and whether relays should be rate-limited per device key.
flowchart LR
subgraph Home["At home: no helpers"]
L1["laptop"] <-- "mDNS/DNS-SD, BLE" --> P1["phone"]
L1 == "direct QUIC" ==> P1
end
subgraph Away["Away: helpers see addresses and ciphertext only"]
P2["phone"] -- "where is laptop?" --> DHT["DHT"]
DHT -- "signed addresses and relays" --> P2
P2 <-- "observed addresses" --> C["coordinator"]
C <-- "observed addresses" --> L2["laptop"]
P2 == "hole-punched QUIC, if it works" ==> L2
P2 == "QUIC" ==> Rl["relay"]
Rl == "QUIC, otherwise" ==> L2
end
6. Situations¶
| Situation | Discovery | Path | Helpers used |
|---|---|---|---|
| At home, same LAN | mDNS/DNS-SD, BLE | Direct QUIC | None |
| Away, user has a home hub | DHT record, gossiped relays | Direct QUIC via hole punch, else relay through the hub | Hub as coordinator and relay |
| Away, no home hub | DHT record, gossiped relays | Direct QUIC via hole punch, else relay | Any relay listed in the user's records |
| Convenience default | DHT record | Direct QUIC via hole punch, else relay | Project-run relay, replaceable at any time |
In every row the helper sees only addresses and ciphertext. A pairing with a headless device at home uses the device's own web page (chapter 02 section 5) over the LAN.
7. Optional: WireGuard / Headscale integration¶
LP does not depend on WireGuard. As an optional integration, LP can generate Headscale/WireGuard peer configurations from the user's device list for users who want full network access to their home (SSH, NAS, media). This is a convenience for other software, not an LP transport, and the protocol must work identically without it. See ADR 0013.
8. Wake and presence¶
Devices should be able to wake peers and learn their presence cheaply. Open question: how presence interacts with battery constraints on mobile platforms, and whether presence is itself a capability (chapter 05).
9. Open questions¶
- Which QUIC implementation(s) the reference implementation should target, and whether iroh's endpoint abstraction is reusable directly.
- How multiple network paths to the same peer are ranked (direct over relay, IPv6 over IPv4, Wi-Fi over mobile).
- Whether IPv6 reachability should be preferred aggressively, since it often removes the need for hole punching (chapter 08).