Finding a Peer Without Mistaking Location for Trust

Syncthing's device-ID checks answer who a peer is, but they do not answer where that peer can be reached. This chapter focuses on the reachability layer: how local discovery, global discovery, static addresses, and relays help two already-configured devices find a usable route, what each path reveals, and why none of those paths replaces certificate-based authorization. The practical judgment is to treat every discovered address as a lead. The connection becomes trusted only when it returns to the identity checks described earlier.

Discovery is an address directory, not a permission system

A static address is the simplest way for one device to find another. If a home server has a stable address or a usable DNS name, a laptop can try that address directly. But many personal devices do not stay at one address. A laptop moves between networks, a home router changes its external address, and two machines on the same local network may be able to reach each other even though neither has a useful public address. A peer-to-peer synchronizer needs a way to learn current candidates without turning every connection into a manually maintained networking project.

Syncthing uses two discovery scopes for this purpose. Local discovery is intended for devices that share a local network. The device periodically broadcasts on IPv4 or multicasts on IPv6 an announcement containing its device ID and the addresses at which it believes it can accept synchronization connections. The current client sends announcements roughly every 30 seconds and keeps a short-lived cache of what it has heard. An instance ID generated at startup helps other devices notice that a known device has restarted, so a new announcement is not confused with a stale one.

The contents make local discovery useful and observable at the same time. A laptop does not need to know a server's hostname: it can learn the server's device ID and a local address directly from the LAN. Unspecified addresses can be interpreted using the source address of the announcement, which lets a device describe a listening port without knowing every interface address in advance. But anyone able to observe that local traffic can also infer that a machine runs Syncthing and see the announced identity and port information.

Local discovery is not cryptographically authenticated in the way the device-to-device connection is. An announcement is an address suggestion, not a signed authorization statement. A malicious or misconfigured machine could announce a candidate address associated with an ID it does not control. That does not automatically give it access to a folder. When Syncthing actually connects, the peer certificate still has to hash to the ID configured for the intended device. The unauthenticated announcement can misdirect a connection attempt or create a privacy problem, but it does not by itself change the allowlist.

Global discovery serves a different network situation. A device announces connection addresses to a discovery server over HTTPS. When another device needs to find it, the client queries the service with the requested device ID and receives the currently registered addresses. This is helpful when the devices are not on the same LAN and have no stable address configured. The global client presents its own certificate when announcing, allowing the server to verify that the announcing device owns the identity being registered.

The discovery server's identity is also part of the protection story. Syncthing can carry an expected server device ID in the discovery-server configuration and compare the server certificate's fingerprint with that expected identity. This is certificate pinning: the client is not relying only on a general operating-system CA bundle and a hostname. It is applying the same fingerprint idea used for device identities to the service it consults. The global request remains an address lookup, however. It does not authorize the returned endpoint to exchange files.

Global discovery also creates a clearer operator and observer trade-off. The service can associate a device ID with external connection addresses and may infer relationships from announcements and queries. An Internet observer may infer which machines run Syncthing, while the discovery operator can learn more about which devices are present and connected. HTTPS protects the contents of the client-server exchange from ordinary network interception, but it does not make the existence of the exchange disappear. Syncthing's security model protects file traffic; it does not promise anonymity.

The narrowness of the discovery record is part of the design. Discovery is concerned with an identity, an address, and the transport information needed to attempt contact; it is not where Syncthing publishes a folder listing or file contents. That limits what a discovery operator needs to know, but it does not make the remaining metadata trivial. An address can reveal a home connection or a workplace network, and a pattern of announcements and queries can reveal that devices are active together. Turning global discovery off removes that particular service from the path, but devices with changing external addresses may then be unreachable unless they have a static route or another way to connect.

This distinction is easiest to see as a three-step process. First, a device produces or retrieves an address candidate. Second, the connection service chooses whether that candidate is worth dialing, possibly preferring a local route or a better transport. Third, after TLS, Syncthing derives the remote device ID from the certificate and compares it with the expected ID. The first step answers “where might the device be?” The third answers “is the device actually the one I configured?” Collapsing those questions would let a directory service become an unintended authority over file access.

Local discovery is intentionally announcement-driven rather than a directory that answers every request. A device keeps listening for announcements and periodically sends its own; there is no separate solicitation response that guarantees a fresh answer on demand. That makes the cache and its age meaningful. A recently restarted device can trigger a fresh observation through its new instance ID, while a device that has gone silent eventually stops being a useful candidate. The trade-off is modest delay and stale-address handling in exchange for a simple local protocol that does not require a coordinator on every network.

The connection manager can also have more than one possible address for a configured device. A static address may remain useful as a fallback, a local announcement may offer a lower-latency route, and a global result may provide an external route when the local one is unavailable. These are candidate paths, not competing identities. Syncthing can try them under its connection policy, but the successful path still has to produce the certificate that matches the configured device ID. A route that is faster is not allowed to become a route that is trusted more.

Global discovery has the same separation in a different form. The announcing device proves ownership of its identity to the discovery server through its certificate, while the lookup client asks for an address associated with a requested ID. The service is maintaining a registry of reachability information, not a registry of file contents or a permission to synchronize. If the returned address leads to a different certificate, the final device-ID check rejects it. If the registry has no current address, the devices may be correctly paired and still unable to connect until another route becomes available.

Relays change the route, not the identity

Discovery can tell a device where to try, but some devices cannot accept a direct connection at all. Network address translation may hide both devices behind routers that do not allow an incoming connection. Port forwarding may be unavailable or undesirable. Syncthing uses a relay as a fallback service for this case: a relay gives the two endpoints a rendezvous point and forwards traffic between them.

A relay connection has two conceptual stages. In the control stage, a client uses a TLS-protected relay protocol to join a relay or request a session with a particular device. The relay creates or returns the information needed for the two clients to join the same forwarding session. In the session stage, the relay forwards bytes between the endpoints. At that layer the relay is a transport intermediary, not the endpoint that interprets the synchronization protocol.

Syncthing then establishes its ordinary device-to-device TLS connection inside that relay session. The current relay dialer obtains an invitation, joins the session, wraps the resulting socket as a TLS client or server according to the invitation, and performs the same kind of synchronization handshake used on a direct path. The relay session may be plain byte forwarding at its own protocol layer, but the bytes being forwarded are protected by the end-to-end BEP TLS layer.

sequenceDiagram participant A as Device A participant D as Discovery service participant R as Relay participant B as Device B A->>D: Announce identity and candidate addresses B->>D: Query for A's device ID D-->>B: Return candidate address or relay route alt Direct route works B->>A: Open direct connection A-->>B: TLS and device-ID validation else Direct route fails B->>R: Request session invitation for A R-->>A: Deliver invitation A->>R: Join forwarding session B->>R: Join forwarding session A<<->>R: Encrypted synchronization traffic R<<->>B: Forward bytes Note over A,B: BEP TLS remains end to end end

This arrangement gives the relay a narrower role than a central file service, but not zero visibility. The relay can learn the participating device IDs, when they connect, and other traffic metadata such as timing or volume. It can also refuse service, become unavailable, or impose capacity limits. What it should not learn from the documented design is the plaintext file content, because it never holds the endpoint's synchronization keys. A relay can be operationally important without becoming the custodian of the synchronized files.

The two-stage design also prevents a successful relay rendezvous from being mistaken for a successful peer relationship. The relay can deliver an invitation and connect two sockets, yet the subsequent endpoint TLS handshake can still fail because the certificate is unexpected, the peer is the local device, or the configured policy rejects the connection. Conversely, a relay can be honest about forwarding bytes and still be a poor operational choice if it is unreliable or exposes metadata that matters to the user. Connectivity and trust remain separate measurements even when they share one physical route.

That distinction matters when assessing a public relay. “The relay cannot inspect the contents” is a content-confidentiality statement, not a claim that the relay is invisible or trusted for all purposes. Someone choosing a relay still has to consider metadata exposure and availability. Conversely, refusing every relay because it is not a trusted storage endpoint would throw away a useful connectivity mechanism without recognizing that the end-to-end protocol preserves the main file-content boundary.

The identity relationship remains invariant across these paths. On a direct connection, the TLS handshake follows the address attempt. On a relayed connection, the socket first passes through the relay's session protocol and then carries the same endpoint TLS handshake. The route changes; the expected certificate fingerprint does not. This is why the earlier identity layer is more durable than any particular address, discovery server, or relay. It gives Syncthing a stable answer to “which device may speak?” while discovery and relays answer the separate question “how can the bytes get there?”

There are also failure modes that the separation helps explain. A missing local announcement may mean the devices are on different networks or local discovery is disabled; it is not proof that the peer is unauthorized. A global lookup may return no address even though both IDs are correctly configured; that is a reachability or announcement problem. A relay may provide a session while the subsequent TLS check rejects the endpoint; that is a trust failure, not a successful synchronization path. A device may pass identity checks and still have no shared folder or no usable file state. Finding a route is only the beginning of the protocol relationship.

Once a route and an authorized identity are in place, the two devices can exchange information about the folders they share. That information is more consequential than an address: it describes what each side believes exists, which version it is offering, and what the other side may need. The next boundary is therefore the shared model, where Syncthing turns an established connection into a coordinated view of file state.

References