Skip to main content

n0 QUIC NAT Traversal
draft-bruynooghe-n0-quic-nat-traversal-00

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]