Loading page...Загружаем страницу...正在加载页面...
AtlasRepo

The limit that matters isn't in my code: what I learned building a P2P file transfer app

Description and use

By turning TURN into a diagnostic and enforcing direct connections, Peerino eliminated client‑side abuse of the relay, reduced unnecessary traffic, and clarified the failure path. The redesign also highlighted the need for out‑of‑band identity verification and proper connection teardown.

Problem

Peerino’s initial design allowed abuse of the TURN relay because client‑side limits could be bypassed and credentials were exposed in plain text, enabling third‑party traffic and undermining the intended 100 MB transfer cap.

Outcome

By turning TURN into a diagnostic and enforcing direct connections, Peerino eliminated client‑side abuse of the relay, reduced unnecessary traffic, and clarified the failure path. The redesign also highlighted the need for out‑of‑band identity verification and proper connection teardown.

Workflow

  • 1. Peerino establishes a WebRTC connection with ICE servers including TURN.
  • 2. Sender retrieves connection stats via pc.getStats().
  • 3. Sender iterates over stats to find selected or nominated candidate‑pair reports.
  • 4. If any candidate is of type "relay", the sender sends an error message and closes the connection.
  • 5. Receiver shows a user‑friendly message: "Your connection requires a relay server. To share this file, connect to WiFi."

Evidence

When I started, Peerino used TURN as a fallback. If two peers couldn't connect directly, the file was relayed through a TURN server. Cloudflare's, in my case. Files up to 100 MB went through it.

Source

I saw the TURN credentials sitting there in plain text. Username and password, right in the receiver's browser.

Source

I turned TURN into a diagnostic instead of a transport. If the direct path isn't available, ICE can select a relay candidate pair and the connection establishes through it. But then a gate on the sender checks the selected candidate pair and refuses to send the file.

Source

The gate reads the WebRTC stats and looks for a relay candidate.

Source

If the pair is relay, the sender sends an error message and the transfer stops. The user sees: "Your connection requires a relay server. To share this file, connect to WiFi."

Source

The redesign didn't stop someone with the credentials from using the relay. They still can. The credentials still go to the browser.

Source

To answer the question the redesign raises: what protects the account today? Rate limiting on the Worker that issues credentials — 40 requests per hour per source IP, with 15-minute credentials.

Source

I re-read my own code before publishing this. The design doc said "the gate refuses the file." The code did exactly that. It sent an error message and returned. But it didn't close the connection.

Source

Signaling sees peer IDs and ICE candidates. TURN sees an IP pair and a handshake when a relay path is attempted. Neither sees file content. But the signaling server isn't authenticated out-of-band, so a compromised signaling server could, in theory, MITM the connection.

Source

  • Record date: 2026-10-07T13:40:58.067Z