n0 QUIC NAT Traversal
draft-bruynooghe-n0-quic-nat-traversal-00
This document is an Internet-Draft (I-D).
Anyone may submit an I-D to the IETF.
This I-D is not endorsed by the IETF and has no formal standing in the
IETF standards process.
| Document | Type | Active Internet-Draft (individual) | |
|---|---|---|---|
| Author | Floris Bruynooghe | ||
| Last updated | 2026-07-06 | ||
| RFC stream | (None) | ||
| Intended RFC status | (None) | ||
| Formats | |||
| Stream | Stream state | (No stream defined) | |
| Consensus boilerplate | Unknown | ||
| RFC Editor Note | (None) | ||
| IESG | IESG state | I-D Exists | |
| Telechat date | (None) | ||
| Responsible AD | (None) | ||
| Send notices to | (None) |
draft-bruynooghe-n0-quic-nat-traversal-00
QUIC F. Bruynooghe
Internet-Draft n0 Inc.
Intended status: Informational 6 July 2026
Expires: 7 January 2027
n0 QUIC NAT Traversal
draft-bruynooghe-n0-quic-nat-traversal-00
Abstract
A description of how noq (https://github.com/n0-computer/noq)
performs NAT traversal for iroh (https://github.com/n0-computer/
iroh), including all current bugs. This is not yet a specification,
though further revisions migth be.
Status of This Memo
This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
This Internet-Draft will expire on 7 January 2027.
Copyright Notice
Copyright (c) 2026 IETF Trust and the persons identified as the
document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents (https://trustee.ietf.org/
license-info) in effect on the date of publication of this document.
Please review these documents carefully, as they describe your rights
and restrictions with respect to this document. Code Components
extracted from this document must include Revised BSD License text as
described in Section 4.e of the Trust Legal Provisions and are
provided without warranty as described in the Revised BSD License.
Bruynooghe Expires 7 January 2027 [Page 1]
Internet-Draft n0 QNT July 2026
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2
2. Conventions and Definitions . . . . . . . . . . . . . . . . . 3
3. NAT Traversal . . . . . . . . . . . . . . . . . . . . . . . . 3
3.1. Establishing a connection . . . . . . . . . . . . . . . . 3
3.2. Gathering address candidates . . . . . . . . . . . . . . 3
3.3. Negotiating Extension use . . . . . . . . . . . . . . . . 3
3.4. Exchanging address candidates . . . . . . . . . . . . . . 4
3.5. Initiating NAT traversal . . . . . . . . . . . . . . . . 4
3.5.1. NAT probes . . . . . . . . . . . . . . . . . . . . . 4
3.5.2. Probe responses . . . . . . . . . . . . . . . . . . . 5
3.5.3. Successful NAT traversal . . . . . . . . . . . . . . 6
4. Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
4.1. ADD_ADDRESS . . . . . . . . . . . . . . . . . . . . . . . 6
4.2. REMOVE_ADDRESS . . . . . . . . . . . . . . . . . . . . . 7
4.3. REACH_OUT . . . . . . . . . . . . . . . . . . . . . . . . 7
5. Security Considerations . . . . . . . . . . . . . . . . . . . 8
6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 8
7. Normative References . . . . . . . . . . . . . . . . . . . . 8
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 9
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 9
1. Introduction
This document describes how noq (https://github.com/n0-computer/noq)
currently performs NAT traversal using a QUIC extension. It is based
on [SEEMANN-QNT], but with heavy modifications. This is not expected
to be the final shape of the protocol, and does not aim to be a
specification.
The NAT traversal described here functions as a QUIC extension which
needs to be negotiated in the transport parameters. Once negotiated
the server can share NAT traversal address candidates using
ADD_ADDRESS frames. NAT traversal is initiated by the client using
REACH_OUT frames, and performed using [QUIC-TRANSPORT] PATH_CHALLEGE
and PATH_RESPONSE frames in probing packets to achieve NAT traversal.
The current implementation is combined with [QUIC-ADDR-DISCOVERY] for
gathering address candidates and [QUIC-MULTIPATH] for opening
multiple paths concurrently, however these mechanisms are somewhat
orthogonal and not not require tight integration.
Bruynooghe Expires 7 January 2027 [Page 2]
Internet-Draft n0 QNT July 2026
2. Conventions and Definitions
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in
BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here.
3. NAT Traversal
3.1. Establishing a connection
Both endpoints are expected to be able to establish a QUIC connection
already. This is done via a "relay" path, the transport of this is
out of scope. However in iroh this looks like a normal IP path that
uses IPv6 Unique Local Addresses as far as the QUIC stack is
concerned.
Once the connection is established with the extension negotiated the
endpoints can perform NAT traversal.
3.2. Gathering address candidates
Both endpoints need to gather address candidates to participate in
the holepunching from the same UDP socket that takes part in the
holepunching. This is done using [QUIC-ADDR-DISCOVERY] using a
sparate connection to a cooperating server.
The discovered addresses are propagated up to the application, which
has full control over which ones it decides to use for NAT traversal
by passing any desired address candidates into the QUIC stack as NAT
traversal address candidates.
3.3. Negotiating Extension use
Endpoints advertise their support of the extension by sending the
max_remote_nat_traversal_addresses (0x3d7f91120401) set to a non-zero
variable-length integer.
The value advertised by the server is not used by the client. It is
only used by the server itself to limit the number of address
candidates the application is allowed to use.
The value sent by the client limits the number of address candidates
the server can advertise to the client at any given time.
Bruynooghe Expires 7 January 2027 [Page 3]
Internet-Draft n0 QNT July 2026
3.4. Exchanging address candidates
The server advertises address candidates using ADD_ADDRESS frames.
Any address candidates advertised by the server that exceed the
allowed number the client advertised in the transport parameter, are
ignored by the client. Each ADD_ADDRESS frame uses a unique and
monotonically incrementing sequence ID.
If the server wants to remove an address candidate from the set of
address candidates the client can use, it uses the REMOVE_ADDRESS
frame using a sequence ID of a previously sent ADD_ADDRESS frame.
The client ignores an unknown sequence ID in any REMOVE_ADDRESS
frames.
If the server receives an ADD_ADDRESS or REMOVE_ADDRESS frame it
closes the connection with the PROTOCOL_VIOLATION transport error.
3.5. Initiating NAT traversal
The client initiates NAT traversal by sending one or more REACH_OUT
frames, each containing one of the client's address candidates. At
the same time the client sends out probes to all the address
candidates the server advertised.
Upon receipt of a REACH_OUT frame the server also sends out a probe
to the client's address candidate advertised in the frame.
NAT traversal happens in rounds, each round has a sequence ID. The
receipt of a higher sequence ID than the current round implies the
termination of the previous round. This means that any probes which
have not yet had a response will no longer be retried.
If the server sends a REACH_OUT frame the client closes the
connection with the PROTOCOL_VIOLATION transport error.
3.5.1. NAT probes
NAT probes are valid QUIC packets containing a PATH_CHALLENGE frame,
sent off-path to the address candidate provided by the remote
endpoint. They are treated as in Section 8.2.1 of [QUIC-TRANSPORT],
except they are not padded to 1200 bytes. As a result any valid
PATH_RESPONSE received for such a challenge does not validate the
path.
Such NAT probes are treated as _probing frames_ as defined in
Section 9.1 of [QUIC-TRANSPORT]. Since this extension is used
together with [QUIC-MULTIPATH] this re-introduces the concept of
probing frames even when [QUIC-MULTIPATH] is negotiated.
Bruynooghe Expires 7 January 2027 [Page 4]
Internet-Draft n0 QNT July 2026
Currently these NAT probes are sent using the active CID of the
[QUIC-MULTIPATH] PathId they are sent on, in clear violation of
Section 9.5 of [QUIC-TRANSPORT].
Since PATH_CHALLENGE frames are not retransmittable the sending
endpoint has to re-send NAT probes if it does not receive a timely
response. For this the normal PTO duration calculation is used,
using the initial RTT for new paths and using no ack-delay since
PATH_RESPONSES must be sent immediately. The exponent of the
exponential backoff is the retry count of the probe. Finally NAT
probes are abandoned once a new round is started, or a fixed timeout
of 30s elapsed.
Once a successful response is received from a remote address probing
of that remote address stops, even if there are still other un-
responded challenges to the same remote address.
In combination with [QUIC-MULTIPATH] an acknowledgement for the NAT
probe migth be received over another path, even if no matching
PATH_RESPONSE is received. These acknowledgements do not influence
the sending of new challenges when no timely response is received.
3.5.2. Probe responses
Upon receiving an off-path probing packet containing a
PATH_CHALLENGE, the receiving endpoint handles this as any other path
validation or liveness probe response as specified in Section 8.2.2
of [QUIC-TRANSPORT]. Since the receiving endpoint does not know the
reason for this path challenge it always expands the packet to the
1200 byte limit required for path validation.
When the client receives an off-path PATH_CHALLENGE it always
includes a new PATH_CHALLENGE together with the PATH_RESPONSE it must
send, turning the response into a new NAT probe. This has two
benefits:
* It speeds up opening of new paths, since as per [QUIC-MULTIPATH]
only the client can open a new path a successful NAT traversal can
only be acted upon by the client. Sending a new challenge before
the next challenge retry would occur is faster.
* It enables NAT traversal even for challenges received from
addresses not advertised as address candidates by the server.
This can occur when the server is behind an Endpoint Dependent
Mapping NAT, while the client is behind an Endpoint Independent
Mapping NAT.
Bruynooghe Expires 7 January 2027 [Page 5]
Internet-Draft n0 QNT July 2026
3.5.3. Successful NAT traversal
Once the client receives a PATH_RESPONSE for a NAT probe it sent, NAT
traversal is successful.
The client now opens a new path using [QUIC-MULTIPATH] over the path.
It does however stil have to validate the path before it can use it,
since only the address is validated as part of the NAT traversal.
4. Frames
Receipt of any frame while the extension is not negotiated results in
closing the connection with a PROTOCOL_VIOLATION transport error.
4.1. ADD_ADDRESS
As per [SEEMANN-QNT], but with different codepoints:
ADD_ADDRESS Frame {
Type (i) = 0x3d7f90..0x3d7f91,
Sequence Number (i),
[ IPv4 (32) ],
[ IPv6 (128) ],
Port (16),
}
The ADD_ADDRESS frame contains the following fields:
Sequence Number: A variable-length integer encoding the sequence
number of this address advertisement.
IPv4: The IPv4 address. Only present if the least significant bit
of the frame type is 0.
IPv6: The IPv6 address. Only present if the least significant bit
of the frame type is 1.
Port: The port number.
ADD_ADDRESS frames are ack-eliciting. When lost, they SHOULD be
retransmitted, unless the address is not active anymore.
This frame is only sent from the server to the client. Servers MUST
treat receipt of an ADD_ADDRESS frame as a connection error of type
PROTOCOL_VIOLATION.
Bruynooghe Expires 7 January 2027 [Page 6]
Internet-Draft n0 QNT July 2026
4.2. REMOVE_ADDRESS
As per [SEEMANN-QNT], but with different codepoints:
REMOVE_ADDRESS Frame {
Type (i) = 0x3d7f94,
Sequence Number (i),
}
The REMOVE_ADDRESS frame contains the following fields:
Sequence Number: A variable-length integer encoding the sequence
number of the address advertisement to be removed.
REMOVE_ADDRESS frames are ack-eliciting. When lost, they SHOULD be
retransmitted.
This frame is only sent from the server to the client. Servers MUST
treat receipt of an REMOVE_ADDRESS frame as a connection error of
type PROTOCOL_VIOLATION.
4.3. REACH_OUT
REACH_OUT Frame {
Type (i) = 0x3d7f92..0x3d7f93,
round (i),
[ IPv4 (32) ],
[ IPv6 (128) ],
Port (16),
}
The REACH_OUT frame contains the following fields:
Round: The sequence number of the NAT Traversal attempt.
IPv4: The IPv4 address. Only present if the least significant bit
of the frame type is 0.
IPv6: The IPv6 address. Only present if the least significant bit
of the frame type is 1.
Port: The port number.
REACH_OUT frames are ack-eliciting.
This frame is only sent from the client to the server. Clients MUST
treat receipt of a REACH_OUT frame as a connection error of type
PROTOCOL_VIOLATION.
Bruynooghe Expires 7 January 2027 [Page 7]
Internet-Draft n0 QNT July 2026
5. Security Considerations
TODO Security
* Both client and server send data to un-validated addresses
provided by the peer, this should be subject to ani-amplification
limits.
6. IANA Considerations
TODO codepoints need registering
7. Normative References
[QUIC-ADDR-DISCOVERY]
Seemann, M. and C. Huitema, "QUIC Address Discovery", Work
in Progress, Internet-Draft, draft-ietf-quic-address-
discovery-00, 3 March 2025,
<https://datatracker.ietf.org/doc/html/draft-ietf-quic-
address-discovery-00>.
[QUIC-MULTIPATH]
Liu, Y., Ma, Y., De Coninck, Q., Bonaventure, O., Huitema,
C., and M. Kühlewind, "Managing multiple paths for a QUIC
connection", Work in Progress, Internet-Draft, draft-ietf-
quic-multipath-21, 17 March 2026,
<https://datatracker.ietf.org/doc/html/draft-ietf-quic-
multipath-21>.
[QUIC-TRANSPORT]
Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based
Multiplexed and Secure Transport", RFC 9000,
DOI 10.17487/RFC9000, May 2021,
<https://www.rfc-editor.org/rfc/rfc9000>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/rfc/rfc2119>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.
Bruynooghe Expires 7 January 2027 [Page 8]
Internet-Draft n0 QNT July 2026
[SEEMANN-QNT]
Seemann, M. and E. Kinnear, "Using QUIC to traverse NATs",
Work in Progress, Internet-Draft, draft-seemann-quic-nat-
traversal-02, 3 March 2024,
<https://datatracker.ietf.org/doc/html/draft-seemann-quic-
nat-traversal-02>.
Acknowledgments
TODO acknowledge.
Author's Address
Floris Bruynooghe
n0 Inc.
Email: flub@n0.computer
Bruynooghe Expires 7 January 2027 [Page 9]