@@ -363,25 +363,25 @@ as follows:
363
363
Alice-->>Bob: hm(FINDNODE)
364
364
```
365
365
366
- Bob is behind a NAT. Bob is in Relay's kbuckets, they have a session together and Bob has
366
+ Bob is behind NAT. Bob is in Relay's kbuckets, they have a session together and Bob has
367
367
sent a packet to Relay in the last ~20 seconds hence Relay can get through Bob's NAT[^1].
368
368
369
369
As part of recursive query for peers, Alice sends a [FINDNODE] request to Bob, who's ENR
370
- it received from Relay. By making an outgoing request to Bob, if Alice is behind a NAT,
370
+ it received from Relay. By making an outgoing request to Bob, if Alice is behind NAT,
371
371
Alice's NAT adds the filtering rule `(Alice's-LAN-ip, Alice's-LAN-port, Bob's-WAN-ip,
372
372
Bob's-WAN-port, entry-lifetime)` to it's UDP session table[^2] [^3]. This means a hole now
373
373
is punched for Bob in Alice's NAT for the duration of `entry-lifetime`. The request to Bob
374
- times out as Bob is behind a NAT.
374
+ times out as Bob is behind NAT.
375
375
376
376
Alice initiates an attempt to punch a hole in Bob's NAT via Relay. Alice resets the
377
- request time out on the timed out [FINDNODE] message and wraps the message's nonce in a
377
+ request time- out on the timed out [FINDNODE] message and wraps the message's nonce in a
378
378
[RELAYINIT] notification and sends it to Relay. The notification also contains its ENR and
379
379
Bob's node id.
380
380
381
381
Relay disassembles the [RELAYINIT] notification and uses the `target-id` to look up Bob's
382
382
ENR in its kbuckets. With high probability, Relay will find Bob's ENR in its kbuckets as
383
383
~1 second ago, Relay assembled a [NODES] response for Alice containing Bob's ENR (see [UDP
384
- Communication] for recommended time out duration). Relay assembles a [RELAYMSG]
384
+ Communication] for recommended time- out duration). Relay assembles a [RELAYMSG]
385
385
notification with Alice's message nonce and ENR, then sends it to the address in Bob's
386
386
ENR.
387
387
@@ -409,28 +409,37 @@ hence of its ability to relay.
409
409
410
410
UDP session table entry lifetimes are configurable, though a common lower bound is 20
411
411
seconds[^1]. Bob must periodically reset the session table entry for Alice in its NAT to
412
- keep the hole for Alice punched. If Alice too is behind a NAT, it must do the same for Bob.
413
- Implementations must ensure, when a node behind a NAT does not send a packet to a peer
412
+ keep the hole for Alice punched. If Alice too is behind NAT, it must do the same for Bob.
413
+ Implementations must ensure, when a node behind NAT does not send a packet to a peer
414
414
within the entry lifetime then an empty packet is sent that is dropped by the peer.
415
415
416
416
NAT hole punching unavoidably creates overhead for all nodes in the network but once a
417
417
hole is punched, keeping it punched requires no interaction between peers. The incentive
418
- for nodes behind a NAT to keep holes for its peers punched is to avoid reestablishing a
418
+ for nodes behind NAT to keep holes for its peers punched is to avoid reestablishing a
419
419
session. If there is no hole for Alice in Bob's NAT when Alice carries out a
420
420
[liveness check], Bob is considered offline and the session to Bob useless. If the node
421
- behind a NAT intends to frequently communicate with a peer, reestablishing the session is
421
+ behind NAT intends to frequently communicate with a peer, reestablishing the session is
422
422
more costly than managing the interval of sent packets to that peer.
423
423
424
- ### Discovering if the local node is behind a NAT and must keep holes for peers punched
425
-
426
- A node may be assigned an externally reachable socket to advertise at start-up. If it is
427
- not, the [external socket used by the local node is discovered] at runtime and at start-up
428
- the node assumes it is behind at least one level of NAT and must activate the
429
- [mechanism for keeping holes punched][^1].
430
- Once an externally reachable IP address is known, implementations will try to bind to the
431
- address at some number of ports, randomly selected from a given range of probably unused
432
- ports. If binding succeeds for any port, the node is not behind a NAT and the
433
- [mechanism for keeping holes punched] is deactivated.
424
+ ### Discovering if the local node is behind NAT and must keep holes for peers punched
425
+
426
+ A node may at start-up be assigned an externally reachable socket to advertise as well as a
427
+ listen socket. If those sockets are not equivalent, the node is behind NAT and the
428
+ [mechanism for keeping holes punched] is activated. Like so, a node assumes it is behind
429
+ NAT if an externally reachable socket is omitted from the initial configuration and must
430
+ activate the [mechanism for keeping holes punched]. The
431
+ [external socket used by the local node is assessed] at runtime. Once a new externally
432
+ reachable IP address is known, implementations will try to bind to the address at some
433
+ number of randomly selected ports from a given range of probably unused ports. If binding
434
+ succeeds with any port, the node is not behind NAT and the
435
+ [mechanism for keeping holes punched] is
436
+ deactivated. This solution assumes, in most scenarios where port-forwarding cannot be
437
+ configured the local node host's address is private to the address realm of the device
438
+ operating the NAT level furthest from the local node host[^1]. If the host and NAT device
439
+ use the same IP address, binding will always succeed, so this method may give a false
440
+ negative. However, this is not detrimental. A node behind NAT that deactivates the
441
+ [mechanism for keeping holes punched] will more frequently have to re-establish sessions
442
+ to its peers.
434
443
435
444
[EIP-778]: ../enr.md
436
445
[identity scheme]: ../enr.md#record-structure
@@ -448,7 +457,7 @@ ports. If binding succeeds for any port, the node is not behind a NAT and the
448
457
[UDP communication]: ./discv5-wire.md#udp-communication
449
458
[Sessions]: ./discv5-theory.md#sessions
450
459
[liveness check]: ./discv5-theory.md#table-maintenance-in-practice
451
- [external socket used by the local node is discovered ]: ./discv5-theory.md#maintaining-the-local-node-record
460
+ [external socket used by the local node is assessed ]: ./discv5-theory.md#maintaining-the-local-node-record
452
461
[mechanism for keeping holes punched]: ./discv5-theory.md#job-of-keeping-the-hole-punched-falls-on-bob-and-bob's-incentive-to-do-so
453
462
454
463
[^1]: https://pdos.csail.mit.edu/papers/p2pnat.pdf
0 commit comments