@decentnetwork/peer 0.1.133 → 0.1.135

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/peer.js +33 -2
  2. package/package.json +1 -1
package/dist/peer.js CHANGED
@@ -34,7 +34,21 @@ import { createBoundUdp4Socket, closeDgramSocket } from "./transport/dgram-lifec
34
34
  const TURN_RELAY_SERVERS = (() => {
35
35
  const raw = process.env.DECENT_TURN_SERVERS?.trim();
36
36
  if (!raw) {
37
- return [{ host: "tokyo.fi.chat", port: 3478, username: "allcom", password: "allcompass" }];
37
+ // MORE THAN ONE, ALWAYS. This list is not a preference — it is the only
38
+ // way a peer learns its own public endpoint, so when every entry is down
39
+ // nobody can hole-punch and the WHOLE network silently degrades to TCP
40
+ // relay. That is not hypothetical: coturn on tokyo core-dumped and stayed
41
+ // dead for ten days, and with tokyo as the sole entry every link in the
42
+ // network ran at relay latency (~1200ms instead of ~130ms) the entire
43
+ // time. Nothing alerted, because the port stayed open.
44
+ //
45
+ // Ordered by expected reachability from the biggest population of peers.
46
+ // A dead entry costs one timeout before the next is tried, so listing a
47
+ // spare is close to free; having none is a network-wide outage.
48
+ return [
49
+ { host: "tokyo.fi.chat", port: 3478, username: "allcom", password: "allcompass" },
50
+ { host: "gfax.cn", port: 3478, username: "allcom", password: "allcompass" },
51
+ ];
38
52
  }
39
53
  return raw
40
54
  .split(",")
@@ -5206,7 +5220,24 @@ export class Peer {
5206
5220
  // Permit the advertised private candidate when both peers share the same
5207
5221
  // public NAT; if it is a CGNAT/private collision and never validates, the
5208
5222
  // normal 12s stale-LAN-lock breaker restores the public/relay path.
5209
- const samePublicNat = !!this.#srflxCache?.addr.host && this.#srflxCache.addr.host === host;
5223
+ // "We share one NAT" the only reason to trust a peer's private address
5224
+ // without checking our own subnets.
5225
+ //
5226
+ // It requires that we are actually BEHIND a NAT. A node with a public IP
5227
+ // has srflx == its own address, so the naive comparison matched every
5228
+ // offer whose observed source was that same address (relayed or
5229
+ // reflected through us), and the subnet check below was bypassed for any
5230
+ // private host at all. tokyo, on a public IP, took 10.0.0.245 from a
5231
+ // laptop across the Pacific this way and pinned its session to it —
5232
+ // re-adopting it within seconds of every self-heal, because this path
5233
+ // writes session.remote directly and never goes through #adoptRemote.
5234
+ //
5235
+ // Behind a NAT, srflx is the NAT's address and differs from every local
5236
+ // interface, so the extra test costs nothing there and closes the hole
5237
+ // for public hosts.
5238
+ const srflxHost = this.#srflxCache?.addr.host;
5239
+ const weAreBehindNat = !!srflxHost && !getPhysicalLanAddresses().includes(srflxHost);
5240
+ const samePublicNat = weAreBehindNat && srflxHost === host;
5210
5241
  const sameLan = lanPort !== 0 &&
5211
5242
  isPrivateAddress(lanHost) &&
5212
5243
  !isCgnatAddress(lanHost) &&
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/peer",
3
- "version": "0.1.133",
3
+ "version": "0.1.135",
4
4
  "description": "Pure TypeScript port of Elastos Carrier (toxcore-derived) P2P messaging. DHT, onion routing, TCP relay, FlatBuffers app payloads, Express offline relay. Wire-compatible with iOS Beagle and the Carrier C SDK.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",