5602 lines
210 KiB
ReStructuredText
5602 lines
210 KiB
ReStructuredText
======
|
|
SSU2
|
|
======
|
|
.. meta::
|
|
:author: orignal, zlatinb, zzz
|
|
:created: 2021-09-12
|
|
:thread: http://zzz.i2p/topics/2612
|
|
:lastupdated: 2021-10-21
|
|
:status: Open
|
|
:target: 0.9.55
|
|
|
|
.. contents::
|
|
|
|
|
|
|
|
Overview
|
|
========
|
|
|
|
This proposal describes an authenticated key agreement protocol to improve the
|
|
resistance of [SSU]_ to various forms of automated identification and attacks.
|
|
|
|
The proposal is organized as follows: the security goals are presented,
|
|
followed by a discussion of the basic protocol. Next, a complete specification
|
|
of all protocol messages is given. Finally, router addresses and version
|
|
identification are discussed.
|
|
|
|
As with other I2P transports, SSU2 is defined
|
|
for point-to-point (router-to-router) transport of I2NP messages.
|
|
It is not a general-purpose data pipe.
|
|
Like [SSU]_, it also provides two additional services:
|
|
Relaying for NAT traversal, and Peer Testing for determination of inbound reachability.
|
|
|
|
|
|
Motivation
|
|
==========
|
|
|
|
SSU is the only remaining protocol layer that requires ElGamal, which is very slow.
|
|
The flow control for SSU is complex and does not work well.
|
|
Portions of SSU are vulnerable to address spoofing attacks.
|
|
The handshake does not use Noise.
|
|
|
|
|
|
|
|
Design Goals
|
|
============
|
|
|
|
- Reduce CPU usage by eliminating ElGamal. Use X25519 for the DH.
|
|
|
|
- Maintain the Peer Test and Relay functions, and increase security for them.
|
|
|
|
- Make implementation easier by allowing for standard flow control
|
|
algorithms.
|
|
|
|
- Increase speed and reduce latency.
|
|
Median setup time is currently about 135 ms for NTCP2 and 187 ms for SSU,
|
|
even though NTCP2 has an additional round trip; replacing ElGamal in
|
|
SSU2 should reduce it, but other changes may also help.
|
|
|
|
- (maybe) Prevent traffic amplification attacks from spoofed source addresses
|
|
via "address validation"? Is this necessary, or are there other
|
|
ways that would not require an additional round trip?
|
|
Does this conflict with the requirement to prevent traffic identification?
|
|
See below.
|
|
|
|
- Make packet identification easier, to reduce reliance on fallbacks and
|
|
heuristics that make the code overly complex.
|
|
|
|
- (maybe) Support SSU 1 and 2 on a single port, auto-detect, and published as a single
|
|
"transport" (i.e. [RouterAddress]_) in the [NetDB]_.
|
|
|
|
- Publish support for version 1 only, 2 only, or 1+2 in the NetDB in a separate
|
|
field, and default to version 1 only (don't bind version support to a
|
|
particular router version)
|
|
|
|
- Ensure that all implementations (Java/i2pd/Go) can add version 2
|
|
support (or not) on their own schedules
|
|
|
|
- Add random padding to all SSU messages including handshake and data messages.
|
|
Provide options mechanism for both sides to request min and max padding
|
|
and/or padding distribution. Specifics of the padding distribution are
|
|
implementation-dependent and may or may not be specified in the protocol
|
|
itself.
|
|
|
|
- Obfuscate the contents of messages that aren't fully encrypted (Session Created and Confirmed),
|
|
sufficiently so that DPI boxes and AV signatures can't easily classify them.
|
|
Also ensure that the messages going to a single peer or set of peers do not
|
|
have a similar pattern of bits.
|
|
|
|
- Fix loss of bits in DH due to Java format [Ticket1112]_, and speed up the DH
|
|
by switching to X25519.
|
|
|
|
- Switch to a real key derivation function (KDF) rather than using the DH
|
|
result as-is
|
|
|
|
- Add "probing resistance" (as Tor calls it); this includes replay resistance.
|
|
|
|
- Maintain 2-way authenticated key exchange (2W-AKE). 1W-AKE is not sufficient
|
|
for our application.
|
|
|
|
- Continue to use the variable-type, variable-length signatures (from the
|
|
published [RouterIdentity]_ signing key) as a part of authentication. Rely
|
|
on a static public key published in the RouterInfo as another part of
|
|
authentication.
|
|
|
|
- Add options/version in handshake for future extensibility.
|
|
|
|
- Don't add significantly to CPU required for connection setup; if possible,
|
|
reduce it significantly.
|
|
|
|
- Add message authentication (MAC) using ChaCha/Poly1305.
|
|
|
|
- Use a 3-message, one-round-trip handshake, as in [NTCP2]_.
|
|
Remove the delay waiting for data messages that makes
|
|
[SSU]_ effectively a two-round-trip handshake.
|
|
|
|
- Minimize protocol overhead before padding. While padding will be added,
|
|
overhead before padding is still overhead.
|
|
Low-bandwidth nodes must be able to use SSU2.
|
|
|
|
- All padding must be covered by the MAC, unlike the end-of-packet padding in SSU.
|
|
|
|
- Maintain timestamps for replay and skew detection.
|
|
|
|
- Avoid any year 2038 issues in timestamps, must work until at least 2106.
|
|
|
|
- Maintain a max I2NP message size of approximately 32K, as in SSU.
|
|
Increase to 64 KB? TBD
|
|
|
|
- Remove IP and port fields from the handshake, so that routers that don't know
|
|
their external IP and port will be able to connect.
|
|
|
|
- Include representatives of Java, C++, and Go router developers in the design.
|
|
|
|
|
|
|
|
Non-Goals
|
|
---------
|
|
|
|
- Bullet-proof DPI resistance... that would be pluggable transports,
|
|
[Prop109]_.
|
|
|
|
- A TLS-based (or HTTPS-lookalike) transport... that would be [Prop104]_.
|
|
|
|
- It's OK to change the symmetric stream cryptography.
|
|
|
|
- Timing-based DPI resistance (inter-message timing/delays can be
|
|
implementation-dependent; intra-message delays can be introduced at any
|
|
point, including before sending the random padding, for example). Artificial
|
|
delays (what obfs4 calls IAT or inter-arrival time) are independent of the
|
|
protocol itself.
|
|
|
|
- Deniability of participating in a session (there's signatures in there).
|
|
|
|
Non-goals that may be partially reconsidered or discussed:
|
|
|
|
- The degree of protection against Deep Packet Inspection (DPI)
|
|
|
|
- Post-Quantum (PQ) security
|
|
|
|
- Deniability
|
|
|
|
|
|
|
|
Security Goals
|
|
==============
|
|
|
|
We consider three parties:
|
|
|
|
- Alice, who wishes to establish a new session.
|
|
- Bob, with whom Alice wishes to establish a session.
|
|
- Mallory, the "man in the middle" between Alice and Bob.
|
|
|
|
At most two participants can engage in active attacks.
|
|
|
|
Alice and Bob are both in possession of a static key pair, which is contained
|
|
in their [RouterIdentity]_.
|
|
|
|
The proposed protocol attempts to allow Alice and Bob to agree on a shared
|
|
secret key (K) under the following requirements:
|
|
|
|
1) Private key security: neither Bob nor Mallory learns anything about Alice's
|
|
static private key. Symmetrically, Alice does not learn anything about Bob's
|
|
static private key.
|
|
|
|
2) The session key K is only known by Alice and Bob.
|
|
|
|
3) Perfect forward secrecy: the agreed upon session key remains secret in the
|
|
future, even when the static private keys of Alice and/or Bob are revealed
|
|
after the key has been agreed upon.
|
|
|
|
4) Two-way authentication: Alice is certain that she has established a session
|
|
with Bob, and vice versa.
|
|
|
|
5) Protection against online DPI: Ensure that it is not trivial to detect that
|
|
Alice and Bob are engaged in the protocol using only straightforward deep
|
|
packet inspection (DPI) techniques. See below.
|
|
|
|
6) Limited deniability: neither Alice nor Bob can deny participation in the
|
|
protocol, but if either leaks the shared key the other party can deny the
|
|
authenticity of the contents of the transmitted data.
|
|
|
|
The present proposal attempts to provide all five requirements based on the
|
|
Station-To-Station (STS) protocol [STS]_. Note that this protocol is also the
|
|
basis for the [SSU]_ protocol.
|
|
|
|
|
|
Additional DPI Discussion
|
|
-------------------------
|
|
|
|
We assume two DPI components:
|
|
|
|
Online DPI
|
|
`````````````
|
|
|
|
Online DPI inspecting all flows in real-time. Connections may be blocked or
|
|
otherwise tampered with. Connection data or metadata may be identified and
|
|
stored for offline analysis. The online DPI does not have access to the I2P
|
|
network database. The online DPI has only limited real-time computational
|
|
capability, including length calculation, field inspection, and simple
|
|
calculations such as XOR. The online DPI does have the capability of fast
|
|
real-time cryptographic functions such as AES, AEAD, and hashing, but these
|
|
would be too expensive to apply to most or all flows. Any application of these
|
|
cryptographic operations would apply only to flows on IP/Port combinations
|
|
previously identified by offline analysis. The online DPI does not have the
|
|
capability of high-overhead cryptographic functions such as DH or elligator2.
|
|
The online DPI is not designed specifically to detect I2P, although it may have
|
|
limited classification rules for that purpose.
|
|
|
|
It is a goal to prevent protocol identification by an online DPI.
|
|
|
|
The notion of online or "straightforward" DPI is here taken to include the
|
|
following adversary capabilities:
|
|
|
|
1) The ability to inspect all data sent or received by the target.
|
|
|
|
2) The ability to perform operations on the observed data, such as
|
|
applying block ciphers or hash functions.
|
|
|
|
3) The ability to store and compare with previously sent messages.
|
|
|
|
4) The ability to modify, delay or fragment packets.
|
|
|
|
However, the online DPI is assumed to have the following restrictions:
|
|
|
|
5) The inability to map IP addresses to router hashes. While this is trivial
|
|
with real-time access to the network database,
|
|
it would require a DPI system specifically designed to target I2P.
|
|
|
|
6) The inability to use timing information to detect the protocol.
|
|
|
|
7) Generally speaking, the online DPI toolbox does not contain any built-in
|
|
tools that are specifically designed for I2P detection. This includes
|
|
creating "honeypots", which would for example include nonrandom padding in
|
|
their messages. Note that this does not exclude machine learning systems or
|
|
highly configurable DPI tools as long as they meet the other requirements.
|
|
|
|
To counter payload analysis, it is ensured that all messages are
|
|
indistinguishable from random. This also requires their length to be random,
|
|
which is more complicated than just adding random padding. In fact, in Appendix
|
|
A, the authors argue that a naive (i.e. uniform) padding scheme does not
|
|
resolve the problem. Appendix A therefore proposes to include either random
|
|
delays or to develop an alternate padding scheme that can provide reasonable
|
|
protection for the proposed attack.
|
|
|
|
To protect against the sixth entry above, implementations should include random
|
|
delays in the protocol. Such techniques are not covered by this proposal, but
|
|
they could also resolve the padding length issues. In summary, the proposal
|
|
provides good protection against payload analysis (when the considerations in
|
|
Appendix A are taken into account), but only limited protection against flow
|
|
analysis.
|
|
|
|
|
|
Offline DPI
|
|
``````````````
|
|
|
|
Offline DPI inspecting data stored by the online DPI for later analysis.
|
|
The offline DPI may be designed specifically to detect I2P.
|
|
The offline DPI does have real-time access to the I2P network database.
|
|
The offline DPI does have access to this and other I2P specifications.
|
|
The offline DPI has unlimited computational capability, including
|
|
all cryptographic functions defined in this specification.
|
|
|
|
The offline DPI does not have the ability to block existing connections. The
|
|
offline DPI does have the capability to do near-realtime (within minutes of
|
|
setup) sending to host/port of parties by packet injection. The offline DPI
|
|
does have the capability to do near-realtime (within minutes of setup) replay
|
|
of previous messages (modified or not) for "probing" or other reasons.
|
|
|
|
It is not a goal to prevent protocol identification by an offline DPI.
|
|
All decoding of obfuscated data in the first two messages, which
|
|
is implemented by I2P routers, may also be implemented by the offline DPI.
|
|
|
|
It is a goal to reject attempted connections using replay of previous messages.
|
|
|
|
|
|
|
|
|
|
Address Validation
|
|
---------------------------
|
|
|
|
Following is copied from QUIC [RFC-9000]_.
|
|
For each section, review and edit.
|
|
|
|
Address validation ensures that an endpoint cannot be used for a
|
|
traffic amplification attack. In such an attack, a packet is sent to
|
|
a server with spoofed source address information that identifies a
|
|
victim. If a server generates more or larger packets in response to
|
|
that packet, the attacker can use the server to send more data toward
|
|
the victim than it would be able to send on its own.
|
|
|
|
The primary defense against amplification attacks is verifying that a
|
|
peer is able to receive packets at the transport address that it
|
|
claims. Therefore, after receiving packets from an address that is
|
|
not yet validated, an endpoint MUST limit the amount of data it sends
|
|
to the unvalidated address to three times the amount of data received
|
|
from that address. This limit on the size of responses is known as
|
|
the anti-amplification limit.
|
|
|
|
Address validation is performed both during connection establishment
|
|
(see Section 8.1) and during connection migration (see Section 8.2).
|
|
|
|
Address Validation during Connection Establishment
|
|
```````````````````````````````````````````````````````
|
|
|
|
Connection establishment implicitly provides address validation for
|
|
both endpoints. In particular, receipt of a packet protected with
|
|
Handshake keys confirms that the peer successfully processed an
|
|
Initial packet. Once an endpoint has successfully processed a
|
|
Handshake packet from the peer, it can consider the peer address to
|
|
have been validated.
|
|
|
|
Additionally, an endpoint MAY consider the peer address validated if
|
|
the peer uses a connection ID chosen by the endpoint and the
|
|
connection ID contains at least 64 bits of entropy.
|
|
|
|
For the client, the value of the Destination Connection ID field in
|
|
its first Initial packet allows it to validate the server address as
|
|
a part of successfully processing any packet. Initial packets from
|
|
the server are protected with keys that are derived from this value
|
|
(see Section 5.2 of [QUIC-TLS]). Alternatively, the value is echoed
|
|
by the server in Version Negotiation packets (Section 6) or included
|
|
in the Integrity Tag in Retry packets (Section 5.8 of [QUIC-TLS]).
|
|
|
|
Prior to validating the client address, servers MUST NOT send more
|
|
than three times as many bytes as the number of bytes they have
|
|
received. This limits the magnitude of any amplification attack that
|
|
can be mounted using spoofed source addresses. For the purposes of
|
|
avoiding amplification prior to address validation, servers MUST
|
|
count all of the payload bytes received in datagrams that are
|
|
uniquely attributed to a single connection. This includes datagrams
|
|
that contain packets that are successfully processed and datagrams
|
|
that contain packets that are all discarded.
|
|
|
|
Clients MUST ensure that UDP datagrams containing Initial packets
|
|
have UDP payloads of at least 1200 bytes, adding PADDING frames as
|
|
necessary. A client that sends padded datagrams allows the server to
|
|
send more data prior to completing address validation.
|
|
|
|
Loss of an Initial or Handshake packet from the server can cause a
|
|
deadlock if the client does not send additional Initial or Handshake
|
|
packets. A deadlock could occur when the server reaches its anti-
|
|
amplification limit and the client has received acknowledgments for
|
|
all the data it has sent. In this case, when the client has no
|
|
reason to send additional packets, the server will be unable to send
|
|
more data because it has not validated the client's address. To
|
|
prevent this deadlock, clients MUST send a packet on a Probe Timeout
|
|
(PTO); see Section 6.2 of [QUIC-RECOVERY]. Specifically, the client
|
|
MUST send an Initial packet in a UDP datagram that contains at least
|
|
1200 bytes if it does not have Handshake keys, and otherwise send a
|
|
Handshake packet.
|
|
|
|
A server might wish to validate the client address before starting
|
|
the cryptographic handshake. QUIC uses a token in the Initial packet
|
|
to provide address validation prior to completing the handshake.
|
|
This token is delivered to the client during connection establishment
|
|
with a Retry packet (see Section 8.1.2) or in a previous connection
|
|
using the NEW_TOKEN frame (see Section 8.1.3).
|
|
|
|
In addition to sending limits imposed prior to address validation,
|
|
servers are also constrained in what they can send by the limits set
|
|
by the congestion controller. Clients are only constrained by the
|
|
congestion controller.
|
|
|
|
Token Construction
|
|
```````````````````````````````````````````````````````
|
|
|
|
A token sent in a NEW_TOKEN frame or a Retry packet MUST be
|
|
constructed in a way that allows the server to identify how it was
|
|
provided to a client. These tokens are carried in the same field but
|
|
require different handling from servers.
|
|
|
|
Address Validation Using Retry Packets
|
|
```````````````````````````````````````````````````````
|
|
|
|
Upon receiving the client's Initial packet, the server can request
|
|
address validation by sending a Retry packet (Section 17.2.5)
|
|
containing a token. This token MUST be repeated by the client in all
|
|
Initial packets it sends for that connection after it receives the
|
|
Retry packet.
|
|
|
|
In response to processing an Initial packet containing a token that
|
|
was provided in a Retry packet, a server cannot send another Retry
|
|
packet; it can only refuse the connection or permit it to proceed.
|
|
|
|
As long as it is not possible for an attacker to generate a valid
|
|
token for its own address (see Section 8.1.4) and the client is able
|
|
to return that token, it proves to the server that it received the
|
|
token.
|
|
|
|
A server can also use a Retry packet to defer the state and
|
|
processing costs of connection establishment. Requiring the server
|
|
to provide a different connection ID, along with the
|
|
original_destination_connection_id transport parameter defined in
|
|
Section 18.2, forces the server to demonstrate that it, or an entity
|
|
it cooperates with, received the original Initial packet from the
|
|
client. Providing a different connection ID also grants a server
|
|
some control over how subsequent packets are routed. This can be
|
|
used to direct connections to a different server instance.
|
|
|
|
If a server receives a client Initial that contains an invalid Retry
|
|
token but is otherwise valid, it knows the client will not accept
|
|
another Retry token. The server can discard such a packet and allow
|
|
the client to time out to detect handshake failure, but that could
|
|
impose a significant latency penalty on the client. Instead, the
|
|
server SHOULD immediately close (Section 10.2) the connection with an
|
|
INVALID_TOKEN error. Note that a server has not established any
|
|
state for the connection at this point and so does not enter the
|
|
closing period.
|
|
|
|
A flow showing the use of a Retry packet is shown in Figure 9.
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight %}
|
|
Client Server
|
|
|
|
Initial[0]: CRYPTO[CH] ->
|
|
|
|
<- Retry+Token
|
|
|
|
Initial+Token[1]: CRYPTO[CH] ->
|
|
|
|
Initial[0]: CRYPTO[SH] ACK[1]
|
|
Handshake[0]: CRYPTO[EE, CERT, CV, FIN]
|
|
<- 1-RTT[0]: STREAM[1, "..."]
|
|
|
|
Figure 9: Example Handshake with Retry
|
|
{% endhighlight %}
|
|
|
|
|
|
|
|
Address Validation for Future Connections
|
|
```````````````````````````````````````````````````````
|
|
|
|
A server MAY provide clients with an address validation token during
|
|
one connection that can be used on a subsequent connection. Address
|
|
validation is especially important with 0-RTT because a server
|
|
potentially sends a significant amount of data to a client in
|
|
response to 0-RTT data.
|
|
|
|
The server uses the NEW_TOKEN frame (Section 19.7) to provide the
|
|
client with an address validation token that can be used to validate
|
|
future connections. In a future connection, the client includes this
|
|
token in Initial packets to provide address validation. The client
|
|
MUST include the token in all Initial packets it sends, unless a
|
|
Retry replaces the token with a newer one. The client MUST NOT use
|
|
the token provided in a Retry for future connections. Servers MAY
|
|
discard any Initial packet that does not carry the expected token.
|
|
|
|
Unlike the token that is created for a Retry packet, which is used
|
|
immediately, the token sent in the NEW_TOKEN frame can be used after
|
|
some period of time has passed. Thus, a token SHOULD have an
|
|
expiration time, which could be either an explicit expiration time or
|
|
an issued timestamp that can be used to dynamically calculate the
|
|
expiration time. A server can store the expiration time or include
|
|
it in an encrypted form in the token.
|
|
|
|
A token issued with NEW_TOKEN MUST NOT include information that would
|
|
allow values to be linked by an observer to the connection on which
|
|
it was issued. For example, it cannot include the previous
|
|
connection ID or addressing information, unless the values are
|
|
encrypted. A server MUST ensure that every NEW_TOKEN frame it sends
|
|
is unique across all clients, with the exception of those sent to
|
|
repair losses of previously sent NEW_TOKEN frames. Information that
|
|
allows the server to distinguish between tokens from Retry and
|
|
NEW_TOKEN MAY be accessible to entities other than the server.
|
|
|
|
It is unlikely that the client port number is the same on two
|
|
different connections; validating the port is therefore unlikely to
|
|
be successful.
|
|
|
|
A token received in a NEW_TOKEN frame is applicable to any server
|
|
that the connection is considered authoritative for (e.g., server
|
|
names included in the certificate). When connecting to a server for
|
|
which the client retains an applicable and unused token, it SHOULD
|
|
include that token in the Token field of its Initial packet.
|
|
Including a token might allow the server to validate the client
|
|
address without an additional round trip. A client MUST NOT include
|
|
a token that is not applicable to the server that it is connecting
|
|
to, unless the client has the knowledge that the server that issued
|
|
the token and the server the client is connecting to are jointly
|
|
managing the tokens. A client MAY use a token from any previous
|
|
connection to that server.
|
|
|
|
A token allows a server to correlate activity between the connection
|
|
where the token was issued and any connection where it is used.
|
|
Clients that want to break continuity of identity with a server can
|
|
discard tokens provided using the NEW_TOKEN frame. In comparison, a
|
|
token obtained in a Retry packet MUST be used immediately during the
|
|
connection attempt and cannot be used in subsequent connection
|
|
attempts.
|
|
|
|
A client SHOULD NOT reuse a token from a NEW_TOKEN frame for
|
|
different connection attempts. Reusing a token allows connections to
|
|
be linked by entities on the network path; see Section 9.5.
|
|
|
|
Clients might receive multiple tokens on a single connection. Aside
|
|
from preventing linkability, any token can be used in any connection
|
|
attempt. Servers can send additional tokens to either enable address
|
|
validation for multiple connection attempts or replace older tokens
|
|
that might become invalid. For a client, this ambiguity means that
|
|
sending the most recent unused token is most likely to be effective.
|
|
Though saving and using older tokens have no negative consequences,
|
|
clients can regard older tokens as being less likely to be useful to
|
|
the server for address validation.
|
|
|
|
When a server receives an Initial packet with an address validation
|
|
token, it MUST attempt to validate the token, unless it has already
|
|
completed address validation. If the token is invalid, then the
|
|
server SHOULD proceed as if the client did not have a validated
|
|
address, including potentially sending a Retry packet. Tokens
|
|
provided with NEW_TOKEN frames and Retry packets can be distinguished
|
|
by servers (see Section 8.1.1), and the latter can be validated more
|
|
strictly. If the validation succeeds, the server SHOULD then allow
|
|
the handshake to proceed.
|
|
|
|
Note: The rationale for treating the client as unvalidated
|
|
rather than discarding the packet is that the client might have
|
|
received the token in a previous connection using the NEW_TOKEN
|
|
frame, and if the server has lost state, it might be unable to
|
|
validate the token at all, leading to connection failure if the
|
|
packet is discarded.
|
|
|
|
In a stateless design, a server can use encrypted and authenticated
|
|
tokens to pass information to clients that the server can later
|
|
recover and use to validate a client address. Tokens are not
|
|
integrated into the cryptographic handshake, and so they are not
|
|
authenticated. For instance, a client might be able to reuse a
|
|
token. To avoid attacks that exploit this property, a server can
|
|
limit its use of tokens to only the information needed to validate
|
|
client addresses.
|
|
|
|
Clients MAY use tokens obtained on one connection for any connection
|
|
attempt using the same version. When selecting a token to use,
|
|
clients do not need to consider other properties of the connection
|
|
that is being attempted, including the choice of possible application
|
|
protocols, session tickets, or other connection properties.
|
|
|
|
Address Validation Token Integrity
|
|
```````````````````````````````````````````````````````
|
|
|
|
An address validation token MUST be difficult to guess. Including a
|
|
random value with at least 128 bits of entropy in the token would be
|
|
sufficient, but this depends on the server remembering the value it
|
|
sends to clients.
|
|
|
|
A token-based scheme allows the server to offload any state
|
|
associated with validation to the client. For this design to work,
|
|
the token MUST be covered by integrity protection against
|
|
modification or falsification by clients. Without integrity
|
|
protection, malicious clients could generate or guess values for
|
|
tokens that would be accepted by the server. Only the server
|
|
requires access to the integrity protection key for tokens.
|
|
|
|
There is no need for a single well-defined format for the token
|
|
because the server that generates the token also consumes it. Tokens
|
|
sent in Retry packets SHOULD include information that allows the
|
|
server to verify that the source IP address and port in client
|
|
packets remain constant.
|
|
|
|
Tokens sent in NEW_TOKEN frames MUST include information that allows
|
|
the server to verify that the client IP address has not changed from
|
|
when the token was issued. Servers can use tokens from NEW_TOKEN
|
|
frames in deciding not to send a Retry packet, even if the client
|
|
address has changed. If the client IP address has changed, the
|
|
server MUST adhere to the anti-amplification limit; see Section 8.
|
|
Note that in the presence of NAT, this requirement might be
|
|
insufficient to protect other hosts that share the NAT from
|
|
amplification attacks.
|
|
|
|
Attackers could replay tokens to use servers as amplifiers in DDoS
|
|
attacks. To protect against such attacks, servers MUST ensure that
|
|
replay of tokens is prevented or limited. Servers SHOULD ensure that
|
|
tokens sent in Retry packets are only accepted for a short time, as
|
|
they are returned immediately by clients. Tokens that are provided
|
|
in NEW_TOKEN frames (Section 19.7) need to be valid for longer but
|
|
SHOULD NOT be accepted multiple times. Servers are encouraged to
|
|
allow tokens to be used only once, if possible; tokens MAY include
|
|
additional information about clients to further narrow applicability
|
|
or reuse.
|
|
|
|
Path Validation
|
|
```````````````````````````````````````````````````````
|
|
|
|
Path validation is used by both peers during connection migration
|
|
(see Section 9) to verify reachability after a change of address. In
|
|
path validation, endpoints test reachability between a specific local
|
|
address and a specific peer address, where an address is the 2-tuple
|
|
of IP address and port.
|
|
|
|
Path validation tests that packets sent on a path to a peer are
|
|
received by that peer. Path validation is used to ensure that
|
|
packets received from a migrating peer do not carry a spoofed source
|
|
address.
|
|
|
|
Path validation does not validate that a peer can send in the return
|
|
direction. Acknowledgments cannot be used for return path validation
|
|
because they contain insufficient entropy and might be spoofed.
|
|
Endpoints independently determine reachability on each direction of a
|
|
path, and therefore return reachability can only be established by
|
|
the peer.
|
|
|
|
Path validation can be used at any time by either endpoint. For
|
|
instance, an endpoint might check that a peer is still in possession
|
|
of its address after a period of quiescence.
|
|
|
|
Path validation is not designed as a NAT traversal mechanism. Though
|
|
the mechanism described here might be effective for the creation of
|
|
NAT bindings that support NAT traversal, the expectation is that one
|
|
endpoint is able to receive packets without first having sent a
|
|
packet on that path. Effective NAT traversal needs additional
|
|
synchronization mechanisms that are not provided here.
|
|
|
|
An endpoint MAY include other frames with the PATH_CHALLENGE and
|
|
PATH_RESPONSE frames used for path validation. In particular, an
|
|
endpoint can include PADDING frames with a PATH_CHALLENGE frame for
|
|
Path Maximum Transmission Unit Discovery (PMTUD); see Section 14.2.1.
|
|
An endpoint can also include its own PATH_CHALLENGE frame when
|
|
sending a PATH_RESPONSE frame.
|
|
|
|
An endpoint uses a new connection ID for probes sent from a new local
|
|
address; see Section 9.5. When probing a new path, an endpoint can
|
|
ensure that its peer has an unused connection ID available for
|
|
responses. Sending NEW_CONNECTION_ID and PATH_CHALLENGE frames in
|
|
the same packet, if the peer's active_connection_id_limit permits,
|
|
ensures that an unused connection ID will be available to the peer
|
|
when sending a response.
|
|
|
|
An endpoint can choose to simultaneously probe multiple paths. The
|
|
number of simultaneous paths used for probes is limited by the number
|
|
of extra connection IDs its peer has previously supplied, since each
|
|
new local address used for a probe requires a previously unused
|
|
connection ID.
|
|
|
|
Initiating Path Validation
|
|
```````````````````````````````````````````````````````
|
|
|
|
To initiate path validation, an endpoint sends a PATH_CHALLENGE frame
|
|
containing an unpredictable payload on the path to be validated.
|
|
|
|
An endpoint MAY send multiple PATH_CHALLENGE frames to guard against
|
|
packet loss. However, an endpoint SHOULD NOT send multiple
|
|
PATH_CHALLENGE frames in a single packet.
|
|
|
|
An endpoint SHOULD NOT probe a new path with packets containing a
|
|
PATH_CHALLENGE frame more frequently than it would send an Initial
|
|
packet. This ensures that connection migration is no more load on a
|
|
new path than establishing a new connection.
|
|
|
|
The endpoint MUST use unpredictable data in every PATH_CHALLENGE
|
|
frame so that it can associate the peer's response with the
|
|
corresponding PATH_CHALLENGE.
|
|
|
|
An endpoint MUST expand datagrams that contain a PATH_CHALLENGE frame
|
|
to at least the smallest allowed maximum datagram size of 1200 bytes,
|
|
unless the anti-amplification limit for the path does not permit
|
|
sending a datagram of this size. Sending UDP datagrams of this size
|
|
ensures that the network path from the endpoint to the peer can be
|
|
used for QUIC; see Section 14.
|
|
|
|
When an endpoint is unable to expand the datagram size to 1200 bytes
|
|
due to the anti-amplification limit, the path MTU will not be
|
|
validated. To ensure that the path MTU is large enough, the endpoint
|
|
MUST perform a second path validation by sending a PATH_CHALLENGE
|
|
frame in a datagram of at least 1200 bytes. This additional
|
|
validation can be performed after a PATH_RESPONSE is successfully
|
|
received or when enough bytes have been received on the path that
|
|
sending the larger datagram will not result in exceeding the anti-
|
|
amplification limit.
|
|
|
|
Unlike other cases where datagrams are expanded, endpoints MUST NOT
|
|
discard datagrams that appear to be too small when they contain
|
|
PATH_CHALLENGE or PATH_RESPONSE.
|
|
|
|
Path Validation Responses
|
|
```````````````````````````````````````````````````````
|
|
|
|
On receiving a PATH_CHALLENGE frame, an endpoint MUST respond by
|
|
echoing the data contained in the PATH_CHALLENGE frame in a
|
|
PATH_RESPONSE frame. An endpoint MUST NOT delay transmission of a
|
|
packet containing a PATH_RESPONSE frame unless constrained by
|
|
congestion control.
|
|
|
|
A PATH_RESPONSE frame MUST be sent on the network path where the
|
|
PATH_CHALLENGE frame was received. This ensures that path validation
|
|
by a peer only succeeds if the path is functional in both directions.
|
|
This requirement MUST NOT be enforced by the endpoint that initiates
|
|
path validation, as that would enable an attack on migration; see
|
|
Section 9.3.3.
|
|
|
|
An endpoint MUST expand datagrams that contain a PATH_RESPONSE frame
|
|
to at least the smallest allowed maximum datagram size of 1200 bytes.
|
|
This verifies that the path is able to carry datagrams of this size
|
|
in both directions. However, an endpoint MUST NOT expand the
|
|
datagram containing the PATH_RESPONSE if the resulting data exceeds
|
|
the anti-amplification limit. This is expected to only occur if the
|
|
received PATH_CHALLENGE was not sent in an expanded datagram.
|
|
|
|
An endpoint MUST NOT send more than one PATH_RESPONSE frame in
|
|
response to one PATH_CHALLENGE frame; see Section 13.3. The peer is
|
|
expected to send more PATH_CHALLENGE frames as necessary to evoke
|
|
additional PATH_RESPONSE frames.
|
|
|
|
Successful Path Validation
|
|
```````````````````````````````````````````````````````
|
|
|
|
Path validation succeeds when a PATH_RESPONSE frame is received that
|
|
contains the data that was sent in a previous PATH_CHALLENGE frame.
|
|
A PATH_RESPONSE frame received on any network path validates the path
|
|
on which the PATH_CHALLENGE was sent.
|
|
|
|
If an endpoint sends a PATH_CHALLENGE frame in a datagram that is not
|
|
expanded to at least 1200 bytes and if the response to it validates
|
|
the peer address, the path is validated but not the path MTU. As a
|
|
result, the endpoint can now send more than three times the amount of
|
|
data that has been received. However, the endpoint MUST initiate
|
|
another path validation with an expanded datagram to verify that the
|
|
path supports the required MTU.
|
|
|
|
Receipt of an acknowledgment for a packet containing a PATH_CHALLENGE
|
|
frame is not adequate validation, since the acknowledgment can be
|
|
spoofed by a malicious peer.
|
|
|
|
Failed Path Validation
|
|
```````````````````````````````````````````````````````
|
|
|
|
Path validation only fails when the endpoint attempting to validate
|
|
the path abandons its attempt to validate the path.
|
|
|
|
Endpoints SHOULD abandon path validation based on a timer. When
|
|
setting this timer, implementations are cautioned that the new path
|
|
could have a longer round-trip time than the original. A value of
|
|
three times the larger of the current PTO or the PTO for the new path
|
|
(using kInitialRtt, as defined in [QUIC-RECOVERY]) is RECOMMENDED.
|
|
|
|
This timeout allows for multiple PTOs to expire prior to failing path
|
|
validation, so that loss of a single PATH_CHALLENGE or PATH_RESPONSE
|
|
frame does not cause path validation failure.
|
|
|
|
Note that the endpoint might receive packets containing other frames
|
|
on the new path, but a PATH_RESPONSE frame with appropriate data is
|
|
required for path validation to succeed.
|
|
|
|
When an endpoint abandons path validation, it determines that the
|
|
path is unusable. This does not necessarily imply a failure of the
|
|
connection -- endpoints can continue sending packets over other paths
|
|
as appropriate. If no paths are available, an endpoint can wait for
|
|
a new path to become available or close the connection. An endpoint
|
|
that has no valid network path to its peer MAY signal this using the
|
|
NO_VIABLE_PATH connection error, noting that this is only possible if
|
|
the network path exists but does not support the required MTU
|
|
(Section 14).
|
|
|
|
A path validation might be abandoned for other reasons besides
|
|
failure. Primarily, this happens if a connection migration to a new
|
|
path is initiated while a path validation on the old path is in
|
|
progress.
|
|
|
|
Connection Migration
|
|
----------------------------
|
|
|
|
Following is copied from QUIC [RFC-9000]_.
|
|
For each section, review and edit.
|
|
|
|
|
|
The use of a connection ID allows connections to survive changes to
|
|
endpoint addresses (IP address and port), such as those caused by an
|
|
endpoint migrating to a new network. This section describes the
|
|
process by which an endpoint migrates to a new address.
|
|
|
|
The design of QUIC relies on endpoints retaining a stable address for
|
|
the duration of the handshake. An endpoint MUST NOT initiate
|
|
connection migration before the handshake is confirmed, as defined in
|
|
Section 4.1.2 of [QUIC-TLS].
|
|
|
|
If the peer sent the disable_active_migration transport parameter, an
|
|
endpoint also MUST NOT send packets (including probing packets; see
|
|
Section 9.1) from a different local address to the address the peer
|
|
used during the handshake, unless the endpoint has acted on a
|
|
preferred_address transport parameter from the peer. If the peer
|
|
violates this requirement, the endpoint MUST either drop the incoming
|
|
packets on that path without generating a Stateless Reset or proceed
|
|
with path validation and allow the peer to migrate. Generating a
|
|
Stateless Reset or closing the connection would allow third parties
|
|
in the network to cause connections to close by spoofing or otherwise
|
|
manipulating observed traffic.
|
|
|
|
Not all changes of peer address are intentional, or active,
|
|
migrations. The peer could experience NAT rebinding: a change of
|
|
address due to a middlebox, usually a NAT, allocating a new outgoing
|
|
port or even a new outgoing IP address for a flow. An endpoint MUST
|
|
perform path validation (Section 8.2) if it detects any change to a
|
|
peer's address, unless it has previously validated that address.
|
|
|
|
When an endpoint has no validated path on which to send packets, it
|
|
MAY discard connection state. An endpoint capable of connection
|
|
migration MAY wait for a new path to become available before
|
|
discarding connection state.
|
|
|
|
This document limits migration of connections to new client
|
|
addresses, except as described in Section 9.6. Clients are
|
|
responsible for initiating all migrations. Servers do not send non-
|
|
probing packets (see Section 9.1) toward a client address until they
|
|
see a non-probing packet from that address. If a client receives
|
|
packets from an unknown server address, the client MUST discard these
|
|
packets.
|
|
|
|
Probing a New Path
|
|
`````````````````````````
|
|
|
|
An endpoint MAY probe for peer reachability from a new local address
|
|
using path validation (Section 8.2) prior to migrating the connection
|
|
to the new local address. Failure of path validation simply means
|
|
that the new path is not usable for this connection. Failure to
|
|
validate a path does not cause the connection to end unless there are
|
|
no valid alternative paths available.
|
|
|
|
PATH_CHALLENGE, PATH_RESPONSE, NEW_CONNECTION_ID, and PADDING frames
|
|
are "probing frames", and all other frames are "non-probing frames".
|
|
A packet containing only probing frames is a "probing packet", and a
|
|
packet containing any other frame is a "non-probing packet".
|
|
|
|
Initiating Connection Migration
|
|
`````````````````````````````````````
|
|
|
|
An endpoint can migrate a connection to a new local address by
|
|
sending packets containing non-probing frames from that address.
|
|
|
|
Each endpoint validates its peer's address during connection
|
|
establishment. Therefore, a migrating endpoint can send to its peer
|
|
knowing that the peer is willing to receive at the peer's current
|
|
address. Thus, an endpoint can migrate to a new local address
|
|
without first validating the peer's address.
|
|
|
|
To establish reachability on the new path, an endpoint initiates path
|
|
validation (Section 8.2) on the new path. An endpoint MAY defer path
|
|
validation until after a peer sends the next non-probing frame to its
|
|
new address.
|
|
|
|
When migrating, the new path might not support the endpoint's current
|
|
sending rate. Therefore, the endpoint resets its congestion
|
|
controller and RTT estimate, as described in Section 9.4.
|
|
|
|
The new path might not have the same ECN capability. Therefore, the
|
|
endpoint validates ECN capability as described in Section 13.4.
|
|
|
|
Responding to Connection Migration
|
|
```````````````````````````````````````````
|
|
|
|
Receiving a packet from a new peer address containing a non-probing
|
|
frame indicates that the peer has migrated to that address.
|
|
|
|
If the recipient permits the migration, it MUST send subsequent
|
|
packets to the new peer address and MUST initiate path validation
|
|
(Section 8.2) to verify the peer's ownership of the address if
|
|
validation is not already underway. If the recipient has no unused
|
|
connection IDs from the peer, it will not be able to send anything on
|
|
the new path until the peer provides one; see Section 9.5.
|
|
|
|
An endpoint only changes the address to which it sends packets in
|
|
response to the highest-numbered non-probing packet. This ensures
|
|
that an endpoint does not send packets to an old peer address in the
|
|
case that it receives reordered packets.
|
|
|
|
An endpoint MAY send data to an unvalidated peer address, but it MUST
|
|
protect against potential attacks as described in Sections 9.3.1 and
|
|
9.3.2. An endpoint MAY skip validation of a peer address if that
|
|
address has been seen recently. In particular, if an endpoint
|
|
returns to a previously validated path after detecting some form of
|
|
spurious migration, skipping address validation and restoring loss
|
|
detection and congestion state can reduce the performance impact of
|
|
the attack.
|
|
|
|
After changing the address to which it sends non-probing packets, an
|
|
endpoint can abandon any path validation for other addresses.
|
|
|
|
Receiving a packet from a new peer address could be the result of a
|
|
NAT rebinding at the peer.
|
|
|
|
After verifying a new client address, the server SHOULD send new
|
|
address validation tokens (Section 8) to the client.
|
|
|
|
Peer Address Spoofing
|
|
`````````````````````````
|
|
|
|
It is possible that a peer is spoofing its source address to cause an
|
|
endpoint to send excessive amounts of data to an unwilling host. If
|
|
the endpoint sends significantly more data than the spoofing peer,
|
|
connection migration might be used to amplify the volume of data that
|
|
an attacker can generate toward a victim.
|
|
|
|
As described in Section 9.3, an endpoint is required to validate a
|
|
peer's new address to confirm the peer's possession of the new
|
|
address. Until a peer's address is deemed valid, an endpoint limits
|
|
the amount of data it sends to that address; see Section 8. In the
|
|
absence of this limit, an endpoint risks being used for a denial-of-
|
|
service attack against an unsuspecting victim.
|
|
|
|
If an endpoint skips validation of a peer address as described above,
|
|
it does not need to limit its sending rate.
|
|
|
|
On-Path Address Spoofing
|
|
`````````````````````````
|
|
|
|
An on-path attacker could cause a spurious connection migration by
|
|
copying and forwarding a packet with a spoofed address such that it
|
|
arrives before the original packet. The packet with the spoofed
|
|
address will be seen to come from a migrating connection, and the
|
|
original packet will be seen as a duplicate and dropped. After a
|
|
spurious migration, validation of the source address will fail
|
|
because the entity at the source address does not have the necessary
|
|
cryptographic keys to read or respond to the PATH_CHALLENGE frame
|
|
that is sent to it even if it wanted to.
|
|
|
|
To protect the connection from failing due to such a spurious
|
|
migration, an endpoint MUST revert to using the last validated peer
|
|
address when validation of a new peer address fails. Additionally,
|
|
receipt of packets with higher packet numbers from the legitimate
|
|
peer address will trigger another connection migration. This will
|
|
cause the validation of the address of the spurious migration to be
|
|
abandoned, thus containing migrations initiated by the attacker
|
|
injecting a single packet.
|
|
|
|
If an endpoint has no state about the last validated peer address, it
|
|
MUST close the connection silently by discarding all connection
|
|
state. This results in new packets on the connection being handled
|
|
generically. For instance, an endpoint MAY send a Stateless Reset in
|
|
response to any further incoming packets.
|
|
|
|
Off-Path Packet Forwarding
|
|
```````````````````````````````````
|
|
|
|
An off-path attacker that can observe packets might forward copies of
|
|
genuine packets to endpoints. If the copied packet arrives before
|
|
the genuine packet, this will appear as a NAT rebinding. Any genuine
|
|
packet will be discarded as a duplicate. If the attacker is able to
|
|
continue forwarding packets, it might be able to cause migration to a
|
|
path via the attacker. This places the attacker on-path, giving it
|
|
the ability to observe or drop all subsequent packets.
|
|
|
|
This style of attack relies on the attacker using a path that has
|
|
approximately the same characteristics as the direct path between
|
|
endpoints. The attack is more reliable if relatively few packets are
|
|
sent or if packet loss coincides with the attempted attack.
|
|
|
|
A non-probing packet received on the original path that increases the
|
|
maximum received packet number will cause the endpoint to move back
|
|
to that path. Eliciting packets on this path increases the
|
|
likelihood that the attack is unsuccessful. Therefore, mitigation of
|
|
this attack relies on triggering the exchange of packets.
|
|
|
|
In response to an apparent migration, endpoints MUST validate the
|
|
previously active path using a PATH_CHALLENGE frame. This induces
|
|
the sending of new packets on that path. If the path is no longer
|
|
viable, the validation attempt will time out and fail; if the path is
|
|
viable but no longer desired, the validation will succeed but only
|
|
results in probing packets being sent on the path.
|
|
|
|
An endpoint that receives a PATH_CHALLENGE on an active path SHOULD
|
|
send a non-probing packet in response. If the non-probing packet
|
|
arrives before any copy made by an attacker, this results in the
|
|
connection being migrated back to the original path. Any subsequent
|
|
migration to another path restarts this entire process.
|
|
|
|
This defense is imperfect, but this is not considered a serious
|
|
problem. If the path via the attack is reliably faster than the
|
|
original path despite multiple attempts to use that original path, it
|
|
is not possible to distinguish between an attack and an improvement
|
|
in routing.
|
|
|
|
An endpoint could also use heuristics to improve detection of this
|
|
style of attack. For instance, NAT rebinding is improbable if
|
|
packets were recently received on the old path; similarly, rebinding
|
|
is rare on IPv6 paths. Endpoints can also look for duplicated
|
|
packets. Conversely, a change in connection ID is more likely to
|
|
indicate an intentional migration rather than an attack.
|
|
|
|
Loss Detection and Congestion Control
|
|
`````````````````````````````````````````
|
|
|
|
The capacity available on the new path might not be the same as the
|
|
old path. Packets sent on the old path MUST NOT contribute to
|
|
congestion control or RTT estimation for the new path.
|
|
|
|
On confirming a peer's ownership of its new address, an endpoint MUST
|
|
immediately reset the congestion controller and round-trip time
|
|
estimator for the new path to initial values (see Appendices A.3 and
|
|
B.3 of [QUIC-RECOVERY]) unless the only change in the peer's address
|
|
is its port number. Because port-only changes are commonly the
|
|
result of NAT rebinding or other middlebox activity, the endpoint MAY
|
|
instead retain its congestion control state and round-trip estimate
|
|
in those cases instead of reverting to initial values. In cases
|
|
where congestion control state retained from an old path is used on a
|
|
new path with substantially different characteristics, a sender could
|
|
transmit too aggressively until the congestion controller and the RTT
|
|
estimator have adapted. Generally, implementations are advised to be
|
|
cautious when using previous values on a new path.
|
|
|
|
There could be apparent reordering at the receiver when an endpoint
|
|
sends data and probes from/to multiple addresses during the migration
|
|
period, since the two resulting paths could have different round-trip
|
|
times. A receiver of packets on multiple paths will still send ACK
|
|
frames covering all received packets.
|
|
|
|
While multiple paths might be used during connection migration, a
|
|
single congestion control context and a single loss recovery context
|
|
(as described in [QUIC-RECOVERY]) could be adequate. For instance,
|
|
an endpoint might delay switching to a new congestion control context
|
|
until it is confirmed that an old path is no longer needed (such as
|
|
the case described in Section 9.3.3).
|
|
|
|
A sender can make exceptions for probe packets so that their loss
|
|
detection is independent and does not unduly cause the congestion
|
|
controller to reduce its sending rate. An endpoint might set a
|
|
separate timer when a PATH_CHALLENGE is sent, which is canceled if
|
|
the corresponding PATH_RESPONSE is received. If the timer fires
|
|
before the PATH_RESPONSE is received, the endpoint might send a new
|
|
PATH_CHALLENGE and restart the timer for a longer period of time.
|
|
This timer SHOULD be set as described in Section 6.2.1 of
|
|
[QUIC-RECOVERY] and MUST NOT be more aggressive.
|
|
|
|
Privacy Implications of Connection Migration
|
|
`````````````````````````````````````````````````
|
|
|
|
Using a stable connection ID on multiple network paths would allow a
|
|
passive observer to correlate activity between those paths. An
|
|
endpoint that moves between networks might not wish to have their
|
|
activity correlated by any entity other than their peer, so different
|
|
connection IDs are used when sending from different local addresses,
|
|
as discussed in Section 5.1. For this to be effective, endpoints
|
|
need to ensure that connection IDs they provide cannot be linked by
|
|
any other entity.
|
|
|
|
At any time, endpoints MAY change the Destination Connection ID they
|
|
transmit with to a value that has not been used on another path.
|
|
|
|
An endpoint MUST NOT reuse a connection ID when sending from more
|
|
than one local address -- for example, when initiating connection
|
|
migration as described in Section 9.2 or when probing a new network
|
|
path as described in Section 9.1.
|
|
|
|
Similarly, an endpoint MUST NOT reuse a connection ID when sending to
|
|
more than one destination address. Due to network changes outside
|
|
the control of its peer, an endpoint might receive packets from a new
|
|
source address with the same Destination Connection ID field value,
|
|
in which case it MAY continue to use the current connection ID with
|
|
the new remote address while still sending from the same local
|
|
address.
|
|
|
|
These requirements regarding connection ID reuse apply only to the
|
|
sending of packets, as unintentional changes in path without a change
|
|
in connection ID are possible. For example, after a period of
|
|
network inactivity, NAT rebinding might cause packets to be sent on a
|
|
new path when the client resumes sending. An endpoint responds to
|
|
such an event as described in Section 9.3.
|
|
|
|
Using different connection IDs for packets sent in both directions on
|
|
each new network path eliminates the use of the connection ID for
|
|
linking packets from the same connection across different network
|
|
paths. Header protection ensures that packet numbers cannot be used
|
|
to correlate activity. This does not prevent other properties of
|
|
packets, such as timing and size, from being used to correlate
|
|
activity.
|
|
|
|
An endpoint SHOULD NOT initiate migration with a peer that has
|
|
requested a zero-length connection ID, because traffic over the new
|
|
path might be trivially linkable to traffic over the old one. If the
|
|
server is able to associate packets with a zero-length connection ID
|
|
to the right connection, it means that the server is using other
|
|
information to demultiplex packets. For example, a server might
|
|
provide a unique address to every client -- for instance, using HTTP
|
|
alternative services [ALTSVC]. Information that might allow correct
|
|
routing of packets across multiple network paths will also allow
|
|
activity on those paths to be linked by entities other than the peer.
|
|
|
|
A client might wish to reduce linkability by switching to a new
|
|
connection ID, source UDP port, or IP address (see [RFC8981]) when
|
|
sending traffic after a period of inactivity. Changing the address
|
|
from which it sends packets at the same time might cause the server
|
|
to detect a connection migration. This ensures that the mechanisms
|
|
that support migration are exercised even for clients that do not
|
|
experience NAT rebindings or genuine migrations. Changing address
|
|
can cause a peer to reset its congestion control state (see
|
|
Section 9.4), so addresses SHOULD only be changed infrequently.
|
|
|
|
An endpoint that exhausts available connection IDs cannot probe new
|
|
paths or initiate migration, nor can it respond to probes or attempts
|
|
by its peer to migrate. To ensure that migration is possible and
|
|
packets sent on different paths cannot be correlated, endpoints
|
|
SHOULD provide new connection IDs before peers migrate; see
|
|
Section 5.1.1. If a peer might have exhausted available connection
|
|
IDs, a migrating endpoint could include a NEW_CONNECTION_ID frame in
|
|
all packets sent on a new network path.
|
|
|
|
Server's Preferred Address
|
|
`````````````````````````````
|
|
|
|
QUIC allows servers to accept connections on one IP address and
|
|
attempt to transfer these connections to a more preferred address
|
|
shortly after the handshake. This is particularly useful when
|
|
clients initially connect to an address shared by multiple servers
|
|
but would prefer to use a unicast address to ensure connection
|
|
stability. This section describes the protocol for migrating a
|
|
connection to a preferred server address.
|
|
|
|
Migrating a connection to a new server address mid-connection is not
|
|
supported by the version of QUIC specified in this document. If a
|
|
client receives packets from a new server address when the client has
|
|
not initiated a migration to that address, the client SHOULD discard
|
|
these packets.
|
|
|
|
Communicating a Preferred Address
|
|
``````````````````````````````````````
|
|
|
|
A server conveys a preferred address by including the
|
|
preferred_address transport parameter in the TLS handshake.
|
|
|
|
Servers MAY communicate a preferred address of each address family
|
|
(IPv4 and IPv6) to allow clients to pick the one most suited to their
|
|
network attachment.
|
|
|
|
Once the handshake is confirmed, the client SHOULD select one of the
|
|
two addresses provided by the server and initiate path validation
|
|
(see Section 8.2). A client constructs packets using any previously
|
|
unused active connection ID, taken from either the preferred_address
|
|
transport parameter or a NEW_CONNECTION_ID frame.
|
|
|
|
As soon as path validation succeeds, the client SHOULD begin sending
|
|
all future packets to the new server address using the new connection
|
|
ID and discontinue use of the old server address. If path validation
|
|
fails, the client MUST continue sending all future packets to the
|
|
server's original IP address.
|
|
|
|
Migration to a Preferred Address
|
|
````````````````````````````````````
|
|
|
|
A client that migrates to a preferred address MUST validate the
|
|
address it chooses before migrating; see Section 21.5.3.
|
|
|
|
A server might receive a packet addressed to its preferred IP address
|
|
at any time after it accepts a connection. If this packet contains a
|
|
PATH_CHALLENGE frame, the server sends a packet containing a
|
|
PATH_RESPONSE frame as per Section 8.2. The server MUST send non-
|
|
probing packets from its original address until it receives a non-
|
|
probing packet from the client at its preferred address and until the
|
|
server has validated the new path.
|
|
|
|
The server MUST probe on the path toward the client from its
|
|
preferred address. This helps to guard against spurious migration
|
|
initiated by an attacker.
|
|
|
|
Once the server has completed its path validation and has received a
|
|
non-probing packet with a new largest packet number on its preferred
|
|
address, the server begins sending non-probing packets to the client
|
|
exclusively from its preferred IP address. The server SHOULD drop
|
|
newer packets for this connection that are received on the old IP
|
|
address. The server MAY continue to process delayed packets that are
|
|
received on the old IP address.
|
|
|
|
The addresses that a server provides in the preferred_address
|
|
transport parameter are only valid for the connection in which they
|
|
are provided. A client MUST NOT use these for other connections,
|
|
including connections that are resumed from the current connection.
|
|
|
|
Interaction of Client Migration and Preferred Address
|
|
``````````````````````````````````````````````````````````
|
|
|
|
A client might need to perform a connection migration before it has
|
|
migrated to the server's preferred address. In this case, the client
|
|
SHOULD perform path validation to both the original and preferred
|
|
server address from the client's new address concurrently.
|
|
|
|
If path validation of the server's preferred address succeeds, the
|
|
client MUST abandon validation of the original address and migrate to
|
|
using the server's preferred address. If path validation of the
|
|
server's preferred address fails but validation of the server's
|
|
original address succeeds, the client MAY migrate to its new address
|
|
and continue sending to the server's original address.
|
|
|
|
If packets received at the server's preferred address have a
|
|
different source address than observed from the client during the
|
|
handshake, the server MUST protect against potential attacks as
|
|
described in Sections 9.3.1 and 9.3.2. In addition to intentional
|
|
simultaneous migration, this might also occur because the client's
|
|
access network used a different NAT binding for the server's
|
|
preferred address.
|
|
|
|
Servers SHOULD initiate path validation to the client's new address
|
|
upon receiving a probe packet from a different address; see
|
|
Section 8.
|
|
|
|
A client that migrates to a new address SHOULD use a preferred
|
|
address from the same address family for the server.
|
|
|
|
The connection ID provided in the preferred_address transport
|
|
parameter is not specific to the addresses that are provided. This
|
|
connection ID is provided to ensure that the client has a connection
|
|
ID available for migration, but the client MAY use this connection ID
|
|
on any path.
|
|
|
|
Use of IPv6 Flow Label and Migration
|
|
``````````````````````````````````````````
|
|
|
|
QUIC recommends endpoints that send data using IPv6 SHOULD apply an IPv6 flow label
|
|
in compliance with [RFC-6437]_, unless the local API does not allow
|
|
setting IPv6 flow labels.
|
|
|
|
Unfortunately, the Java API does not allow setting IPv6 flow labels.
|
|
|
|
|
|
Security Considerations
|
|
---------------------------
|
|
|
|
Following is copied from QUIC [RFC-9000]_.
|
|
For each section, review and edit.
|
|
|
|
The goal of QUIC is to provide a secure transport connection.
|
|
Section 21.1 provides an overview of those properties; subsequent
|
|
sections discuss constraints and caveats regarding these properties,
|
|
including descriptions of known attacks and countermeasures.
|
|
|
|
Overview of Security Properties
|
|
``````````````````````````````````````````````
|
|
|
|
A complete security analysis of QUIC is outside the scope of this
|
|
document. This section provides an informal description of the
|
|
desired security properties as an aid to implementers and to help
|
|
guide protocol analysis.
|
|
|
|
QUIC assumes the threat model described in [SEC-CONS] and provides
|
|
protections against many of the attacks that arise from that model.
|
|
|
|
For this purpose, attacks are divided into passive and active
|
|
attacks. Passive attackers have the ability to read packets from the
|
|
network, while active attackers also have the ability to write
|
|
packets into the network. However, a passive attack could involve an
|
|
attacker with the ability to cause a routing change or other
|
|
modification in the path taken by packets that comprise a connection.
|
|
|
|
Attackers are additionally categorized as either on-path attackers or
|
|
off-path attackers. An on-path attacker can read, modify, or remove
|
|
any packet it observes such that the packet no longer reaches its
|
|
destination, while an off-path attacker observes the packets but
|
|
cannot prevent the original packet from reaching its intended
|
|
destination. Both types of attackers can also transmit arbitrary
|
|
packets. This definition differs from that of Section 3.5 of
|
|
[SEC-CONS] in that an off-path attacker is able to observe packets.
|
|
|
|
Properties of the handshake, protected packets, and connection
|
|
migration are considered separately.
|
|
|
|
Handshake
|
|
``````````````````````````````````````````````
|
|
|
|
The QUIC handshake incorporates the TLS 1.3 handshake and inherits
|
|
the cryptographic properties described in Appendix E.1 of [TLS13].
|
|
Many of the security properties of QUIC depend on the TLS handshake
|
|
providing these properties. Any attack on the TLS handshake could
|
|
affect QUIC.
|
|
|
|
Any attack on the TLS handshake that compromises the secrecy or
|
|
uniqueness of session keys, or the authentication of the
|
|
participating peers, affects other security guarantees provided by
|
|
QUIC that depend on those keys. For instance, migration (Section 9)
|
|
depends on the efficacy of confidentiality protections, both for the
|
|
negotiation of keys using the TLS handshake and for QUIC packet
|
|
protection, to avoid linkability across network paths.
|
|
|
|
An attack on the integrity of the TLS handshake might allow an
|
|
attacker to affect the selection of application protocol or QUIC
|
|
version.
|
|
|
|
In addition to the properties provided by TLS, the QUIC handshake
|
|
provides some defense against DoS attacks on the handshake.
|
|
|
|
Anti-Amplification
|
|
``````````````````````````````````````````````
|
|
|
|
Address validation (Section 8) is used to verify that an entity that
|
|
claims a given address is able to receive packets at that address.
|
|
Address validation limits amplification attack targets to addresses
|
|
for which an attacker can observe packets.
|
|
|
|
Prior to address validation, endpoints are limited in what they are
|
|
able to send. Endpoints cannot send data toward an unvalidated
|
|
address in excess of three times the data received from that address.
|
|
|
|
Note: The anti-amplification limit only applies when an
|
|
endpoint responds to packets received from an unvalidated
|
|
address. The anti-amplification limit does not apply to
|
|
clients when establishing a new connection or when initiating
|
|
connection migration.
|
|
|
|
Server-Side DoS
|
|
``````````````````````````````````````````````
|
|
|
|
Computing the server's first flight for a full handshake is
|
|
potentially expensive, requiring both a signature and a key exchange
|
|
computation. In order to prevent computational DoS attacks, the
|
|
Retry packet provides a cheap token exchange mechanism that allows
|
|
servers to validate a client's IP address prior to doing any
|
|
expensive computations at the cost of a single round trip. After a
|
|
successful handshake, servers can issue new tokens to a client, which
|
|
will allow new connection establishment without incurring this cost.
|
|
|
|
On-Path Handshake Termination
|
|
``````````````````````````````````````````````
|
|
|
|
An on-path or off-path attacker can force a handshake to fail by
|
|
replacing or racing Initial packets. Once valid Initial packets have
|
|
been exchanged, subsequent Handshake packets are protected with the
|
|
Handshake keys, and an on-path attacker cannot force handshake
|
|
failure other than by dropping packets to cause endpoints to abandon
|
|
the attempt.
|
|
|
|
An on-path attacker can also replace the addresses of packets on
|
|
either side and therefore cause the client or server to have an
|
|
incorrect view of the remote addresses. Such an attack is
|
|
indistinguishable from the functions performed by a NAT.
|
|
|
|
Parameter Negotiation
|
|
``````````````````````````````````````````````
|
|
|
|
The entire handshake is cryptographically protected, with the Initial
|
|
packets being encrypted with per-version keys and the Handshake and
|
|
later packets being encrypted with keys derived from the TLS key
|
|
exchange. Further, parameter negotiation is folded into the TLS
|
|
transcript and thus provides the same integrity guarantees as
|
|
ordinary TLS negotiation. An attacker can observe the client's
|
|
transport parameters (as long as it knows the version-specific salt)
|
|
but cannot observe the server's transport parameters and cannot
|
|
influence parameter negotiation.
|
|
|
|
Connection IDs are unencrypted but integrity protected in all
|
|
packets.
|
|
|
|
This version of QUIC does not incorporate a version negotiation
|
|
mechanism; implementations of incompatible versions will simply fail
|
|
to establish a connection.
|
|
|
|
Protected Packets
|
|
``````````````````````````````````````````````
|
|
|
|
Packet protection (Section 12.1) applies authenticated encryption to
|
|
all packets except Version Negotiation packets, though Initial and
|
|
Retry packets have limited protection due to the use of version-
|
|
specific keying material; see [QUIC-TLS] for more details. This
|
|
section considers passive and active attacks against protected
|
|
packets.
|
|
|
|
Both on-path and off-path attackers can mount a passive attack in
|
|
which they save observed packets for an offline attack against packet
|
|
protection at a future time; this is true for any observer of any
|
|
packet on any network.
|
|
|
|
An attacker that injects packets without being able to observe valid
|
|
packets for a connection is unlikely to be successful, since packet
|
|
protection ensures that valid packets are only generated by endpoints
|
|
that possess the key material established during the handshake; see
|
|
Sections 7 and 21.1.1. Similarly, any active attacker that observes
|
|
packets and attempts to insert new data or modify existing data in
|
|
those packets should not be able to generate packets deemed valid by
|
|
the receiving endpoint, other than Initial packets.
|
|
|
|
A spoofing attack, in which an active attacker rewrites unprotected
|
|
parts of a packet that it forwards or injects, such as the source or
|
|
destination address, is only effective if the attacker can forward
|
|
packets to the original endpoint. Packet protection ensures that the
|
|
packet payloads can only be processed by the endpoints that completed
|
|
the handshake, and invalid packets are ignored by those endpoints.
|
|
|
|
An attacker can also modify the boundaries between packets and UDP
|
|
datagrams, causing multiple packets to be coalesced into a single
|
|
datagram or splitting coalesced packets into multiple datagrams.
|
|
Aside from datagrams containing Initial packets, which require
|
|
padding, modification of how packets are arranged in datagrams has no
|
|
functional effect on a connection, although it might change some
|
|
performance characteristics.
|
|
|
|
Connection Migration
|
|
``````````````````````````````````````````````
|
|
|
|
Connection migration (Section 9) provides endpoints with the ability
|
|
to transition between IP addresses and ports on multiple paths, using
|
|
one path at a time for transmission and receipt of non-probing
|
|
frames. Path validation (Section 8.2) establishes that a peer is
|
|
both willing and able to receive packets sent on a particular path.
|
|
This helps reduce the effects of address spoofing by limiting the
|
|
number of packets sent to a spoofed address.
|
|
|
|
This section describes the intended security properties of connection
|
|
migration under various types of DoS attacks.
|
|
|
|
On-Path Active Attacks
|
|
``````````````````````````````````````````````
|
|
|
|
An attacker that can cause a packet it observes to no longer reach
|
|
its intended destination is considered an on-path attacker. When an
|
|
attacker is present between a client and server, endpoints are
|
|
required to send packets through the attacker to establish
|
|
connectivity on a given path.
|
|
|
|
An on-path attacker can:
|
|
|
|
* Inspect packets
|
|
|
|
* Modify IP and UDP packet headers
|
|
|
|
* Inject new packets
|
|
|
|
* Delay packets
|
|
|
|
* Reorder packets
|
|
|
|
* Drop packets
|
|
|
|
* Split and merge datagrams along packet boundaries
|
|
|
|
An on-path attacker cannot:
|
|
|
|
* Modify an authenticated portion of a packet and cause the
|
|
recipient to accept that packet
|
|
|
|
An on-path attacker has the opportunity to modify the packets that it
|
|
observes; however, any modifications to an authenticated portion of a
|
|
packet will cause it to be dropped by the receiving endpoint as
|
|
invalid, as packet payloads are both authenticated and encrypted.
|
|
|
|
QUIC aims to constrain the capabilities of an on-path attacker as
|
|
follows:
|
|
|
|
1. An on-path attacker can prevent the use of a path for a
|
|
connection, causing the connection to fail if it cannot use a
|
|
different path that does not contain the attacker. This can be
|
|
achieved by dropping all packets, modifying them so that they
|
|
fail to decrypt, or other methods.
|
|
|
|
2. An on-path attacker can prevent migration to a new path for which
|
|
the attacker is also on-path by causing path validation to fail
|
|
on the new path.
|
|
|
|
3. An on-path attacker cannot prevent a client from migrating to a
|
|
path for which the attacker is not on-path.
|
|
|
|
4. An on-path attacker can reduce the throughput of a connection by
|
|
delaying packets or dropping them.
|
|
|
|
5. An on-path attacker cannot cause an endpoint to accept a packet
|
|
for which it has modified an authenticated portion of that
|
|
packet.
|
|
|
|
Off-Path Active Attacks
|
|
``````````````````````````````````````````````
|
|
|
|
An off-path attacker is not directly on the path between a client and
|
|
server but could be able to obtain copies of some or all packets sent
|
|
between the client and the server. It is also able to send copies of
|
|
those packets to either endpoint.
|
|
|
|
An off-path attacker can:
|
|
|
|
* Inspect packets
|
|
|
|
* Inject new packets
|
|
|
|
* Reorder injected packets
|
|
|
|
An off-path attacker cannot:
|
|
|
|
* Modify packets sent by endpoints
|
|
|
|
* Delay packets
|
|
|
|
* Drop packets
|
|
|
|
* Reorder original packets
|
|
|
|
An off-path attacker can create modified copies of packets that it
|
|
has observed and inject those copies into the network, potentially
|
|
with spoofed source and destination addresses.
|
|
|
|
For the purposes of this discussion, it is assumed that an off-path
|
|
attacker has the ability to inject a modified copy of a packet into
|
|
the network that will reach the destination endpoint prior to the
|
|
arrival of the original packet observed by the attacker. In other
|
|
words, an attacker has the ability to consistently "win" a race with
|
|
the legitimate packets between the endpoints, potentially causing the
|
|
original packet to be ignored by the recipient.
|
|
|
|
It is also assumed that an attacker has the resources necessary to
|
|
affect NAT state. In particular, an attacker can cause an endpoint
|
|
to lose its NAT binding and then obtain the same port for use with
|
|
its own traffic.
|
|
|
|
QUIC aims to constrain the capabilities of an off-path attacker as
|
|
follows:
|
|
|
|
1. An off-path attacker can race packets and attempt to become a
|
|
"limited" on-path attacker.
|
|
|
|
2. An off-path attacker can cause path validation to succeed for
|
|
forwarded packets with the source address listed as the off-path
|
|
attacker as long as it can provide improved connectivity between
|
|
the client and the server.
|
|
|
|
3. An off-path attacker cannot cause a connection to close once the
|
|
handshake has completed.
|
|
|
|
4. An off-path attacker cannot cause migration to a new path to fail
|
|
if it cannot observe the new path.
|
|
|
|
5. An off-path attacker can become a limited on-path attacker during
|
|
migration to a new path for which it is also an off-path
|
|
attacker.
|
|
|
|
6. An off-path attacker can become a limited on-path attacker by
|
|
affecting shared NAT state such that it sends packets to the
|
|
server from the same IP address and port that the client
|
|
originally used.
|
|
|
|
Limited On-Path Active Attacks
|
|
``````````````````````````````````````````````
|
|
|
|
A limited on-path attacker is an off-path attacker that has offered
|
|
improved routing of packets by duplicating and forwarding original
|
|
packets between the server and the client, causing those packets to
|
|
arrive before the original copies such that the original packets are
|
|
dropped by the destination endpoint.
|
|
|
|
A limited on-path attacker differs from an on-path attacker in that
|
|
it is not on the original path between endpoints, and therefore the
|
|
original packets sent by an endpoint are still reaching their
|
|
destination. This means that a future failure to route copied
|
|
packets to the destination faster than their original path will not
|
|
prevent the original packets from reaching the destination.
|
|
|
|
A limited on-path attacker can:
|
|
|
|
* Inspect packets
|
|
|
|
* Inject new packets
|
|
|
|
* Modify unencrypted packet headers
|
|
|
|
* Reorder packets
|
|
|
|
A limited on-path attacker cannot:
|
|
|
|
* Delay packets so that they arrive later than packets sent on the
|
|
original path
|
|
|
|
* Drop packets
|
|
|
|
* Modify the authenticated and encrypted portion of a packet and
|
|
cause the recipient to accept that packet
|
|
|
|
A limited on-path attacker can only delay packets up to the point
|
|
that the original packets arrive before the duplicate packets,
|
|
meaning that it cannot offer routing with worse latency than the
|
|
original path. If a limited on-path attacker drops packets, the
|
|
original copy will still arrive at the destination endpoint.
|
|
|
|
QUIC aims to constrain the capabilities of a limited off-path
|
|
attacker as follows:
|
|
|
|
1. A limited on-path attacker cannot cause a connection to close
|
|
once the handshake has completed.
|
|
|
|
2. A limited on-path attacker cannot cause an idle connection to
|
|
close if the client is first to resume activity.
|
|
|
|
3. A limited on-path attacker can cause an idle connection to be
|
|
deemed lost if the server is the first to resume activity.
|
|
|
|
Note that these guarantees are the same guarantees provided for any
|
|
NAT, for the same reasons.
|
|
|
|
Handshake Denial of Service
|
|
``````````````````````````````````````````````
|
|
|
|
As an encrypted and authenticated transport, QUIC provides a range of
|
|
protections against denial of service. Once the cryptographic
|
|
handshake is complete, QUIC endpoints discard most packets that are
|
|
not authenticated, greatly limiting the ability of an attacker to
|
|
interfere with existing connections.
|
|
|
|
Once a connection is established, QUIC endpoints might accept some
|
|
unauthenticated ICMP packets (see Section 14.2.1), but the use of
|
|
these packets is extremely limited. The only other type of packet
|
|
that an endpoint might accept is a stateless reset (Section 10.3),
|
|
which relies on the token being kept secret until it is used.
|
|
|
|
During the creation of a connection, QUIC only provides protection
|
|
against attacks from off the network path. All QUIC packets contain
|
|
proof that the recipient saw a preceding packet from its peer.
|
|
|
|
Addresses cannot change during the handshake, so endpoints can
|
|
discard packets that are received on a different network path.
|
|
|
|
The Source and Destination Connection ID fields are the primary means
|
|
of protection against an off-path attack during the handshake; see
|
|
Section 8.1. These are required to match those set by a peer.
|
|
Except for Initial and Stateless Resets, an endpoint only accepts
|
|
packets that include a Destination Connection ID field that matches a
|
|
value the endpoint previously chose. This is the only protection
|
|
offered for Version Negotiation packets.
|
|
|
|
The Destination Connection ID field in an Initial packet is selected
|
|
by a client to be unpredictable, which serves an additional purpose.
|
|
The packets that carry the cryptographic handshake are protected with
|
|
a key that is derived from this connection ID and a salt specific to
|
|
the QUIC version. This allows endpoints to use the same process for
|
|
authenticating packets that they receive as they use after the
|
|
cryptographic handshake completes. Packets that cannot be
|
|
authenticated are discarded. Protecting packets in this fashion
|
|
provides a strong assurance that the sender of the packet saw the
|
|
Initial packet and understood it.
|
|
|
|
These protections are not intended to be effective against an
|
|
attacker that is able to receive QUIC packets prior to the connection
|
|
being established. Such an attacker can potentially send packets
|
|
that will be accepted by QUIC endpoints. This version of QUIC
|
|
attempts to detect this sort of attack, but it expects that endpoints
|
|
will fail to establish a connection rather than recovering. For the
|
|
most part, the cryptographic handshake protocol [QUIC-TLS] is
|
|
responsible for detecting tampering during the handshake.
|
|
|
|
Endpoints are permitted to use other methods to detect and attempt to
|
|
recover from interference with the handshake. Invalid packets can be
|
|
identified and discarded using other methods, but no specific method
|
|
is mandated in this document.
|
|
|
|
Amplification Attack
|
|
``````````````````````````````````````````````
|
|
|
|
An attacker might be able to receive an address validation token
|
|
(Section 8) from a server and then release the IP address it used to
|
|
acquire that token. At a later time, the attacker can initiate a
|
|
0-RTT connection with a server by spoofing this same address, which
|
|
might now address a different (victim) endpoint. The attacker can
|
|
thus potentially cause the server to send an initial congestion
|
|
window's worth of data towards the victim.
|
|
|
|
Servers SHOULD provide mitigations for this attack by limiting the
|
|
usage and lifetime of address validation tokens; see Section 8.1.3.
|
|
|
|
Optimistic ACK Attack
|
|
``````````````````````````````````````````````
|
|
|
|
An endpoint that acknowledges packets it has not received might cause
|
|
a congestion controller to permit sending at rates beyond what the
|
|
network supports. An endpoint MAY skip packet numbers when sending
|
|
packets to detect this behavior. An endpoint can then immediately
|
|
close the connection with a connection error of type
|
|
PROTOCOL_VIOLATION; see Section 10.2.
|
|
|
|
Request Forgery Attacks
|
|
``````````````````````````````````````````````
|
|
|
|
A request forgery attack occurs where an endpoint causes its peer to
|
|
issue a request towards a victim, with the request controlled by the
|
|
endpoint. Request forgery attacks aim to provide an attacker with
|
|
access to capabilities of its peer that might otherwise be
|
|
unavailable to the attacker. For a networking protocol, a request
|
|
forgery attack is often used to exploit any implicit authorization
|
|
conferred on the peer by the victim due to the peer's location in the
|
|
network.
|
|
|
|
For request forgery to be effective, an attacker needs to be able to
|
|
influence what packets the peer sends and where these packets are
|
|
sent. If an attacker can target a vulnerable service with a
|
|
controlled payload, that service might perform actions that are
|
|
attributed to the attacker's peer but are decided by the attacker.
|
|
|
|
For example, cross-site request forgery [CSRF] exploits on the Web
|
|
cause a client to issue requests that include authorization cookies
|
|
[COOKIE], allowing one site access to information and actions that
|
|
are intended to be restricted to a different site.
|
|
|
|
As QUIC runs over UDP, the primary attack modality of concern is one
|
|
where an attacker can select the address to which its peer sends UDP
|
|
datagrams and can control some of the unprotected content of those
|
|
packets. As much of the data sent by QUIC endpoints is protected,
|
|
this includes control over ciphertext. An attack is successful if an
|
|
attacker can cause a peer to send a UDP datagram to a host that will
|
|
perform some action based on content in the datagram.
|
|
|
|
This section discusses ways in which QUIC might be used for request
|
|
forgery attacks.
|
|
|
|
This section also describes limited countermeasures that can be
|
|
implemented by QUIC endpoints. These mitigations can be employed
|
|
unilaterally by a QUIC implementation or deployment, without
|
|
potential targets for request forgery attacks taking action.
|
|
However, these countermeasures could be insufficient if UDP-based
|
|
services do not properly authorize requests.
|
|
|
|
Because the migration attack described in Section 21.5.4 is quite
|
|
powerful and does not have adequate countermeasures, QUIC server
|
|
implementations should assume that attackers can cause them to
|
|
generate arbitrary UDP payloads to arbitrary destinations. QUIC
|
|
servers SHOULD NOT be deployed in networks that do not deploy ingress
|
|
filtering [BCP38] and also have inadequately secured UDP endpoints.
|
|
|
|
Although it is not generally possible to ensure that clients are not
|
|
co-located with vulnerable endpoints, this version of QUIC does not
|
|
allow servers to migrate, thus preventing spoofed migration attacks
|
|
on clients. Any future extension that allows server migration MUST
|
|
also define countermeasures for forgery attacks.
|
|
|
|
Control Options for Endpoints
|
|
``````````````````````````````````````````````
|
|
|
|
QUIC offers some opportunities for an attacker to influence or
|
|
control where its peer sends UDP datagrams:
|
|
|
|
* initial connection establishment (Section 7), where a server is
|
|
able to choose where a client sends datagrams -- for example, by
|
|
populating DNS records;
|
|
|
|
* preferred addresses (Section 9.6), where a server is able to
|
|
choose where a client sends datagrams;
|
|
|
|
* spoofed connection migrations (Section 9.3.1), where a client is
|
|
able to use source address spoofing to select where a server sends
|
|
subsequent datagrams; and
|
|
|
|
* spoofed packets that cause a server to send a Version Negotiation
|
|
packet (Section 21.5.5).
|
|
|
|
In all cases, the attacker can cause its peer to send datagrams to a
|
|
victim that might not understand QUIC. That is, these packets are
|
|
sent by the peer prior to address validation; see Section 8.
|
|
|
|
Outside of the encrypted portion of packets, QUIC offers an endpoint
|
|
several options for controlling the content of UDP datagrams that its
|
|
peer sends. The Destination Connection ID field offers direct
|
|
control over bytes that appear early in packets sent by the peer; see
|
|
Section 5.1. The Token field in Initial packets offers a server
|
|
control over other bytes of Initial packets; see Section 17.2.2.
|
|
|
|
There are no measures in this version of QUIC to prevent indirect
|
|
control over the encrypted portions of packets. It is necessary to
|
|
assume that endpoints are able to control the contents of frames that
|
|
a peer sends, especially those frames that convey application data,
|
|
such as STREAM frames. Though this depends to some degree on details
|
|
of the application protocol, some control is possible in many
|
|
protocol usage contexts. As the attacker has access to packet
|
|
protection keys, they are likely to be capable of predicting how a
|
|
peer will encrypt future packets. Successful control over datagram
|
|
content then only requires that the attacker be able to predict the
|
|
packet number and placement of frames in packets with some amount of
|
|
reliability.
|
|
|
|
This section assumes that limiting control over datagram content is
|
|
not feasible. The focus of the mitigations in subsequent sections is
|
|
on limiting the ways in which datagrams that are sent prior to
|
|
address validation can be used for request forgery.
|
|
|
|
Request Forgery with Client Initial Packets
|
|
``````````````````````````````````````````````
|
|
|
|
An attacker acting as a server can choose the IP address and port on
|
|
which it advertises its availability, so Initial packets from clients
|
|
are assumed to be available for use in this sort of attack. The
|
|
address validation implicit in the handshake ensures that -- for a
|
|
new connection -- a client will not send other types of packets to a
|
|
destination that does not understand QUIC or is not willing to accept
|
|
a QUIC connection.
|
|
|
|
Initial packet protection (Section 5.2 of [QUIC-TLS]) makes it
|
|
difficult for servers to control the content of Initial packets sent
|
|
by clients. A client choosing an unpredictable Destination
|
|
Connection ID ensures that servers are unable to control any of the
|
|
encrypted portion of Initial packets from clients.
|
|
|
|
However, the Token field is open to server control and does allow a
|
|
server to use clients to mount request forgery attacks. The use of
|
|
tokens provided with the NEW_TOKEN frame (Section 8.1.3) offers the
|
|
only option for request forgery during connection establishment.
|
|
|
|
Clients, however, are not obligated to use the NEW_TOKEN frame.
|
|
Request forgery attacks that rely on the Token field can be avoided
|
|
if clients send an empty Token field when the server address has
|
|
changed from when the NEW_TOKEN frame was received.
|
|
|
|
Clients could avoid using NEW_TOKEN if the server address changes.
|
|
However, not including a Token field could adversely affect
|
|
performance. Servers could rely on NEW_TOKEN to enable the sending
|
|
of data in excess of the three-times limit on sending data; see
|
|
Section 8.1. In particular, this affects cases where clients use
|
|
0-RTT to request data from servers.
|
|
|
|
Sending a Retry packet (Section 17.2.5) offers a server the option to
|
|
change the Token field. After sending a Retry, the server can also
|
|
control the Destination Connection ID field of subsequent Initial
|
|
packets from the client. This also might allow indirect control over
|
|
the encrypted content of Initial packets. However, the exchange of a
|
|
Retry packet validates the server's address, thereby preventing the
|
|
use of subsequent Initial packets for request forgery.
|
|
|
|
Request Forgery with Preferred Addresses
|
|
``````````````````````````````````````````````
|
|
|
|
Servers can specify a preferred address, which clients then migrate
|
|
to after confirming the handshake; see Section 9.6. The Destination
|
|
Connection ID field of packets that the client sends to a preferred
|
|
address can be used for request forgery.
|
|
|
|
A client MUST NOT send non-probing frames to a preferred address
|
|
prior to validating that address; see Section 8. This greatly
|
|
reduces the options that a server has to control the encrypted
|
|
portion of datagrams.
|
|
|
|
This document does not offer any additional countermeasures that are
|
|
specific to the use of preferred addresses and can be implemented by
|
|
endpoints. The generic measures described in Section 21.5.6 could be
|
|
used as further mitigation.
|
|
|
|
Request Forgery with Spoofed Migration
|
|
``````````````````````````````````````````
|
|
|
|
Clients are able to present a spoofed source address as part of an
|
|
apparent connection migration to cause a server to send datagrams to
|
|
that address.
|
|
|
|
The Destination Connection ID field in any packets that a server
|
|
subsequently sends to this spoofed address can be used for request
|
|
forgery. A client might also be able to influence the ciphertext.
|
|
|
|
A server that only sends probing packets (Section 9.1) to an address
|
|
prior to address validation provides an attacker with only limited
|
|
control over the encrypted portion of datagrams. However,
|
|
particularly for NAT rebinding, this can adversely affect
|
|
performance. If the server sends frames carrying application data,
|
|
an attacker might be able to control most of the content of
|
|
datagrams.
|
|
|
|
This document does not offer specific countermeasures that can be
|
|
implemented by endpoints, aside from the generic measures described
|
|
in Section 21.5.6. However, countermeasures for address spoofing at
|
|
the network level -- in particular, ingress filtering [BCP38] -- are
|
|
especially effective against attacks that use spoofing and originate
|
|
from an external network.
|
|
|
|
Request Forgery with Version Negotiation
|
|
`````````````````````````````````````````````````````
|
|
|
|
Clients that are able to present a spoofed source address on a packet
|
|
can cause a server to send a Version Negotiation packet
|
|
(Section 17.2.1) to that address.
|
|
|
|
The absence of size restrictions on the connection ID fields for
|
|
packets of an unknown version increases the amount of data that the
|
|
client controls from the resulting datagram. The first byte of this
|
|
packet is not under client control and the next four bytes are zero,
|
|
but the client is able to control up to 512 bytes starting from the
|
|
fifth byte.
|
|
|
|
No specific countermeasures are provided for this attack, though
|
|
generic protections (Section 21.5.6) could apply. In this case,
|
|
ingress filtering [BCP38] is also effective.
|
|
|
|
Generic Request Forgery Countermeasures
|
|
`````````````````````````````````````````````````````
|
|
|
|
The most effective defense against request forgery attacks is to
|
|
modify vulnerable services to use strong authentication. However,
|
|
this is not always something that is within the control of a QUIC
|
|
deployment. This section outlines some other steps that QUIC
|
|
endpoints could take unilaterally. These additional steps are all
|
|
discretionary because, depending on circumstances, they could
|
|
interfere with or prevent legitimate uses.
|
|
|
|
Services offered over loopback interfaces often lack proper
|
|
authentication. Endpoints MAY prevent connection attempts or
|
|
migration to a loopback address. Endpoints SHOULD NOT allow
|
|
connections or migration to a loopback address if the same service
|
|
was previously available at a different interface or if the address
|
|
was provided by a service at a non-loopback address. Endpoints that
|
|
depend on these capabilities could offer an option to disable these
|
|
protections.
|
|
|
|
Similarly, endpoints could regard a change in address to a link-local
|
|
address [RFC4291] or an address in a private-use range [RFC1918] from
|
|
a global, unique-local [RFC4193], or non-private address as a
|
|
potential attempt at request forgery. Endpoints could refuse to use
|
|
these addresses entirely, but that carries a significant risk of
|
|
interfering with legitimate uses. Endpoints SHOULD NOT refuse to use
|
|
an address unless they have specific knowledge about the network
|
|
indicating that sending datagrams to unvalidated addresses in a given
|
|
range is not safe.
|
|
|
|
Endpoints MAY choose to reduce the risk of request forgery by not
|
|
including values from NEW_TOKEN frames in Initial packets or by only
|
|
sending probing frames in packets prior to completing address
|
|
validation. Note that this does not prevent an attacker from using
|
|
the Destination Connection ID field for an attack.
|
|
|
|
Endpoints are not expected to have specific information about the
|
|
location of servers that could be vulnerable targets of a request
|
|
forgery attack. However, it might be possible over time to identify
|
|
specific UDP ports that are common targets of attacks or particular
|
|
patterns in datagrams that are used for attacks. Endpoints MAY
|
|
choose to avoid sending datagrams to these ports or not send
|
|
datagrams that match these patterns prior to validating the
|
|
destination address. Endpoints MAY retire connection IDs containing
|
|
patterns known to be problematic without using them.
|
|
|
|
Note: Modifying endpoints to apply these protections is more
|
|
efficient than deploying network-based protections, as
|
|
endpoints do not need to perform any additional processing when
|
|
sending to an address that has been validated.
|
|
|
|
Slowloris Attacks
|
|
`````````````````````````````````````````````````````
|
|
|
|
The attacks commonly known as Slowloris [SLOWLORIS] try to keep many
|
|
connections to the target endpoint open and hold them open as long as
|
|
possible. These attacks can be executed against a QUIC endpoint by
|
|
generating the minimum amount of activity necessary to avoid being
|
|
closed for inactivity. This might involve sending small amounts of
|
|
data, gradually opening flow control windows in order to control the
|
|
sender rate, or manufacturing ACK frames that simulate a high loss
|
|
rate.
|
|
|
|
QUIC deployments SHOULD provide mitigations for the Slowloris
|
|
attacks, such as increasing the maximum number of clients the server
|
|
will allow, limiting the number of connections a single IP address is
|
|
allowed to make, imposing restrictions on the minimum transfer speed
|
|
a connection is allowed to have, and restricting the length of time
|
|
an endpoint is allowed to stay connected.
|
|
|
|
Stream Fragmentation and Reassembly Attacks
|
|
`````````````````````````````````````````````````````
|
|
|
|
An adversarial sender might intentionally not send portions of the
|
|
stream data, causing the receiver to commit resources for the unsent
|
|
data. This could cause a disproportionate receive buffer memory
|
|
commitment and/or the creation of a large and inefficient data
|
|
structure at the receiver.
|
|
|
|
An adversarial receiver might intentionally not acknowledge packets
|
|
containing stream data in an attempt to force the sender to store the
|
|
unacknowledged stream data for retransmission.
|
|
|
|
The attack on receivers is mitigated if flow control windows
|
|
correspond to available memory. However, some receivers will
|
|
overcommit memory and advertise flow control offsets in the aggregate
|
|
that exceed actual available memory. The overcommitment strategy can
|
|
lead to better performance when endpoints are well behaved, but
|
|
renders endpoints vulnerable to the stream fragmentation attack.
|
|
|
|
QUIC deployments SHOULD provide mitigations for stream fragmentation
|
|
attacks. Mitigations could consist of avoiding overcommitting
|
|
memory, limiting the size of tracking data structures, delaying
|
|
reassembly of STREAM frames, implementing heuristics based on the age
|
|
and duration of reassembly holes, or some combination of these.
|
|
|
|
Stream Commitment Attack
|
|
`````````````````````````````````````````````````````
|
|
|
|
An adversarial endpoint can open a large number of streams,
|
|
exhausting state on an endpoint. The adversarial endpoint could
|
|
repeat the process on a large number of connections, in a manner
|
|
similar to SYN flooding attacks in TCP.
|
|
|
|
Normally, clients will open streams sequentially, as explained in
|
|
Section 2.1. However, when several streams are initiated at short
|
|
intervals, loss or reordering can cause STREAM frames that open
|
|
streams to be received out of sequence. On receiving a higher-
|
|
numbered stream ID, a receiver is required to open all intervening
|
|
streams of the same type; see Section 3.2. Thus, on a new
|
|
connection, opening stream 4000000 opens 1 million and 1 client-
|
|
initiated bidirectional streams.
|
|
|
|
The number of active streams is limited by the
|
|
initial_max_streams_bidi and initial_max_streams_uni transport
|
|
parameters as updated by any received MAX_STREAMS frames, as
|
|
explained in Section 4.6. If chosen judiciously, these limits
|
|
mitigate the effect of the stream commitment attack. However,
|
|
setting the limit too low could affect performance when applications
|
|
expect to open a large number of streams.
|
|
|
|
Peer Denial of Service
|
|
`````````````````````````````````````````````````````
|
|
|
|
QUIC and TLS both contain frames or messages that have legitimate
|
|
uses in some contexts, but these frames or messages can be abused to
|
|
cause a peer to expend processing resources without having any
|
|
observable impact on the state of the connection.
|
|
|
|
Messages can also be used to change and revert state in small or
|
|
inconsequential ways, such as by sending small increments to flow
|
|
control limits.
|
|
|
|
If processing costs are disproportionately large in comparison to
|
|
bandwidth consumption or effect on state, then this could allow a
|
|
malicious peer to exhaust processing capacity.
|
|
|
|
While there are legitimate uses for all messages, implementations
|
|
SHOULD track cost of processing relative to progress and treat
|
|
excessive quantities of any non-productive packets as indicative of
|
|
an attack. Endpoints MAY respond to this condition with a connection
|
|
error or by dropping packets.
|
|
|
|
Explicit Congestion Notification Attacks
|
|
`````````````````````````````````````````````````````
|
|
|
|
An on-path attacker could manipulate the value of ECN fields in the
|
|
IP header to influence the sender's rate. [RFC3168] discusses
|
|
manipulations and their effects in more detail.
|
|
|
|
A limited on-path attacker can duplicate and send packets with
|
|
modified ECN fields to affect the sender's rate. If duplicate
|
|
packets are discarded by a receiver, an attacker will need to race
|
|
the duplicate packet against the original to be successful in this
|
|
attack. Therefore, QUIC endpoints ignore the ECN field in an IP
|
|
packet unless at least one QUIC packet in that IP packet is
|
|
successfully processed; see Section 13.4.
|
|
|
|
Stateless Reset Oracle
|
|
`````````````````````````````````````````````````````
|
|
|
|
Stateless resets create a possible denial-of-service attack analogous
|
|
to a TCP reset injection. This attack is possible if an attacker is
|
|
able to cause a stateless reset token to be generated for a
|
|
connection with a selected connection ID. An attacker that can cause
|
|
this token to be generated can reset an active connection with the
|
|
same connection ID.
|
|
|
|
If a packet can be routed to different instances that share a static
|
|
key -- for example, by changing an IP address or port -- then an
|
|
attacker can cause the server to send a stateless reset. To defend
|
|
against this style of denial of service, endpoints that share a
|
|
static key for stateless resets (see Section 10.3.2) MUST be arranged
|
|
so that packets with a given connection ID always arrive at an
|
|
instance that has connection state, unless that connection is no
|
|
longer active.
|
|
|
|
More generally, servers MUST NOT generate a stateless reset if a
|
|
connection with the corresponding connection ID could be active on
|
|
any endpoint using the same static key.
|
|
|
|
In the case of a cluster that uses dynamic load balancing, it is
|
|
possible that a change in load-balancer configuration could occur
|
|
while an active instance retains connection state. Even if an
|
|
instance retains connection state, the change in routing and
|
|
resulting stateless reset will result in the connection being
|
|
terminated. If there is no chance of the packet being routed to the
|
|
correct instance, it is better to send a stateless reset than wait
|
|
for the connection to time out. However, this is acceptable only if
|
|
the routing cannot be influenced by an attacker.
|
|
|
|
Version Downgrade
|
|
`````````````````````````````````````````````````````
|
|
|
|
This document defines QUIC Version Negotiation packets (Section 6),
|
|
which can be used to negotiate the QUIC version used between two
|
|
endpoints. However, this document does not specify how this
|
|
negotiation will be performed between this version and subsequent
|
|
future versions. In particular, Version Negotiation packets do not
|
|
contain any mechanism to prevent version downgrade attacks. Future
|
|
versions of QUIC that use Version Negotiation packets MUST define a
|
|
mechanism that is robust against version downgrade attacks.
|
|
|
|
Targeted Attacks by Routing
|
|
`````````````````````````````````````````````````````
|
|
|
|
Deployments should limit the ability of an attacker to target a new
|
|
connection to a particular server instance. Ideally, routing
|
|
decisions are made independently of client-selected values, including
|
|
addresses. Once an instance is selected, a connection ID can be
|
|
selected so that later packets are routed to the same instance.
|
|
|
|
Traffic Analysis
|
|
`````````````````````````````````````````````````````
|
|
|
|
The length of QUIC packets can reveal information about the length of
|
|
the content of those packets. The PADDING frame is provided so that
|
|
endpoints have some ability to obscure the length of packet content;
|
|
see Section 19.1.
|
|
|
|
Defeating traffic analysis is challenging and the subject of active
|
|
research. Length is not the only way that information might leak.
|
|
Endpoints might also reveal sensitive information through other side
|
|
channels, such as the timing of packets.
|
|
|
|
|
|
Relay Security
|
|
----------------
|
|
|
|
Following is an analysis of Relay Request, Relay Response, Relay Intro, and Hole Punch.
|
|
|
|
Constraints: It is important that Relays be fast.
|
|
Round trips should be minimized.
|
|
Bandwidth and CPU are not as important.
|
|
|
|
|
|
SSU 1:
|
|
Alice first connects to introducer Bob, who relays the request to Charlie (who is firewalled).
|
|
After the hole punch, the session is established between Alice and Charlie as in a direct establishment.
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight %}
|
|
Alice Bob Charlie
|
|
1. RelayRequest ---------------------->
|
|
2. <-------------- RelayResponse RelayIntro ----------->
|
|
3. <-------------------------------------------- HolePunch
|
|
4. SessionRequest -------------------------------------------->
|
|
5. <-------------------------------------------- SessionCreated
|
|
6. SessionConfirmed ------------------------------------------>
|
|
{% endhighlight %}
|
|
|
|
Authentication: Relay Request and Relay Response are not securely unauthenticated,
|
|
as Alice and Bob usually do not have an existing session;
|
|
these messages use published intro keys.
|
|
In-session Relay Request/Response is allowed and preferred if a session does exist.
|
|
|
|
Relay Intro from Bob to Charlie is required to be in an existing session,
|
|
so it is presumed secure.
|
|
|
|
Bob may spoof Relay Intros or change IP/port from the Relay Request.
|
|
There are no mechanisms to cryptographically bind requests to intros or
|
|
otherwise prevent or detect malicious Bobs.
|
|
|
|
Bob's router hash is not currently published in Charlie's Router Info, so
|
|
that must be added if we want the Alice-Bob messages to be authenticated.
|
|
Additionally, other SSU2 parameters would have to be published in Charlie's Router Info,
|
|
or Alice would have to lookup Bob's Router Info in the network database,
|
|
adding additional delay.
|
|
Authentication would add a round-trip between Alice and Bob.
|
|
|
|
By forwarding Alice's router hash to Charlie, Charlie could more easily
|
|
determine if he wishes to receive a connection from Alice,
|
|
by checking a local ban list.
|
|
There is no mechanism for Charlie to reject the relay by sending
|
|
a rejection through Bob to Alice.
|
|
There is no mechanism for Charlie to accept the relay by sending
|
|
an acceptance through Bob to Alice. Alice must wait for the HolePunch,
|
|
or simply send the SessionRequest blindly. The HolePunch may come from
|
|
a different port than Alice was expecting, due to NAT, which
|
|
may make it harder to recognize what router the HolePunch came from.
|
|
|
|
Alice could send her full Router Info in the Relay Request to Bob,
|
|
and forwarded to Charlie in the Relay Intro.
|
|
|
|
The Relay Request does not contain a timestamp, so it has no replay prevention.
|
|
The source IP can be spoofed, to cause Charlie to send a Hole Punch to any IP/port.
|
|
The Relay Request is not signed, and even if signed and timestamped,
|
|
Charlie does not have the full Router Identity to be able to verify the signature.
|
|
|
|
The protocol defines a challenge field of variable length 0-255 bytes.
|
|
The challenge in the Relay Request is passed to Charlie in the Relay Intro.
|
|
However, the protocol does not specify how to create, use, or verify the challenge,
|
|
and it is unimplemented.
|
|
If the HolePunch contained the challenge, Alice would be able to easily
|
|
correlate the HolePunch with Charlie.
|
|
|
|
Four byte nonce may need to be replaced or supplemented by
|
|
8-byte connection ID.
|
|
|
|
|
|
Peer Test Security
|
|
---------------------
|
|
|
|
Following is an analysis of Peer Test.
|
|
|
|
Constraints: It is not particularly important that Peer Tests be fast,
|
|
or low-bandwidth, or low-CPU, except perhaps at router startup,
|
|
where we prefer that the router discovers its reachability fairly quickly.
|
|
|
|
|
|
|
|
SSU 1:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight %}
|
|
Alice Bob Charlie
|
|
1. PeerTest ------------------->
|
|
2. PeerTest-------------------->
|
|
3. <-------------------PeerTest
|
|
4. <-------------------PeerTest
|
|
5. <------------------------------------------PeerTest
|
|
6. PeerTest------------------------------------------>
|
|
7. <------------------------------------------PeerTest
|
|
{% endhighlight %}
|
|
|
|
|
|
Authentication:
|
|
As of 0.9.15, Alice will always choose a Bob with an existing session.
|
|
The protocol also permits Bob's introKey if Alice and Bob do not have an established session,
|
|
but in the current implementation Alice always selects a Bob that is established.
|
|
As of release 0.9.15, Bob will reject PeerTests from peers without an established session.
|
|
Message 1 is sent in-session. Therefore, message 1 is secure and authenticated.
|
|
|
|
Bob selects a Charlie with whom he has an existing session.
|
|
Messages 2 and 3 are sent in-session. Therefore, messages 2 and 3 are secure and authenticated.
|
|
|
|
Message 4 should be sent in-session; however, the SSU 1 specification says that it is sent
|
|
with Alice's published intro key, which means not in-session.
|
|
Java I2P does send with the intro key, matching the specification.
|
|
This is fixable and should be fixed in SSU 1.
|
|
|
|
Alice must not have an existing session with Charlie for the test to proceed;
|
|
Alice aborts the test if Bob picks a Charlie that has a sesssion with Alice.
|
|
Therefore, messages 5-7 are not secure and authenticated.
|
|
|
|
All Peer Test messages contain a 4-byte nonce that is chosen by Alice.
|
|
This nonce is not used cryptographically.
|
|
|
|
Attacks possible on messages 5-7: to be researched.
|
|
|
|
Alice's router hash is not known to Charlie.
|
|
Charlie's router hash is not known to Alice.
|
|
Those must be added to the protocol if we want thoe Alice-Charlie messages to be authenticated.
|
|
Additionally, other SSU2 parameters would have to be provided in the Peer Test messages,
|
|
or Charlie would have to lookup Alice's Router Info in the network database,
|
|
adding additional delay.
|
|
Authentication would add a round-trip between Charlie and Alice.
|
|
|
|
By forwarding Alice's router hash to Charlie, Charlie could more easily
|
|
determine if he wishes to participate in a Peer Test with Alice,
|
|
by checking a local ban list.
|
|
|
|
Four byte nonce may need to be replaced or supplemented by
|
|
8-byte connection ID.
|
|
|
|
|
|
Relay and Peer Test Design Goals
|
|
---------------------------------
|
|
|
|
Relay and Peer Test have similar constructions.
|
|
In both cases, Alice requests Bob to forward a service request to Charlie,
|
|
and Charlie then acts on that request.
|
|
|
|
We have the following goals in improving the security of Relay and Peer Test:
|
|
|
|
- Protect against address spoofing or on-path threats that may
|
|
spoof, alter, forge, or replay requests from Alice to Bob.
|
|
Bob must ensure that Alice is an actual I2P router and that the
|
|
request and test address presented are valid.
|
|
|
|
- Protect against malicious Bobs that may spoof, alter, forge, or replay
|
|
requests forwarded to Charlie.
|
|
Charlie must ensure that both Alice and Bob are actual I2P routers and that the
|
|
request and test address presented are valid.
|
|
|
|
- Bob must receive enough information from Alice to be able to validate
|
|
the request and then accept or decline it.
|
|
Bob must have a mechanism to send the acception or rejection back
|
|
to Alice.
|
|
Bob must never be required to perform the requested action.
|
|
|
|
- Charlie must receive enough information from Bob to be able to validate
|
|
the request and then accept or decline it.
|
|
Charlie must have a mechanism to send the acception or rejection back
|
|
to Bob, to be forwarded to Alice.
|
|
Charlie must never be required to perform the requested action.
|
|
|
|
- Alice must be able to validate that the response forwarded via Bob
|
|
actually originated from Charlie.
|
|
|
|
- Alice and Charlie must be able to validate that their subsequent direct
|
|
messages (not relayed via Bob) are from the expected source
|
|
and are actual I2P routers.
|
|
|
|
|
|
The following mechanisms may assist in achieving these goals:
|
|
|
|
- Timestamps
|
|
|
|
- Signatures using the router signing key
|
|
|
|
- Using challenge data included in the request
|
|
|
|
- Encryption using the router encryption key
|
|
|
|
- Sending router hashes, Router Identities, or Router Infos,
|
|
not just IPs and ports.
|
|
|
|
- Validation of router information by querying the network database
|
|
|
|
- Checking router information, IPs, and ports against banlists
|
|
|
|
- Rate limiting
|
|
|
|
- Requiring session establishment
|
|
|
|
|
|
These possible mechanisms may increase the processing time and latency of
|
|
the Relay or Peer Test functions. All effects must be evaluated.
|
|
|
|
Cross-version relaying and peer testing should also be supported if possible.
|
|
This will facilitate a gradual transition from SSU 1 to SSU 2.
|
|
The possible version combinations are:
|
|
|
|
========= =========== ============= =============
|
|
Alice/Bob Bob/Charlie Alice/Charlie Supported
|
|
========= =========== ============= =============
|
|
1 1 2 no, use 1/1/1
|
|
1 2 1 yes?
|
|
1 2 2 no, use 1/2/1
|
|
2 1 2 yes?
|
|
2 2 1 no, use 2/2/2
|
|
2 2 2 yes
|
|
========= =========== ============= =============
|
|
|
|
|
|
|
|
|
|
Design Overview
|
|
====================
|
|
|
|
Summary
|
|
--------
|
|
|
|
We rely on several existing protocols, both within I2P and outside standards,
|
|
for inspiration, guidance, and code reuse:
|
|
|
|
* Threat models: From NTCP2 [NTCP2]_, with significant additional threats
|
|
relevant to UDP transport as analyzed by QUIC [RFC-9000]_ [RFC-9001]_.
|
|
|
|
* Cryptographic choices: From [NTCP2]_.
|
|
|
|
* Handshake: Noise XK from [NTCP2]_ and [NOISE]_. Significant simplifications
|
|
to NTCP2 are possible due to the encapsulation (inherent message boundaries)
|
|
provided by UDP.
|
|
|
|
* Handshake ephemeral key obfuscation: Adapted from [NTCP2]_
|
|
|
|
* Packet headers: Adapted from WireGuard [WireGuard]_ and QUIC [RFC-9000]_ [RFC-9001]_.
|
|
|
|
* Packet header obfuscation: Adapted from [NTCP2]_
|
|
|
|
* Packet header protection: Adapted from QUIC [RFC-9001]_ and [Nonces]_
|
|
|
|
* Headers used as AEAD associated data as in [ECIES]_.
|
|
|
|
* Packet numbering: Adapted from WireGuard [WireGuard]_ and QUIC [RFC-9000]_ [RFC-9001]_.
|
|
|
|
* Messages: Adapted from [SSU]_
|
|
|
|
* I2NP Fragmentation: Adapted from [SSU]_
|
|
|
|
* Relay and Peer Testing: Adapted from [SSU]_
|
|
|
|
* Block format: From [NTCP2]_ and [ECIES]_.
|
|
|
|
* Padding and options: From [NTCP2]_ and [ECIES]_.
|
|
|
|
* Flow control, acks, nacks: TBD
|
|
|
|
|
|
|
|
Delivery Guarantees
|
|
----------------------
|
|
|
|
As with other I2P transports NTCP, NTCP2, and SSU 1, this transport is not a general-purpose
|
|
facility for delivery of an in-order stream of bytes. It is designed for
|
|
transport of I2NP messages. There is no "stream" abstraction provided.
|
|
|
|
In addition, as for SSU, it contains additional facilities for peer-facilitated NAT traversal
|
|
and testing of reachability (inbound connections).
|
|
|
|
As for SSU 1, it does NOT provide in-order delivery of I2NP messages.
|
|
Nor does it provide guaranteed delivery of I2NP messages.
|
|
For efficiency, or because of out-of order delivery of UDP datagrams
|
|
or loss of those datagrams, I2NP messages may be delivered to the
|
|
far-end out-of-order, or may not be delivered at all.
|
|
An I2NP message may be retransmitted multiple times if necessary,
|
|
but delivery may eventually fail without causing the full connection to be
|
|
disconnected. Also, new I2NP messages may continue to be sent even
|
|
while retransmission (loss recovery) is occurring for other I2NP messages.
|
|
|
|
|
|
|
|
Noise Protocol Framework
|
|
-------------------------
|
|
|
|
This proposal provides the requirements based on the Noise Protocol Framework
|
|
[NOISE]_ (Revision 33, 2017-10-04).
|
|
Noise has similar properties to the Station-To-Station protocol
|
|
[STS]_, which is the basis for the [SSU]_ protocol. In Noise parlance, Alice
|
|
is the initiator, and Bob is the responder.
|
|
|
|
SSU2 is based on the Noise protocol Noise_XK_25519_ChaChaPoly_SHA256.
|
|
(The actual identifier for the initial key derivation function
|
|
is "Noise_XKaesobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256"
|
|
to indicate I2P extensions - see KDF 1 section below)
|
|
|
|
NOTE: This identifier is different than that used for NTCP2, because
|
|
all three handshake messages use the header as associated data.
|
|
|
|
This Noise protocol uses the following primitives:
|
|
|
|
- Handshake Pattern: XK
|
|
Alice transmits her key to Bob (X)
|
|
Alice knows Bob's static key already (K)
|
|
|
|
- DH Function: X25519
|
|
X25519 DH with a key length of 32 bytes as specified in [RFC-7748]_.
|
|
|
|
- Cipher Function: ChaChaPoly
|
|
AEAD_CHACHA20_POLY1305 as specified in [RFC-7539]_ section 2.8.
|
|
12 byte nonce, with the first 4 bytes set to zero.
|
|
|
|
- Hash Function: SHA256
|
|
Standard 32-byte hash, already used extensively in I2P.
|
|
|
|
|
|
Additions to the Framework
|
|
-------------------------------
|
|
|
|
This proposal defines the following enhancements to
|
|
Noise_XK_25519_ChaChaPoly_SHA256. These generally follow the guidelines in
|
|
[NOISE]_ section 13.
|
|
|
|
1) Cleartext ephemeral keys are obfuscated with AES encryption using a known
|
|
key and IV. This is quicker than elligator2.
|
|
|
|
|
|
|
|
New Cryptographic Primitives for I2P
|
|
---------------------------------------
|
|
|
|
None?
|
|
Investigate other hash functions to replace SHA256.
|
|
|
|
|
|
|
|
|
|
Processing overhead estimate
|
|
-----------------------------------
|
|
|
|
TBD
|
|
|
|
|
|
Definitions
|
|
===============
|
|
|
|
We define the following functions corresponding to the cryptographic building blocks used.
|
|
|
|
ZEROLEN
|
|
zero-length byte array
|
|
|
|
H(p, d)
|
|
SHA-256 hash function that takes a personalization string p and data d, and
|
|
produces an output of length 32 bytes.
|
|
As defined in [NOISE]_.
|
|
|| below means append.
|
|
|
|
Use SHA-256 as follows::
|
|
|
|
H(p, d) := SHA-256(p || d)
|
|
|
|
MixHash(d)
|
|
SHA-256 hash function that takes a previous hash h and new data d,
|
|
and produces an output of length 32 bytes.
|
|
|| below means append.
|
|
|
|
Use SHA-256 as follows::
|
|
|
|
MixHash(d) := h = SHA-256(h || d)
|
|
|
|
STREAM
|
|
The ChaCha20/Poly1305 AEAD as specified in [RFC-7539]_.
|
|
S_KEY_LEN = 32 and S_IV_LEN = 12.
|
|
|
|
ENCRYPT(k, n, plaintext, ad)
|
|
Encrypts plaintext using the cipher key k, and nonce n which MUST be unique for
|
|
the key k.
|
|
Associated data ad is optional.
|
|
Returns a ciphertext that is the size of the plaintext + 16 bytes for the HMAC.
|
|
|
|
The entire ciphertext must be indistinguishable from random if the key is secret.
|
|
|
|
DECRYPT(k, n, ciphertext, ad)
|
|
Decrypts ciphertext using the cipher key k, and nonce n.
|
|
Associated data ad is optional.
|
|
Returns the plaintext.
|
|
|
|
DH
|
|
X25519 public key agreement system. Private keys of 32 bytes, public keys of 32
|
|
bytes, produces outputs of 32 bytes. It has the following
|
|
functions:
|
|
|
|
GENERATE_PRIVATE()
|
|
Generates a new private key.
|
|
|
|
DERIVE_PUBLIC(privkey)
|
|
Returns the public key corresponding to the given private key.
|
|
|
|
DH(privkey, pubkey)
|
|
Generates a shared secret from the given private and public keys.
|
|
|
|
HKDF(salt, ikm, info, n)
|
|
A cryptographic key derivation function which takes some input key material ikm (which
|
|
should have good entropy but is not required to be a uniformly random string), a salt
|
|
of length 32 bytes, and a context-specific 'info' value, and produces an output
|
|
of n bytes suitable for use as key material.
|
|
|
|
Use HKDF as specified in [RFC-5869]_, using the HMAC hash function SHA-256
|
|
as specified in [RFC-2104]_. This means that SALT_LEN is 32 bytes max.
|
|
|
|
MixKey(d)
|
|
Use HKDF() with a previous chainKey and new data d, and
|
|
sets the new chainKey and k.
|
|
As defined in [NOISE]_.
|
|
|
|
Use HKDF as follows::
|
|
|
|
MixKey(d) := output = HKDF(chainKey, d, "", 64)
|
|
chainKey = output[0:31]
|
|
k = output[32:63]
|
|
|
|
|
|
|
|
|
|
Messages
|
|
========
|
|
|
|
Each UDP datagram contains exactly one message.
|
|
The length of the datagram (after the IP header) is the length of the message.
|
|
Padding, if any, is contained in a padding block inside the message.
|
|
In this document, we use the terms "datagram" and "packet" mostly interchangeably.
|
|
Each datagram (or packet) contains a single message (unlike QUIC, where
|
|
a datagram may contain multiple QUIC packets).
|
|
The "packet header" is the part after the IP/UDP header.
|
|
|
|
All SSU2 messages are less than or equal to TBD bytes in length. The message
|
|
format is based on Noise messages, with modifications for framing and indistinguishability.
|
|
Implementations using standard Noise libraries may need to pre-process received
|
|
messages to/from the Noise message format. All encrypted fields are AEAD
|
|
ciphertexts.
|
|
|
|
The following messages are defined:
|
|
|
|
==== ================ =====
|
|
Type Message Notes
|
|
==== ================ =====
|
|
0 SessionRequest
|
|
1 SessionCreated
|
|
2 SessionConfirmed
|
|
3 RelayRequest TBD may be a block
|
|
4 RelayResponse TBD may be a block
|
|
5 RelayIntro NO, block only
|
|
6 Data
|
|
7 PeerTest TBD may be a block
|
|
8 SessionDestroyed NO, block only??
|
|
9 Retry
|
|
n/a HolePunch
|
|
==== ================ =====
|
|
|
|
|
|
|
|
Session Establishment
|
|
-----------------------
|
|
|
|
The standard establishment sequence is as follows:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight %}
|
|
Alice Bob
|
|
|
|
SessionRequest ------------------->
|
|
<------------------- SessionCreated
|
|
SessionConfirmed ----------------->
|
|
{% endhighlight %}
|
|
|
|
|
|
When address verification is used, the establishment sequence is as follows:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight %}
|
|
Alice Bob
|
|
|
|
SessionRequest ------------------->
|
|
<--------------------------- Retry
|
|
SessionRequest ------------------->
|
|
<------------------- SessionCreated
|
|
SessionConfirmed ----------------->
|
|
{% endhighlight %}
|
|
|
|
Using Noise terminology, the establishment and data sequence is as follows:
|
|
(Payload Security Properties)
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='text' %}
|
|
XK(s, rs): Authentication Confidentiality
|
|
<- s
|
|
...
|
|
-> e, es 0 2
|
|
<- e, ee 2 1
|
|
-> s, se 2 5
|
|
<- 2 5
|
|
{% endhighlight %}
|
|
|
|
|
|
Once a session has been established, Alice and Bob can exchange Data messages.
|
|
|
|
Some notations::
|
|
|
|
- RH_A = Router Hash for Alice (32 bytes)
|
|
- RH_B = Router Hash for Bob (32 bytes)
|
|
|
|
|
|
Packet Header
|
|
---------------
|
|
|
|
All packets start with an obfuscated header.
|
|
There are two header types, long and short.
|
|
|
|
Long Header
|
|
`````````````
|
|
The long header is 32 bytes. It is used before a session is created, for SessionRequest, SessionCreated, and Retry.
|
|
Note that the first 9 bytes (Destination Connection ID and type) are the same for both headers.
|
|
|
|
Before header obfuscation and protection:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
|
|
+----+----+----+----+----+----+----+----+
|
|
| Destination Connection ID |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Packet Number |type| ver| id |flag|
|
|
+----+----+----+----+----+----+----+----+
|
|
| Source Connection ID |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Token |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
Destination Connection ID :: 8 bytes, unsigned big endian integer
|
|
|
|
type :: The message type, 0-255
|
|
|
|
ver :: The protocol version, equal to 2
|
|
|
|
id :: 1 byte, the network ID (currently 2, except for test networks)
|
|
|
|
flag :: 1 byte, unused, set to 0 for future compatibility
|
|
|
|
Packet Number :: 4 bytes, unsigned big endian integer
|
|
|
|
Source Connection ID :: 8 bytes, unsigned big endian integer
|
|
|
|
Token :: 8 bytes, unsigned big endian integer
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
Short Header
|
|
`````````````
|
|
The short header is 16 bytes. It is used after a session is created, for Data messages.
|
|
or (maybe?) for unauthenticated messages.
|
|
|
|
16 bytes is required, because
|
|
the receiver must decrypt the first 16 bytes to get the message type,
|
|
and then must decrypt an additional 16 bytes if it's actually a long header,
|
|
as indicated by the message type.
|
|
|
|
Before header obfuscation and protection:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
|
|
+----+----+----+----+----+----+----+----+
|
|
| Destination Connection ID |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Packet Number |type| flags |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
Destination Connection ID :: 8 bytes, unsigned big endian integer
|
|
|
|
Packet Number :: 4 bytes, unsigned big endian integer
|
|
|
|
type :: The message type, 0-10
|
|
|
|
flags :: 3 bytes, unused, set to 0 for future compatibility
|
|
|
|
{% endhighlight %}
|
|
|
|
Note: If any out-of-session relay or peer test messages are defined
|
|
and used, we must also have the ver and id fields present.
|
|
|
|
|
|
|
|
|
|
Connection ID Numbering
|
|
```````````````````````````
|
|
|
|
Random numbers
|
|
|
|
TBD change during handshake like QUIC?
|
|
|
|
|
|
|
|
Packet Numbering
|
|
`````````````````
|
|
Packets are numbered within a single session, for each direction, starting from 0, to a max of (2**32 -1).
|
|
A session must be terminated, and a new session created, well before the max
|
|
number of packets is sent.
|
|
|
|
TODO key rotation, reduce max packet number?
|
|
|
|
Packets that are determined to be lost are not retransmitted
|
|
whole. The same applies to the blocks that are contained within lost
|
|
packets. Instead, the information that might be carried in blocks is
|
|
sent again in new packets as needed.
|
|
|
|
New packets are used to carry information that is
|
|
determined to have been lost. In general, information is sent again
|
|
when a packet containing that information is determined to be lost,
|
|
and sending ceases when a packet containing that information is remain the same)
|
|
acknowledged.
|
|
|
|
Packets are never retransmitted with the same packet number.
|
|
Any retransmission of packet contents (whether or not the contents remain the same)
|
|
must use the next unused packet number.
|
|
|
|
Packet numbering starts with Session Request. Assuming no retransmissions
|
|
in the handshake, and no Retry reply from Bob, the packet numbers
|
|
in an example standard handshake will be:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight %}
|
|
Alice Bob
|
|
|
|
SessionRequest (0) ------------>
|
|
<------------- SessionCreated (0)
|
|
SessionConfirmed (1) ------------>
|
|
Data (2) ------------>
|
|
<------------- Data (1)
|
|
Data (3) ------------>
|
|
Data (4) ------------>
|
|
Data (5) ------------>
|
|
<------------- Data (2)
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
Any retransmission of handshake messages
|
|
(SessionRequest, SessionCreated, or SessionConfirmed)
|
|
must be resent unchanged, except for incrementing the packet number.
|
|
Do not use different ephemeral keys or change the payload
|
|
when retransmitting these messages.
|
|
|
|
|
|
Header Binding
|
|
````````````````
|
|
The header (before obfuscation and protection) is always included in the associated
|
|
data for the AEAD function, to cryptographically bind the header to the data.
|
|
|
|
|
|
Header Obfuscation
|
|
```````````````````
|
|
Both the long and short headers are always obfuscated with AES-CBC using
|
|
(generally) the destination router hash and IV.
|
|
|
|
For SessionCreated, where the destination router hash and IV are not yet known,
|
|
the source router hash and IV are used.
|
|
|
|
TODO ChaCha20 instead?
|
|
|
|
|
|
|
|
Header Protection
|
|
```````````````````
|
|
In addition to obfuscation, bytes 8-15 of the long header and bytes 8-12 of the short header
|
|
are encrypted by XORing with a known key, as in QUIC [RFC-9001]_ and [Nonces]_.
|
|
|
|
For SessionCreated, where the destination router hash and IV are not yet known,
|
|
the source router hash and IV are used.
|
|
|
|
There are four header protection key phases:
|
|
|
|
- Session Request
|
|
- Session Created and Retry
|
|
- Session Confirmed
|
|
- Data Phase
|
|
|
|
See the individual KDF sections below for the derivation of the header protection key for that phase.
|
|
|
|
Header Protection KDF:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
// incoming encrypted packet
|
|
len = packet.length
|
|
// take the last 16 bytes before the MAC
|
|
sample = packet[len-32:len-17]
|
|
n = sample[4:15]
|
|
key = header protection key
|
|
data = {0, 0, 0, 0, 0, 0, 0, 0}
|
|
mask = ChaCha20.encrypt(key, n, data)
|
|
|
|
// encrypt the header by XORing with the mask
|
|
// short header
|
|
header[8:12] ^= mask[0:4]
|
|
// long header
|
|
header[8:15] ^= mask[0:7]
|
|
|
|
|
|
{% endhighlight %}
|
|
|
|
Header Validation
|
|
```````````````````
|
|
After decrypting the first 16 bytes of the header,
|
|
the receiver will know the Destination Session ID. From there,
|
|
the receiver knows what header protection keys to use based on the key phase of the session.
|
|
|
|
Removing the header protection will then reveal the message type and be able to determine
|
|
if it is a short or long header.
|
|
If it is a long header, the receiver must validate the version and netid fields.
|
|
If the version is != 2, or the netid is != the expected value (generally 2, except in test networks),
|
|
the receiver should drop the message.
|
|
|
|
In limited situations (after sending a Session Request but before receiving a Session Created),
|
|
the receiver should retry header protection with a different key, to check for a Retry message.
|
|
|
|
|
|
Authenticated Encryption
|
|
------------------------
|
|
|
|
There are three separate authenticated encryption instances (CipherStates).
|
|
One during the handshake phase, and two (transmit and receive) for the data phase.
|
|
Each has its own key from a KDF.
|
|
|
|
Encrypted/authenticated data will be represented as
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ +
|
|
| Encrypted and authenticated data |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
{% endhighlight %}
|
|
|
|
|
|
ChaCha20/Poly1305
|
|
`````````````````
|
|
|
|
Encrypted and authenticated data format.
|
|
|
|
Inputs to the encryption/decryption functions:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
|
|
k :: 32 byte cipher key, as generated from KDF
|
|
|
|
nonce :: Counter-based nonce, 12 bytes.
|
|
Starts at 0 and incremented for each message.
|
|
First four bytes are always zero.
|
|
Last eight bytes are the counter, little-endian encoded.
|
|
Maximum value is 2**64 - 2.
|
|
Connection must be dropped and restarted after
|
|
it reaches that value.
|
|
The value 2**64 - 1 must never be sent.
|
|
|
|
ad :: In handshake phase:
|
|
Associated data, 32 bytes.
|
|
The SHA256 hash of all preceding data.
|
|
In data phase:
|
|
The packet header
|
|
|
|
data :: Plaintext data, 0 or more bytes
|
|
|
|
{% endhighlight %}
|
|
|
|
Output of the encryption function, input to the decryption function:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ +
|
|
| ChaCha20 encrypted data |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Poly1305 Message Authentication Code |
|
|
+ (MAC) +
|
|
| 16 bytes |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
encrypted data :: Same size as plaintext data, 0 - 65519 bytes
|
|
|
|
MAC :: Poly1305 message authentication code, 16 bytes
|
|
|
|
{% endhighlight %}
|
|
|
|
For ChaCha20, what is described here corresponds to [RFC-7539]_, which is also
|
|
used similarly in TLS [RFC-7905]_.
|
|
|
|
Notes
|
|
`````
|
|
- Since ChaCha20 is a stream cipher, plaintexts need not be padded.
|
|
Additional keystream bytes are discarded.
|
|
|
|
- The key for the cipher (256 bits) is agreed upon by means of the SHA256 KDF.
|
|
The details of the KDF for each message are in separate sections below.
|
|
|
|
|
|
AEAD Error Handling
|
|
```````````````````
|
|
- In all messages, the AEAD message size is known in advance.
|
|
On an AEAD authentication failure, recipient must halt further message processing and
|
|
discard the message.
|
|
|
|
- Bob should maintain a blacklist of IPs with
|
|
repeated failures.
|
|
|
|
|
|
KDF for Session Request
|
|
-------------------------------------------------------
|
|
|
|
The Key Derivation Function (KDF) generates a handshake phase cipher key k from the DH result,
|
|
using HMAC-SHA256(key, data) as defined in [RFC-2104]_.
|
|
These are the InitializeSymmetric(), MixHash(), and MixKey() functions,
|
|
exactly as defined in the Noise spec.
|
|
|
|
KDF for Initial ChainKey
|
|
````````````````````````
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='text' %}
|
|
|
|
// Define protocol_name.
|
|
Set protocol_name = "Noise_XKaesobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256"
|
|
(52 bytes, US-ASCII encoded, no NULL termination).
|
|
|
|
// Define Hash h = 32 bytes
|
|
h = SHA256(protocol_name);
|
|
|
|
Define ck = 32 byte chaining key. Copy the h data to ck.
|
|
Set ck = h
|
|
|
|
Define rs = Bob's 32-byte static key as published in the RouterInfo
|
|
|
|
// MixHash(null prologue)
|
|
h = SHA256(h);
|
|
|
|
// up until here, can all be precalculated by Alice for all outgoing connections
|
|
|
|
// Bob's X25519 static keys
|
|
// bpk is published in routerinfo
|
|
bsk = GENERATE_PRIVATE()
|
|
bpk = DERIVE_PUBLIC(bsk)
|
|
|
|
// Bob static key
|
|
// MixHash(bpk)
|
|
// || below means append
|
|
h = SHA256(h || bpk);
|
|
|
|
// up until here, can all be precalculated by Bob for all incoming connections
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
KDF for Session Request
|
|
`````````````````````````
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='text' %}
|
|
This is the "e" message pattern:
|
|
|
|
// Alice's X25519 ephemeral keys
|
|
aesk = GENERATE_PRIVATE()
|
|
aepk = DERIVE_PUBLIC(aesk)
|
|
|
|
// Alice ephemeral key X
|
|
// MixHash(aepk)
|
|
h = SHA256(h || aepk);
|
|
|
|
// h is used as the associated data for the AEAD in Session Request
|
|
// Retain the Hash h for the Session Created KDF
|
|
|
|
|
|
End of "e" message pattern.
|
|
|
|
This is the "es" message pattern:
|
|
|
|
// DH(e, rs) == DH(s, re)
|
|
sharedSecret = DH(aesk, bpk) = DH(bsk, aepk)
|
|
|
|
// MixKey(DH())
|
|
//[chainKey, k] = MixKey(sharedSecret)
|
|
// ChaChaPoly parameters to encrypt/decrypt
|
|
keydata = HKDF(chainKey, sharedSecret, "", 64)
|
|
chainKey = keydata[0:31]
|
|
|
|
// AEAD parameters
|
|
k = keydata[32:64]
|
|
n = 0
|
|
ad = h
|
|
ciphertext = ENCRYPT(k, n, payload, ad)
|
|
|
|
// retain the chainKey for Session Created KDF
|
|
|
|
|
|
End of "es" message pattern.
|
|
|
|
// Header protection key
|
|
TBD
|
|
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
|
|
|
|
SessionRequest (Type 0)
|
|
------------------------
|
|
|
|
Alice sends to Bob.
|
|
|
|
Long header.
|
|
Noise content: Alice's ephemeral key X
|
|
Noise payload: datetime and padding blocks
|
|
Max payload size: MTU - 108 (IPv4) or MTU - 128 (IPv6)
|
|
For 1280 MTU: Max payload is 1172 (IPv4) or 1152 (IPv6)
|
|
For 1500 MTU: Max payload is 1392 (IPv4) or 1372 (IPv6)
|
|
|
|
Payload Security Properties:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='text' %}
|
|
XK(s, rs): Authentication Confidentiality
|
|
-> e, es 0 2
|
|
|
|
Authentication: None (0).
|
|
This payload may have been sent by any party, including an active attacker.
|
|
|
|
Confidentiality: 2.
|
|
Encryption to a known recipient, forward secrecy for sender compromise
|
|
only, vulnerable to replay. This payload is encrypted based only on DHs
|
|
involving the recipient's static key pair. If the recipient's static
|
|
private key is compromised, even at a later date, this payload can be
|
|
decrypted. This message can also be replayed, since there's no ephemeral
|
|
contribution from the recipient.
|
|
|
|
"e": Alice generates a new ephemeral key pair and stores it in the e
|
|
variable, writes the ephemeral public key as cleartext into the
|
|
message buffer, and hashes the public key along with the old h to
|
|
derive a new h.
|
|
|
|
"es": A DH is performed between the Alice's ephemeral key pair and the
|
|
Bob's static key pair. The result is hashed along with the old ck to
|
|
derive a new ck and k, and n is set to zero.
|
|
|
|
|
|
{% endhighlight %}
|
|
|
|
The X value is encrypted to ensure payload indistinguishably
|
|
and uniqueness, which are necessary DPI countermeasures.
|
|
We use AES encryption to achieve this,
|
|
rather than more complex and slower alternatives such as elligator2.
|
|
Asymmetric encryption to Bob's router public key would be far too slow.
|
|
AES encryption uses Bob's router hash as the key and Bob's IV as published
|
|
in the network database.
|
|
|
|
AES encryption is for DPI resistance only.
|
|
Any party knowing Bob's router hash, and IV, which are published in the network database,
|
|
may decrypt the X value in this message.
|
|
|
|
|
|
Raw contents:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ obfuscated with RH_B +
|
|
| AES-CBC-256 encrypted |
|
|
+ bytes 8-15 header protected +
|
|
| Long Header |
|
|
+ (32 bytes) +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ obfuscated with RH_B +
|
|
| AES-CBC-256 encrypted X |
|
|
+ (32 bytes) +
|
|
| |
|
|
+ +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ +
|
|
| ChaCha20 encrypted data |
|
|
+ (length varies) +
|
|
| k defined in KDF for Session Request |
|
|
+ n = 0 +
|
|
| see KDF for associated data |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ Poly1305 MAC (16 bytes) +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
X :: 32 bytes, AES-256-CBC encrypted X25519 ephemeral key, little endian
|
|
key: RH_B
|
|
iv: As published in Bobs network database entry
|
|
|
|
{% endhighlight %}
|
|
|
|
Unencrypted data (Poly1305 authentication tag not shown):
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| Destination Connection ID |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Packet Number |type| ver| id |flag|
|
|
+----+----+----+----+----+----+----+----+
|
|
| Source Connection ID |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Token |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ +
|
|
| X |
|
|
+ (32 bytes) +
|
|
| |
|
|
+ +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Noise payload (block data) |
|
|
+ (length varies) +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
|
|
Destination Connection ID :: Randomly generated by Alice
|
|
|
|
id :: 1 byte, the network ID (currently 2, except for test networks)
|
|
|
|
ver :: 2
|
|
|
|
type :: 0
|
|
|
|
flag :: 1 byte, unused, set to 0 for future compatibility
|
|
|
|
Packet Number :: 0 unless retransmitted or resent after Retry
|
|
|
|
Source Connection ID :: Randomly generated by Alice
|
|
|
|
Token :: 0 if not previously received from Bob
|
|
|
|
X :: 32 bytes, X25519 ephemeral key, little endian
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
Notes
|
|
`````
|
|
- When the published address is "NTCP", Bob supports both NTCP and SSU2 on the
|
|
same port. For compatibility, when initiating a connection to an address
|
|
published as "NTCP", Alice must limit the maximum size of this message,
|
|
including padding, to 287 bytes or less. This facilitates automatic protocol
|
|
identification by Bob. When published as "SSU2", there is no size
|
|
restriction. See the Published Addresses and Version Detection sections
|
|
below.
|
|
|
|
- The unique X value in the initial AES block ensure that the ciphertext is
|
|
different for every session.
|
|
|
|
- Bob must reject connections where the timestamp value is too far off from the
|
|
current time. Call the maximum delta time "D". Bob must maintain a local
|
|
cache of previously-used handshake values and reject duplicates, to prevent
|
|
replay attacks. Values in the cache must have a lifetime of at least 2*D.
|
|
The cache values are implementation-dependent, however the 32-byte X value
|
|
(or its encrypted equivalent) may be used.
|
|
|
|
- Diffie-Hellman ephemeral keys may never be reused, to prevent cryptographic attacks,
|
|
and reuse will be rejected as a replay attack.
|
|
|
|
- The "KE" and "auth" options must be compatible, i.e. the shared secret K must
|
|
be of the appropriate size. If more "auth" options are added, this could
|
|
implicitly change the meaning of the "KE" flag to use a different KDF or a
|
|
different truncation size.
|
|
|
|
- Bob must validate that Alice's ephemeral key is a valid point on the curve
|
|
here.
|
|
|
|
- Padding should be limited to a reasonable amount. Bob may reject connections
|
|
with excessive padding. Bob will specify his padding options in Session Created.
|
|
Min/max guidelines TBD. Random size from 0 to 31 bytes minimum?
|
|
(Distribution to be determined, see Appendix A.)
|
|
TODO UNLESS minimum packet size is enforced for PMTU.
|
|
|
|
- On any error, including AEAD, DH, timestamp, apparent replay, or key
|
|
validation failure, Bob must halt further message processing and
|
|
drop the message without responding.
|
|
|
|
- DoS Mitigation: DH is a relatively expensive operation. As with the previous NTCP protocol,
|
|
routers should take all necessary measures to prevent CPU or connection exhaustion.
|
|
Place limits on maximum active connections and maximum connection setups in progress.
|
|
Enforce read timeouts (both per-read and total for "slowloris").
|
|
Limit repeated or simultaneous connections from the same source.
|
|
Maintain blacklists for sources that repeatedly fail.
|
|
Do not respond to AEAD failure.
|
|
|
|
- "ver" field: The overall Noise protocol, extensions, and SSU2 protocol
|
|
including payload specifications, indicating SSU2.
|
|
This field may be used to indicate support for future changes.
|
|
|
|
- Bob must fail the connection if any incoming data remains after validating
|
|
Session Request and reading in the padding. There should be no extra data from Alice,
|
|
as Bob has not responded with Session Created yet.
|
|
|
|
- The network ID field is used to quickly identify cross-network connections.
|
|
If this field is nonzero, and does not match Bob's network ID,
|
|
Bob should disconnect and block future connections.
|
|
|
|
|
|
|
|
KDF for Session Created and Session Confirmed part 1
|
|
----------------------------------------------------------------------------------
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='text' %}
|
|
|
|
// take h saved from Session Request KDF
|
|
// MixHash(ciphertext)
|
|
h = SHA256(h || 32 byte encrypted payload from Session Request)
|
|
|
|
// MixHash(header)
|
|
h = SHA256(h || header)
|
|
|
|
This is the "e" message pattern:
|
|
|
|
// Bob's X25519 ephemeral keys
|
|
besk = GENERATE_PRIVATE()
|
|
bepk = DERIVE_PUBLIC(besk)
|
|
|
|
// h is from KDF for Session Request
|
|
// Bob ephemeral key Y
|
|
// MixHash(bepk)
|
|
h = SHA256(h || bepk);
|
|
|
|
// h is used as the associated data for the AEAD in Session Created
|
|
// Retain the Hash h for the Session Confirmed KDF
|
|
|
|
End of "e" message pattern.
|
|
|
|
This is the "ee" message pattern:
|
|
|
|
// MixKey(DH())
|
|
//[chainKey, k] = MixKey(sharedSecret)
|
|
sharedSecret = DH(aesk, bepk) = DH(besk, aepk)
|
|
keydata = HKDF(chainKey, sharedSecret, "", 64)
|
|
chainKey = keydata[0:31]
|
|
|
|
// AEAD parameters
|
|
k = keydata[32:64]
|
|
n = 0
|
|
ad = h
|
|
ciphertext = ENCRYPT(k, n, payload, ad)
|
|
|
|
// retain the chaining key ck for Session Confirmed KDF
|
|
|
|
End of "ee" message pattern.
|
|
|
|
// Header protection key
|
|
TBD
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
SessionCreated (Type 1)
|
|
------------------------
|
|
|
|
Bob sends to Alice.
|
|
|
|
Noise content: Bob's ephemeral key Y
|
|
Noise payload: datetime, options, and padding blocks
|
|
Max payload size: MTU - 108 (IPv4) or MTU - 128 (IPv6)
|
|
For 1280 MTU: Max payload is 1172 (IPv4) or 1152 (IPv6)
|
|
For 1500 MTU: Max payload is 1392 (IPv4) or 1372 (IPv6)
|
|
|
|
Payload Security Properties:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='text' %}
|
|
XK(s, rs): Authentication Confidentiality
|
|
<- e, ee 2 1
|
|
|
|
Authentication: 2.
|
|
Sender authentication resistant to key-compromise impersonation (KCI).
|
|
The sender authentication is based on an ephemeral-static DH ("es" or "se")
|
|
between the sender's static key pair and the recipient's ephemeral key pair.
|
|
Assuming the corresponding private keys are secure, this authentication cannot be forged.
|
|
|
|
Confidentiality: 1.
|
|
Encryption to an ephemeral recipient.
|
|
This payload has forward secrecy, since encryption involves an ephemeral-ephemeral DH ("ee").
|
|
However, the sender has not authenticated the recipient,
|
|
so this payload might be sent to any party, including an active attacker.
|
|
|
|
|
|
"e": Bob generates a new ephemeral key pair and stores it in the e variable,
|
|
writes the ephemeral public key as cleartext into the message buffer,
|
|
and hashes the public key along with the old h to derive a new h.
|
|
|
|
"ee": A DH is performed between the Bob's ephemeral key pair and the Alice's ephemeral key pair.
|
|
The result is hashed along with the old ck to derive a new ck and k, and n is set to zero.
|
|
|
|
{% endhighlight %}
|
|
|
|
The Y value is encrypted to ensure payload indistinguishably and uniqueness,
|
|
which are necessary DPI countermeasures. We use AES encryption to achieve
|
|
this, rather than more complex and slower alternatives such as elligator2.
|
|
Asymmetric encryption to Alice's router public key would be far too slow. AES
|
|
encryption uses Bob's router hash as the key and the AES state from Session Request
|
|
(which was initialized with Bob's IV as published in the network database).
|
|
|
|
AES encryption is for DPI resistance only. Any party knowing Bob's router hash
|
|
and IV, which are published in the network database, and captured the first 32
|
|
bytes of Session Request, may decrypt the Y value in this message.
|
|
|
|
|
|
Raw contents:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ obfuscated with RH_B +
|
|
| AES-CBC-256 encrypted |
|
|
+ bytes 8-15 header protected +
|
|
| Long Header |
|
|
+ (32 bytes) +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ obfuscated with RH_B +
|
|
| AES-CBC-256 encrypted Y |
|
|
+ (32 bytes) +
|
|
| |
|
|
+ +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| ChaCha20 data |
|
|
+ Encrypted and authenticated data +
|
|
| length varies |
|
|
+ k defined in KDF for Session Created +
|
|
| n = 0; see KDF for associated data |
|
|
+ +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ Poly1305 MAC (16 bytes) +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
Y :: 32 bytes, AES-256-CBC encrypted X25519 ephemeral key, little endian
|
|
key: RH_B
|
|
iv: Using AES state from Session Request
|
|
|
|
{% endhighlight %}
|
|
|
|
Unencrypted data (Poly1305 auth tag not shown):
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| Destination Connection ID |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Packet Number |type| ver| id |flag|
|
|
+----+----+----+----+----+----+----+----+
|
|
| Source Connection ID |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Token |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ +
|
|
| Y |
|
|
+ (32 bytes) +
|
|
| |
|
|
+ +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Noise payload (block data) |
|
|
+ (length varies) +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
Destination Connection ID :: As sent by Alice
|
|
|
|
id :: 1 byte, the network ID (currently 2, except for test networks)
|
|
|
|
ver :: 2
|
|
|
|
type :: 0
|
|
|
|
flag :: 1 byte, unused, set to 0 for future compatibility
|
|
|
|
Packet Number :: 0 unless retransmitted or resent after Retry
|
|
|
|
Source Connection ID :: Randomly generated by Alice
|
|
|
|
Token :: 0 (unused)
|
|
|
|
Y :: 32 bytes, X25519 ephemeral key, little endian
|
|
|
|
{% endhighlight %}
|
|
|
|
Notes
|
|
`````
|
|
|
|
- Alice must validate that Bob's ephemeral key is a valid point on the curve
|
|
here.
|
|
|
|
- Padding should be limited to a reasonable amount.
|
|
Alice may reject connections with excessive padding.
|
|
Alice will specify her padding options in Session Confirmed.
|
|
Min/max guidelines TBD. Random size from 0 to 31 bytes minimum?
|
|
(Distribution to be determined, see Appendix A.)
|
|
TODO UNLESS minimum packet size is enforced for PMTU.
|
|
|
|
- On any error, including AEAD, DH, timestamp, apparent replay, or key
|
|
validation failure, Alice must halt further message processing and close the
|
|
connection without responding.
|
|
|
|
- Alice must fail the connection if any incoming data remains after validating
|
|
Session Created and reading in the padding. There should be no extra data from Bob,
|
|
as Alice has not responded with Session Confirmed yet.
|
|
|
|
- Alice must reject connections where the timestamp value is too far off from
|
|
the current time. Call the maximum delta time "D". Alice must maintain a
|
|
local cache of previously-used handshake values and reject duplicates, to
|
|
prevent replay attacks. Values in the cache must have a lifetime of at least
|
|
2*D. The cache values are implementation-dependent, however the 32-byte Y
|
|
value (or its encrypted equivalent) may be used.
|
|
|
|
Issues
|
|
``````
|
|
- Include min/max padding options here?
|
|
|
|
|
|
|
|
KDF for Session Confirmed part 1, using Session Created KDF
|
|
---------------------------------------------------------------------------
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='text' %}
|
|
|
|
// take h saved from Session Created KDF
|
|
// MixHash(ciphertext)
|
|
h = SHA256(h || 24 byte encrypted payload from Session Created)
|
|
|
|
// MixHash(header)
|
|
h = SHA256(h || header)
|
|
// h is used as the associated data for the AEAD in Session Confirmed part 1, below
|
|
|
|
This is the "s" message pattern:
|
|
|
|
// Alice's X25519 static keys
|
|
ask = GENERATE_PRIVATE()
|
|
apk = DERIVE_PUBLIC(ask)
|
|
|
|
// AEAD parameters
|
|
// k is from Session Request
|
|
n = 1
|
|
ad = h
|
|
ciphertext = ENCRYPT(k, n++, apk, ad)
|
|
|
|
// MixHash(ciphertext)
|
|
h = SHA256(h || ciphertext);
|
|
|
|
// h is used as the associated data for the AEAD in Session Confirmed part 2
|
|
|
|
End of "s" message pattern.
|
|
|
|
// Header protection key
|
|
TBD
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
KDF for Session Confirmed part 2
|
|
--------------------------------------------------------------
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='text' %}
|
|
|
|
This is the "se" message pattern:
|
|
|
|
// DH(ask, bepk) == DH(besk, apk)
|
|
sharedSecret = DH(ask, bepk) = DH(besk, apk)
|
|
|
|
// MixKey(DH())
|
|
//[chainKey, k] = MixKey(sharedSecret)
|
|
keydata = HKDF(chainKey, sharedSecret, "", 64)
|
|
chainKey = keydata[0:31]
|
|
|
|
// AEAD parameters
|
|
k = keydata[32:64]
|
|
n = 0
|
|
ad = h
|
|
ciphertext = ENCRYPT(k, n, payload, ad)
|
|
|
|
// h from Session Confirmed part 1 is used as the associated data for the AEAD in Session Confirmed part 2
|
|
// MixHash(ciphertext)
|
|
h = SHA256(h || ciphertext);
|
|
|
|
// retain the chaining key ck for the data phase KDF
|
|
// retain the hash h for the data phase Additional Symmetric Key (SipHash) KDF
|
|
|
|
End of "se" message pattern.
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
SessionConfirmed (Type 2)
|
|
-----------------------------
|
|
|
|
Alice sends to Bob.
|
|
|
|
Noise content: Alice's static key
|
|
Noise payload part 1: None
|
|
Noise payload part 2: Alice's RouterInfo, options, data, and padding blocks
|
|
Max payload size: MTU - 108 (IPv4) or MTU - 128 (IPv6)
|
|
For 1280 MTU: Max payload is 1172 (IPv4) or 1152 (IPv6)
|
|
For 1500 MTU: Max payload is 1392 (IPv4) or 1372 (IPv6)
|
|
|
|
Payload Security Properties:
|
|
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='text' %}
|
|
XK(s, rs): Authentication Confidentiality
|
|
-> s, se 2 5
|
|
|
|
Authentication: 2.
|
|
Sender authentication resistant to key-compromise impersonation (KCI). The
|
|
sender authentication is based on an ephemeral-static DH ("es" or "se")
|
|
between the sender's static key pair and the recipient's ephemeral key
|
|
pair. Assuming the corresponding private keys are secure, this
|
|
authentication cannot be forged.
|
|
|
|
Confidentiality: 5.
|
|
Encryption to a known recipient, strong forward secrecy. This payload is
|
|
encrypted based on an ephemeral-ephemeral DH as well as an ephemeral-static
|
|
DH with the recipient's static key pair. Assuming the ephemeral private
|
|
keys are secure, and the recipient is not being actively impersonated by an
|
|
attacker that has stolen its static private key, this payload cannot be
|
|
decrypted.
|
|
|
|
"s": Alice writes her static public key from the s variable into the
|
|
message buffer, encrypting it, and hashes the output along with the old h
|
|
to derive a new h.
|
|
|
|
"se": A DH is performed between the Alice's static key pair and the Bob's
|
|
ephemeral key pair. The result is hashed along with the old ck to derive a
|
|
new ck and k, and n is set to zero.
|
|
|
|
{% endhighlight %}
|
|
|
|
This contains two ChaChaPoly frames.
|
|
The first is Alice's encrypted static public key.
|
|
The second is the Noise payload: Alice's encrypted RouterInfo, optional
|
|
options, and optional padding. They use different keys, because the MixKey()
|
|
function is called in between.
|
|
|
|
|
|
Raw contents:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
|Short Header obfuscated with dest hash |
|
|
+ encrypted, bytes 8-15 +
|
|
| header protected |
|
|
+----+----+----+----+----+----+----+----+
|
|
| ChaCha20 frame (32 bytes) |
|
|
+ Encrypted and authenticated data +
|
|
+ Alice static key S +
|
|
| k defined in KDF for Session Created |
|
|
+ n = 1 +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ Poly1305 MAC (16 bytes) +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ Length varies (remainder of packet) +
|
|
| |
|
|
+ ChaChaPoly frame +
|
|
| Encrypted and authenticated |
|
|
+ +
|
|
| Alice RouterInfo |
|
|
+ using block format 2 +
|
|
| Alice Options (optional) |
|
|
+ using block format 1 +
|
|
| Arbitrary padding |
|
|
+ using block format 254 +
|
|
| |
|
|
+ +
|
|
| k defined in KDF for |
|
|
+ Session Confirmed part 2 +
|
|
| n = 0 |
|
|
+ see KDF for associated data +
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ Poly1305 MAC (16 bytes) +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
S :: 32 bytes, ChaChaPoly encrypted Alice's X25519 static key, little endian
|
|
inside 48 byte ChaChaPoly frame
|
|
|
|
{% endhighlight %}
|
|
|
|
Unencrypted data (Poly1305 auth tags not shown):
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| Destination Connection ID |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Packet Number |type| flags |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ +
|
|
| S |
|
|
+ Alice static key +
|
|
| (32 bytes) |
|
|
+ +
|
|
| |
|
|
+ +
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ +
|
|
| Noise Payload |
|
|
+ (length varies) +
|
|
| |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
Destination Connection ID :: As sent in Session Request,
|
|
or one received in Session Confirmed?
|
|
|
|
Packet Number :: 1 unless retransmitted or resent after Retry
|
|
|
|
type :: 2
|
|
|
|
flags :: 3 bytes, unused, set to 0 for future compatibility
|
|
|
|
S :: 32 bytes, Alice's X25519 static key, little endian
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
Notes
|
|
`````
|
|
- Bob must perform the usual Router Info validation.
|
|
Ensure the signature type is supported, verify the signature,
|
|
verify the timestamp is within bounds, and any other checks necessary.
|
|
See below for notes on handling fragmented Router Infos.
|
|
|
|
- Bob must verify that Alice's static key received in the first frame matches
|
|
the static key in the Router Info. Bob must first search the Router Info for
|
|
a NTCP or SSU2 Router Address with a matching version (v) option.
|
|
See Published Router Info and Unpublished Router Info sections below.
|
|
See below for notes on handling fragmented Router Infos.
|
|
|
|
- If Bob has an older version of Alice's RouterInfo in his netdb, verify
|
|
that the static key in the router info is the same in both, if present,
|
|
and if the older version is less than XXX old (see key rotate time below)
|
|
|
|
- Bob must validate that Alice's static key is a valid point on the curve here.
|
|
|
|
- Options should be included, to specify padding parameters.
|
|
|
|
- On any error, including AEAD, RI, DH, timestamp, or key validation failure,
|
|
Bob must halt further message processing and close the connection without
|
|
responding.
|
|
|
|
- Message 3 part 2 frame content: This format of this frame is the same as the
|
|
format of data phase frames, except that the length of the frame is sent
|
|
by Alice in Session Request. See below for the data phase frame format.
|
|
The frame must contain 1 to 4 blocks in the following order:
|
|
1) Alice's Router Info block (required)
|
|
2) Options block (optional)
|
|
3) I2NP blocks (optional)
|
|
4) Padding block (optional)
|
|
This frame must never contain any other block type.
|
|
TODO: what about relay and peer test?
|
|
|
|
- Message 3 part 2 padding block is recommended.
|
|
|
|
- There may be no space, or only a small amount of space, available for
|
|
I2NP blocks, depending on the MTU and the Router Info size.
|
|
Do NOT include I2NP blocks if the Router Info is fragmented.
|
|
The simplest implementation may be to never include I2NP blocks in
|
|
the Session Confirmed message, and send all I2NP blocks in
|
|
subsequent Data messages.
|
|
|
|
|
|
KDF for data phase
|
|
----------------------------------------------
|
|
|
|
The data phase uses the header for associated data.
|
|
|
|
The KDF generates two cipher keys k_ab and k_ba from the chaining key ck,
|
|
using HMAC-SHA256(key, data) as defined in [RFC-2104]_.
|
|
This is the split() function, exactly as defined in the Noise spec.
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='text' %}
|
|
// split()
|
|
// chainKey = from handshake phase
|
|
keydata = HKDF(chainKey, ZEROLEN, "", 64)
|
|
k_ab = keydata[0:31]
|
|
k_ba = keydata[32:63]
|
|
|
|
// key is k_ab for Alice to Bob
|
|
// key is k_ba for Bob to Alice
|
|
|
|
// AEAD parameters
|
|
k = k_ab or k_ba
|
|
n = packet number from header
|
|
ad = header
|
|
ciphertext = ENCRYPT(k, n, payload, ad)
|
|
|
|
// Header protection keys
|
|
TBD
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
|
|
|
|
Relay Messages (Types 3-5)
|
|
------------------------------
|
|
|
|
TBD, only required if these must be sent outside of an existing session.
|
|
|
|
|
|
|
|
Data Message (Type 6)
|
|
---------------------------
|
|
|
|
Noise payload: All block types are allowed
|
|
Max payload size: MTU - 60 (IPv4) or MTU - 80 (IPv6)
|
|
For 1500 MTU: Max payload is 1440 (IPv4) or 1420 (IPv6)
|
|
|
|
Starting with the 2nd part of Session Confirmed, all messages are inside
|
|
an authenticated and encrypted ChaChaPoly payload.
|
|
with a prepended two-byte obfuscated length.
|
|
All padding is inside the frame.
|
|
Inside the payload is a standard format with zero or more "blocks".
|
|
Each block has a one-byte type and a two-byte length.
|
|
Types include date/time, I2NP message, options, termination, and padding.
|
|
|
|
Note: Bob may, but is not required, to send his RouterInfo to Alice as
|
|
his first message to Alice in the data phase.
|
|
|
|
Payload Security Properties:
|
|
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='text' %}
|
|
XK(s, rs): Authentication Confidentiality
|
|
<- 2 5
|
|
-> 2 5
|
|
|
|
Authentication: 2.
|
|
Sender authentication resistant to key-compromise impersonation (KCI).
|
|
The sender authentication is based on an ephemeral-static DH ("es" or "se")
|
|
between the sender's static key pair and the recipient's ephemeral key pair.
|
|
Assuming the corresponding private keys are secure, this authentication cannot be forged.
|
|
|
|
Confidentiality: 5.
|
|
Encryption to a known recipient, strong forward secrecy.
|
|
This payload is encrypted based on an ephemeral-ephemeral DH as well as
|
|
an ephemeral-static DH with the recipient's static key pair.
|
|
Assuming the ephemeral private keys are secure, and the recipient is not being actively impersonated
|
|
by an attacker that has stolen its static private key, this payload cannot be decrypted.
|
|
|
|
{% endhighlight %}
|
|
|
|
Notes
|
|
`````
|
|
- The router must drop a message AEAD error.
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
|Short Header obfuscated with dest hash |
|
|
+ encrypted, bytes 8-15 +
|
|
| header protected |
|
|
+----+----+----+----+----+----+----+----+
|
|
| ChaCha20 data |
|
|
+ Encrypted and authenticated data +
|
|
| length varies |
|
|
+k defined in KDF for Session Confirmed +
|
|
| n = packet number from header |
|
|
+ +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ Poly1305 MAC (16 bytes) +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
{% endhighlight %}
|
|
|
|
Unencrypted data (Poly1305 auth tag not shown):
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| Destination Connection ID |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Packet Number |type| flags |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Noise payload (block data) |
|
|
+ (length varies) +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
Destination Connection ID :: As specified in session setup
|
|
|
|
Packet Number :: 4 byte big endian integer
|
|
|
|
type :: 6
|
|
|
|
flags :: 3 bytes, unused, set to 0 for future compatibility
|
|
|
|
{% endhighlight %}
|
|
|
|
Notes
|
|
`````
|
|
|
|
|
|
Peer Test (Type 7)
|
|
------------------------
|
|
|
|
TBD, only required if these must be sent outside of an existing session.
|
|
|
|
|
|
Session Destroyed (Type 8)
|
|
-------------------------------
|
|
|
|
TBD, only required if these must be sent outside of an existing session.
|
|
|
|
|
|
Retry (Type 9)
|
|
-------------------------------
|
|
|
|
TODO encrypted? to what key?
|
|
|
|
Noise payload: Only padding block
|
|
|
|
Raw contents:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ obfuscated with RH_B +
|
|
| AES-CBC-256 encrypted |
|
|
+ bytes 8-15 header protected +
|
|
| Long Header |
|
|
+ (32 bytes) +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ +
|
|
| ChaCha20 encrypted data |
|
|
+ (length varies) +
|
|
| k defined in KDF for Session Request |
|
|
+ n = 0 +
|
|
| see KDF for associated data |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ Poly1305 MAC (16 bytes) +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
|
|
{% endhighlight %}
|
|
|
|
Unencrypted data (Poly1305 authentication tag not shown):
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| Destination Connection ID |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Packet Number |type| ver| id |flag|
|
|
+----+----+----+----+----+----+----+----+
|
|
| Source Connection ID |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Token |
|
|
+----+----+----+----+----+----+----+----+
|
|
| ChaCha20 payload (block data) |
|
|
+ (length varies) +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
|
|
Destination Connection ID :: As received from Alice in Session Request
|
|
|
|
type :: 9
|
|
|
|
ver :: 2
|
|
|
|
id :: 1 byte, the network ID (currently 2, except for test networks)
|
|
|
|
flag :: 1 byte, unused, set to 0 for future compatibility
|
|
|
|
Packet Number :: 0 unless retransmitted or resent after Retry
|
|
|
|
Source Connection ID :: As received from Alice in Session Request
|
|
|
|
Token :: 8 byte unsigned integer, nonzero
|
|
|
|
{% endhighlight %}
|
|
|
|
Notes
|
|
`````
|
|
This is NOT a standard Noise message and is not part of the handshake.
|
|
It is not bound to the Session Request message other than by connection IDs.
|
|
It is not required to decrypt the Session Request Noise message to create this
|
|
message in response.
|
|
|
|
|
|
Hole Punch Message
|
|
-------------------------------
|
|
|
|
An empty datagram. No content. Same as SSU 1.
|
|
A HolePunch is simply a UDP packet with no data. It is unauthenticated and
|
|
unencrypted. It does not contain a SSU header, so it does not have a message
|
|
type number. It is sent from Charlie to Alice as a part of the Introduction
|
|
sequence.
|
|
|
|
|
|
|
|
Noise Payload
|
|
===============
|
|
|
|
Each Noise payload contains zero or more "blocks".
|
|
|
|
This uses the same block format as defined in the [NTCP2]_ and [ECIES]_ specifications.
|
|
Individual block types are defined differently.
|
|
|
|
There are concerns that encouraging implementers to share code
|
|
may lead to parsing issues. Implementers should carefully consider
|
|
the benefits and risks of sharing code, and ensure that the
|
|
ordering and valid block rules are different for the two contexts.
|
|
|
|
|
|
Payload Format
|
|
----------------
|
|
|
|
There are zero or more blocks in the encrypted payload.
|
|
Each block contains a one-byte identifier, a two-byte length,
|
|
and zero or more bytes of data.
|
|
|
|
For extensibility, receivers must ignore blocks with unknown identifiers,
|
|
and treat them as padding.
|
|
|
|
Encrypted data is 65535 bytes max, including a 16-byte authentication header,
|
|
so the max unencrypted data is 65519 bytes.
|
|
|
|
(Poly1305 auth tag not shown):
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
|blk | size | data |
|
|
+----+----+----+ +
|
|
| |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|blk | size | data |
|
|
+----+----+----+ +
|
|
| |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
~ . . . ~
|
|
|
|
blk :: 1 byte, see below
|
|
size :: 2 bytes, big endian, size of data to follow, 0 - TBD
|
|
data :: the data
|
|
|
|
{% endhighlight %}
|
|
|
|
Maximum ChaChaPoly payload varies based on message type, MTU,
|
|
and IPv4 or IPv6 address type.
|
|
Upper limit is about 1440 bytes for IPv4, 1500 MTU, Data message.
|
|
Maximum total block size is the maximum payload size.
|
|
Maximum single block size is the maximum total block size.
|
|
Block type is 1 byte.
|
|
Block length is 2 bytes.
|
|
Maximum single block data size is the maximum single block size minus 3.
|
|
|
|
Note: Implementers must ensure that when reading a block,
|
|
malformed or malicious data will not cause reads to
|
|
overrun into the next block or beyond the payload boundary.
|
|
|
|
|
|
Block types:
|
|
|
|
==================================== ============= ============
|
|
Payload Block Type Type Number Block Length
|
|
==================================== ============= ============
|
|
DateTime 0 7
|
|
Options (TBD) 1 15+
|
|
Router Info 2 varies
|
|
I2NP Message 3 varies
|
|
First Fragment 4 varies
|
|
Follow-on Fragment 5 varies
|
|
Termination (TBD) 6 9 typ.
|
|
Relay Request 7 TBD
|
|
Relay Response 8 TBD
|
|
Relay Intro 9 TBD
|
|
Peer Test 10 TBD
|
|
Next Nonce 11 TBD
|
|
ACK 12 varies
|
|
Partial ACK 13 varies
|
|
NACK 14 varies
|
|
Relay Tag Request 15 3
|
|
Relay Tag 16 7
|
|
New Token 17 15
|
|
Path Challenge 18 varies
|
|
Path Response 19 varies
|
|
reserved for experimental features 255
|
|
Padding 254 varies
|
|
reserved for future extension 255
|
|
==================================== ============= ============
|
|
|
|
|
|
Block Ordering Rules
|
|
----------------------
|
|
|
|
In the Session Confirmed part 2, order must be:
|
|
RouterInfo, followed by Options if present, followed by Padding if present.
|
|
No other blocks are allowed.
|
|
|
|
In the data phase, order is unspecified, except for the
|
|
following requirements:
|
|
Padding, if present, must be the last block.
|
|
Termination, if present, must be the last block except for Padding.
|
|
|
|
There may be multiple I2NP blocks in a single payload.
|
|
Multiple Padding blocks are not allowed in a single payload.
|
|
Other block types probably won't have multiple blocks in
|
|
a single payload, but it is not prohibited.
|
|
|
|
Block Specifications
|
|
----------------------
|
|
|
|
DateTime
|
|
````````
|
|
For time synchronization:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+
|
|
| 0 | 4 | timestamp |
|
|
+----+----+----+----+----+----+----+
|
|
|
|
blk :: 0
|
|
size :: 2 bytes, big endian, value = 4
|
|
timestamp :: Unix timestamp, unsigned seconds.
|
|
Wraps around in 2106
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
Options
|
|
```````
|
|
Pass updated options.
|
|
Options include: Min and max padding.
|
|
|
|
Options block will be variable length.
|
|
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 1 | size |tmin|tmax|rmin|rmax|tdmy|
|
|
+----+----+----+----+----+----+----+----+
|
|
|tdmy| rdmy | tdelay | rdelay | |
|
|
~----+----+----+----+----+----+----+ ~
|
|
| more_options |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
blk :: 1
|
|
size :: 2 bytes, big endian, size of options to follow, 12 bytes minimum
|
|
|
|
tmin, tmax, rmin, rmax :: requested padding limits
|
|
tmin and rmin are for desired resistance to traffic analysis.
|
|
tmax and rmax are for bandwidth limits.
|
|
tmin and tmax are the transmit limits for the router sending this options block.
|
|
rmin and rmax are the receive limits for the router sending this options block.
|
|
Each is a 4.4 fixed-point float representing 0 to 15.9375
|
|
(or think of it as an unsigned 8-bit integer divided by 16.0).
|
|
This is the ratio of padding to data. Examples:
|
|
Value of 0x00 means no padding
|
|
Value of 0x01 means add 6 percent padding
|
|
Value of 0x10 means add 100 percent padding
|
|
Value of 0x80 means add 800 percent (8x) padding
|
|
Alice and Bob will negotiate the minimum and maximum in each direction.
|
|
These are guidelines, there is no enforcement.
|
|
Sender should honor receiver's maximum.
|
|
Sender may or may not honor receiver's minimum, within bandwidth constraints.
|
|
|
|
tdmy: Max dummy traffic willing to send, 2 bytes big endian, bytes/sec average
|
|
rdmy: Requested dummy traffic, 2 bytes big endian, bytes/sec average
|
|
tdelay: Max intra-message delay willing to insert, 2 bytes big endian, msec average
|
|
rdelay: Requested intra-message delay, 2 bytes big endian, msec average
|
|
|
|
Padding distribution specified as additional parameters?
|
|
Random delay specified as additional parameters?
|
|
|
|
more_options :: Format TBD
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
Options Issues
|
|
``````````````
|
|
- Options negotiation is TBD.
|
|
|
|
|
|
RouterInfo
|
|
``````````
|
|
Pass Alice's RouterInfo to Bob.
|
|
Used in Session Confirmed part 2.
|
|
Pass Alice's RouterInfo to Bob, or Bob's to Alice.
|
|
Used optionally in the data phase.
|
|
|
|
NOTE: Unlike in NTCP2, the Router Info may be fragmented.
|
|
Session setup is not complete until all fragments are received.
|
|
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 2 | size |flag|frag| |
|
|
+----+----+----+----+----+ +
|
|
| |
|
|
+ Router Info fragment +
|
|
| (Alice RI in Sessopm Confirmed) |
|
|
~ (Alice, Bob, or third-party ~
|
|
| RI in data phase) |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
blk :: 2
|
|
size :: 2 bytes, big endian, 2 + fragment size
|
|
flag :: 1 byte flags
|
|
bit order: 76543210 (bit 7 is MSB)
|
|
bit 0: 0 for local store, 1 for flood request
|
|
bits 7-1: Unused, set to 0 for future compatibility
|
|
frag :: 1 byte fragment info:
|
|
bit order: 76543210 (bit 7 is MSB)
|
|
bits 7-4: fragment number 0-14, big endian
|
|
bits 3-0: total fragments 1-15, big endian
|
|
|
|
routerinfo :: Alice's or Bob's RouterInfo
|
|
|
|
|
|
{% endhighlight %}
|
|
|
|
Notes
|
|
`````
|
|
- When used in the data phase, receiver (Alice or Bob) shall validate that
|
|
it's the same Router Hash as originally sent (for Alice) or sent to (for Bob).
|
|
Then, treat it as a local I2NP DatabaseStore Message. Validate signature,
|
|
validate more recent timestamp, and store in the local netdb.
|
|
If the flag bit 0 is 1, and the receiving party is floodfill,
|
|
treat it as a DatabaseStore Message with a nonzero reply token,
|
|
and flood it to the nearest floodfills.
|
|
|
|
- The Router Info is NOT compressed with gzip
|
|
(unlike in a DatabaseStore Message, where it is)
|
|
|
|
- Flooding must not be requested unless there are published
|
|
RouterAddresses in the RouterInfo. The receiving router
|
|
must not flood the RouterInfo unless there are published
|
|
RouterAddresses in it.
|
|
|
|
- This protocol does not provide an acknowledgement that the RouterInfo
|
|
was received, stored, or flooded (either in the handshake or data phase).
|
|
If acknowledgement is desired, and the receiver is floodfill,
|
|
the sender should instead send a standard I2NP DatabaseStoreMessage
|
|
with a reply token.
|
|
|
|
|
|
Issues
|
|
``````
|
|
- Could also be used in data phase, instead of a I2NP DatabaseStoreMessage.
|
|
For example, Bob could use it to start off the data phase.
|
|
|
|
- Is it allowed for this to contain the RI for routers other than the
|
|
originator, as a general replacement for DatabaseStoreMessages,
|
|
e.g. for flooding by floodfills?
|
|
|
|
|
|
I2NP Message
|
|
````````````
|
|
A complete I2NP message with a modified header.
|
|
|
|
This uses the same 9 bytes for the I2NP header
|
|
as in [NTCP2]_ (type, message id, short expiration).
|
|
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 3 | size |type| msg id |
|
|
+----+----+----+----+----+----+----+----+
|
|
| short exp | message |
|
|
+----+----+----+----+ +
|
|
| |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
blk :: 3
|
|
size :: 2 bytes, big endian, size of type + msg id + exp + message to follow
|
|
I2NP message body size is (size - 9).
|
|
type :: 1 byte, I2NP msg type, see I2NP spec
|
|
msg id :: 4 bytes, big endian, I2NP message ID
|
|
short exp :: 4 bytes, big endian, I2NP message expiration, Unix timestamp, unsigned seconds.
|
|
Wraps around in 2106
|
|
message :: I2NP message body
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
First Fragment
|
|
```````````````
|
|
The first fragment (fragment #0) of an I2NP message with a modified header.
|
|
|
|
This uses the same 9 bytes for the I2NP header
|
|
as in [NTCP2]_ (type, message id, short expiration).
|
|
|
|
Total number of fragments is not specified.
|
|
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 4 | size |type| msg id |
|
|
+----+----+----+----+----+----+----+----+
|
|
| short exp | |
|
|
+----+----+----+----+ +
|
|
| partial message |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
blk :: 4
|
|
size :: 2 bytes, big endian, size of type + msg id + exp + partial message to follow
|
|
Fragment size is (size - 9).
|
|
type :: 1 byte, I2NP msg type, see I2NP spec
|
|
msg id :: 4 bytes, big endian, I2NP message ID
|
|
short exp :: 4 bytes, big endian, I2NP message expiration, Unix timestamp, unsigned seconds.
|
|
Wraps around in 2106
|
|
message :: Partial I2NP message body, bytes 0 - (size -1)
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
Follow-on Fragment
|
|
````````````````````````
|
|
An additional fragment (fragment number greater than zero) of an I2NP message.
|
|
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 5 | size |frag| msg id |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ +
|
|
| partial message |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
blk :: 5
|
|
size :: 2 bytes, big endian, size of frag + msg id + partial message to follow
|
|
Fragment size is (size - 5).
|
|
frag :: Fragment info:
|
|
Bit order: 76543210 (bit 7 is MSB)
|
|
bits 7-1: fragment # 1 - 127 (0 not allowed)
|
|
bit 0: isLast (1 = true)
|
|
msg id :: 4 bytes, big endian, I2NP message ID
|
|
message :: Partial I2NP message body
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
|
|
Termination
|
|
```````````
|
|
Drop the connection.
|
|
This must be the last non-padding block in the payload.
|
|
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 6 | size | valid data packets |
|
|
+----+----+----+----+----+----+----+----+
|
|
received | rsn| addl data |
|
|
+----+----+----+----+ +
|
|
~ . . . ~
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
blk :: 6
|
|
size :: 2 bytes, big endian, value = 9 or more
|
|
valid data packets received :: The number of valid packets received
|
|
(current receive nonce value)
|
|
0 if error occurs in handshake phase
|
|
8 bytes, big endian
|
|
rsn :: reason, 1 byte:
|
|
0: normal close or unspecified
|
|
1: termination received
|
|
2: idle timeout
|
|
3: router shutdown
|
|
4: data phase AEAD failure
|
|
5: incompatible options
|
|
6: incompatible signature type
|
|
7: clock skew
|
|
8: padding violation
|
|
9: AEAD framing error
|
|
10: payload format error
|
|
11: Session Request error
|
|
12: Session Created error
|
|
13: Session Confirmed error
|
|
14: Timeout
|
|
15: RI signature verification fail
|
|
16: s parameter missing, invalid, or mismatched in RouterInfo
|
|
17: banned
|
|
addl data :: optional, 0 or more bytes, for future expansion, debugging,
|
|
or reason text.
|
|
Format unspecified and may vary based on reason code.
|
|
|
|
{% endhighlight %}
|
|
|
|
Notes
|
|
`````
|
|
Not all reasons may actually be used, implementation dependent.
|
|
Most failures will generally result in the message being dropped, not a termination.
|
|
See notes in handshake message sections above.
|
|
Additional reasons listed are for consistency, logging, debugging, or if policy changes.
|
|
|
|
RelayRequest
|
|
``````````````
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 7 | size | relay tag | asz|
|
|
+----+----+----+----+----+----+----+----+
|
|
| Alice IP address | APort | csz| |
|
|
+----+----+----+----+----+----+----+ +
|
|
| challenge to be delivered to Charlie |
|
|
+ +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| Alice's intro key |
|
|
+ +
|
|
| |
|
|
+ +
|
|
| |
|
|
+ +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| nonce |
|
|
+----+----+----+----+
|
|
|
|
blk :: 7
|
|
size :: 2 bytes, big endian, size of data to follow
|
|
relay tag :: 4 byte relay (introduction) tag, nonzero, as received by
|
|
Alice in the SessionCreated message from Bob
|
|
asz :: 1 byte IP address size
|
|
Alice IP :: Alice's IP address, network byte order, asz bytes
|
|
APort :: 2 byte port number of Alice, network byte order
|
|
csz :: 1 byte challenge size
|
|
challenge :: if csz is nonzero, that many bytes to be relayed to Charlie in the intro
|
|
intro : Alice's 32-byte introduction key (so Bob can reply with
|
|
Charlie's info)
|
|
nonce :: 4 byte nonce of Alice's relay request
|
|
|
|
{% endhighlight %}
|
|
|
|
Notes
|
|
`````
|
|
* The IP address is only included if it is be different than the packet's
|
|
source address and port.
|
|
|
|
* This message may be sent via IPv4 or IPv6.
|
|
If the message is over IPv6 for an IPv4 introduction,
|
|
or (as of release 0.9.50) over IPv4 for an IPv6 introduction,
|
|
Alice must include her introduction address and port.
|
|
This is supported as of release 0.9.50.
|
|
|
|
* If Alice includes her address/port, Bob may perform additional validation
|
|
before continuing.
|
|
|
|
* Challenge is unimplemented, challenge size is always zero
|
|
|
|
* Relaying for IPv6 is supported as of release 0.9.50.
|
|
|
|
* Prior to release 0.9.12, Bob's intro key was always used. As of release
|
|
0.9.12, the session key is used if there is an established session between
|
|
Alice and Bob. In practice, there must be an established session, as Alice
|
|
will only get the nonce (introduction tag) from the session created message,
|
|
and Bob will mark the introduction tag invalid once the session is destroyed.
|
|
|
|
|
|
RelayResponse
|
|
``````````````
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 8 | size | csz| Charlie IP |
|
|
+----+----+----+----+----+----+----+----+
|
|
| CPort | asz| Alice IP |Aprt
|
|
+----+----+----+----+----+----+----+----+
|
|
Aprt| nonce |
|
|
+----+----+----+----+----+
|
|
|
|
blk :: 8
|
|
size :: 2 bytes, big endian, size of data to follow
|
|
csz :: 1 byte Charlie IP address size
|
|
Charlie IP :: Charlie's IP address, network byte order, csz bytes
|
|
CPort :: 2 byte Charlie's port number, network byte order
|
|
asz :: 1 byte Alice IP address size
|
|
Alice IP :: Alice's IP address, network byte order, asz bytes
|
|
Aprt :: 2 byte Alice's port number, network byte order
|
|
nonce :: 4 byte nonce sent by Alice
|
|
|
|
{% endhighlight %}
|
|
|
|
Notes
|
|
`````
|
|
* This message may be sent via IPv4 or IPv6.
|
|
|
|
* Alice's IP address/port are the apparent IP/port that Bob received the
|
|
RelayRequest on (not necessarily the IP Alice included in the RelayRequest),
|
|
and may be IPv4 or IPv6. Alice currently ignores these on receive.
|
|
|
|
* Charlie's IP address may be IPv4, or, as of release 0.9.50, IPv6.
|
|
as that is the address that Alice will
|
|
send the SessionRequest to after the Hole Punch.
|
|
|
|
* Relaying for IPv6 is supported as of release 0.9.50.
|
|
|
|
* Prior to release 0.9.12, Alice's intro key was always used. As of release
|
|
0.9.12, the session key is used if there is an established session between
|
|
Alice and Bob.
|
|
|
|
|
|
|
|
RelayIntro
|
|
``````````````
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 9 | size | asz| Alice IP |
|
|
+----+----+----+----+----+----+----+----+
|
|
| APort | csz| |
|
|
+----+----+----+ +
|
|
| that many bytes of challenge |
|
|
+ +
|
|
| data relayed from Alice |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
blk :: 9
|
|
size :: 2 bytes, big endian, size of data to follow
|
|
|
|
{% endhighlight %}
|
|
|
|
Notes
|
|
`````
|
|
* For IPv4, Alice's IP address is always 4 bytes, because Alice is trying to connect to Charlie via IPv4.
|
|
As of release 0.9.xx, IPv6 is supported, and Alice's IP address may be 16 bytes.
|
|
|
|
* This message must be sent via an established IPv4 connection, as that's the
|
|
only way that Bob knows Charlie's IPv4 address to return to Alice in the
|
|
RelayResponse_.
|
|
|
|
* For IPv4, this message must be sent via an established IPv4 connection,
|
|
as that's the only way that Bob knows Charlie's IPv4 address to return to Alice in the RelayResponse_.
|
|
As of release 0.9.50, IPv6 is supported, and this message may be sent via an established IPv6 connection.
|
|
|
|
* As of release 0.9.50, any SSU address published with introducers must contain "4" or "6" in the "caps" option.
|
|
|
|
* Challenge is unimplemented, challenge size is always zero
|
|
|
|
|
|
PeerTest
|
|
``````````````
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 10 | size | test nonce | asz|
|
|
+----+----+----+----+----+----+----+----+
|
|
| Alice IP address |AlicePort| |
|
|
+----+----+----+----+----+----+ +
|
|
| Alice or Charlie's |
|
|
+ introduction key (Alice's is sent to +
|
|
| Bob and Charlie, while Charlie's is |
|
|
+ sent to Alice) (32 bytes) +
|
|
| |
|
|
+ +----+----+
|
|
| |
|
|
+----+----+----+----+----+----+
|
|
|
|
blk :: 10
|
|
size :: 2 bytes, big endian, size of data to follow
|
|
test nonce :: 4 byte nonce, big endian integer
|
|
asz :: 1 byte IP address size (may be 0, 4, or 16)
|
|
Alice IP :: asz byte representation of Alice's IP address,
|
|
network byte order, if size is greater than zero
|
|
AlicePort :: 2 byte Alice's port number, big endian
|
|
intro :: Alice's or Charlie's 32-byte introduction key, big endian
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
Notes
|
|
`````
|
|
* When sent by Alice, IP address size is 0, IP address is not present, and port
|
|
is 0, as Bob and Charlie do not use the data; the point is to determine
|
|
Alice's true IP address/port and tell Alice; Bob and Charlie don't care what
|
|
Alice thinks her address is.
|
|
|
|
* When sent by Bob or Charlie, IP and port are present, and IP address is
|
|
4 or 16 bytes. IPv6 testing is supported as of release 0.9.27.
|
|
|
|
* IPv6 Notes: Through release 0.9.26, only testing of IPv4 addresses is supported. Therefore, all
|
|
Alice-Bob and Alice-Charlie communication must be via IPv4. Bob-Charlie
|
|
communication, however, may be via IPv4 or IPv6. Alice's address, when
|
|
specified in the PeerTest message, must be 4 bytes.
|
|
As of release 0.9.27, testing of IPv6 addresses is supported,
|
|
and Alice-Bob and Alice-Charlie communication may be via IPv6,
|
|
if Bob and Charlie indicate support with a 'B' capability in their published IPv6 address.
|
|
See Proposal 126 for details.
|
|
|
|
Alice sends the request to Bob using an existing session over the transport (IPv4 or IPv6) that she wishes to test.
|
|
When Bob receives a request from Alice via IPv4, Bob must select a Charlie that advertises an IPv4 address.
|
|
When Bob receives a request from Alice via IPv6, Bob must select a Charlie that advertises an IPv6 address.
|
|
The actual Bob-Charlie communication may be via IPv4 or IPv6 (i.e., independent of Alice's address type).
|
|
|
|
* A peer must maintain a table of active test states (nonces). On reception of
|
|
a PeerTest message, look up the nonce in the table. If found, it's an
|
|
existing test and you know your role (Alice, Bob, or Charlie). Otherwise, if
|
|
the IP is not present and the port is 0, this is a new test and you are Bob.
|
|
Otherwise, this is a new test and you are Charlie.
|
|
|
|
* Alice must have an established session with Bob and use
|
|
the session key.
|
|
|
|
|
|
|
|
NextNonce
|
|
``````````````
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 11 | size | TBD |
|
|
+----+----+----+ +
|
|
| |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
blk :: 11
|
|
size :: 2 bytes, big endian, size of data to follow
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
Ack
|
|
``````````````
|
|
- 4 byte ack through
|
|
- one byte negative offset from ack through
|
|
- bitfield of nacks from (ack through) - offset
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 12 | size | TBD |
|
|
+----+----+----+ +
|
|
| |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
blk :: 12
|
|
size :: 2 bytes, big endian, size of data to follow
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
Partial Ack
|
|
``````````````
|
|
TODO Not required if we're acking packets, not I2NP messages?
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 13 | size | TBD |
|
|
+----+----+----+ +
|
|
| |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
blk :: 13
|
|
size :: 2 bytes, big endian, size of data to follow
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
Nack
|
|
``````````````
|
|
TODO Not required, put in ack block?
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 14 | size | TBD |
|
|
+----+----+----+ +
|
|
| |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
blk :: 14
|
|
size :: 2 bytes, big endian, size of data to follow
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
Relay Tag Request
|
|
```````````````````````
|
|
In the Session Request message.
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+
|
|
| 15 | 0 |
|
|
+----+----+----+
|
|
|
|
blk :: 15
|
|
size :: 2 bytes, big endian, value = 0
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
Relay Tag
|
|
```````````
|
|
In the Session Created message.
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+
|
|
| 16 | 4 | relay tag |
|
|
+----+----+----+----+----+----+----+
|
|
|
|
blk :: 16
|
|
size :: 2 bytes, big endian, value = 4
|
|
relay tag :: 4 bytes, big endian
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
New Token
|
|
```````````````
|
|
For a subsequent connection:
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 17 | 4 | expires | |
|
|
+----+----+----+----+----+----+----+ +
|
|
token |
|
|
+----+----+----+----+----+----+----+
|
|
|
|
blk :: 17
|
|
size :: 2 bytes, big endian, value = 4
|
|
expires :: Unix timestamp, unsigned seconds.
|
|
Wraps around in 2106
|
|
token :: 8 bytes, big endian
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
Path Challenge
|
|
``````````````
|
|
A Ping with arbitrary data to be returned in a Path Response,
|
|
used as a keep-alive or to validate an IP/Port change.
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 18 | size | Arbitrary Data |
|
|
+----+----+----+ +
|
|
| |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
blk :: 18
|
|
size :: 2 bytes, big endian, size of data to follow
|
|
data :: Arbitrary data to be returned in a Path Response
|
|
length as selected by sender
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
|
|
Path Response
|
|
``````````````
|
|
A Pong with arbitrary data, a reply to a Path Challenge,
|
|
used as a keep-alive or to validate an IP/Port change.
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
| 19 | size | Arbitrary Data |
|
|
+----+----+----+ +
|
|
| |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
blk :: 19
|
|
size :: 2 bytes, big endian, size of data to follow
|
|
data :: As received in a Path Challenge
|
|
|
|
{% endhighlight %}
|
|
|
|
|
|
|
|
|
|
Padding
|
|
```````
|
|
This is for padding inside AEAD payloads.
|
|
Padding for all messages are inside AEAD payloads.
|
|
|
|
Padding should roughly adhere to the negotiated parameters.
|
|
Bob sent his requested tx/rx min/max parameters in Session Created.
|
|
Alice sent her requested tx/rx min/max parameters in Session Confirmed.
|
|
Updated options may be sent during the data phase.
|
|
See options block information above.
|
|
|
|
If present, this must be the last block in the payload.
|
|
|
|
|
|
|
|
.. raw:: html
|
|
|
|
{% highlight lang='dataspec' %}
|
|
+----+----+----+----+----+----+----+----+
|
|
|254 | size | padding |
|
|
+----+----+----+ +
|
|
| |
|
|
~ . . . ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
blk :: 254
|
|
size :: 2 bytes, big endian, size of padding to follow
|
|
padding :: random data
|
|
|
|
{% endhighlight %}
|
|
|
|
Notes
|
|
`````
|
|
- Padding strategies TBD.
|
|
- Minimum padding TBD.
|
|
- Padding-only blocks are allowed.
|
|
- Padding defaults TBD.
|
|
- See options block for padding parameter negotiation
|
|
- See options block for min/max padding parameters
|
|
- Noise limits messages to 64KB. If more padding is necessary, send multiple messages.
|
|
- Router response on violation of negotiated padding is implementation-dependent.
|
|
|
|
|
|
Other block types
|
|
`````````````````
|
|
Implementations should ignore unknown block types for
|
|
forward compatibility, except in Session Confirmed part 2, where
|
|
unknown blocks are not allowed.
|
|
|
|
|
|
Future work
|
|
```````````
|
|
- The padding length is either to be decided on a per-message basis and
|
|
estimates of the length distribution, or random delays should be added.
|
|
These countermeasures are to be included to resist DPI, as message sizes
|
|
would otherwise reveal that I2P traffic is being carried by the transport
|
|
protocol. The exact padding scheme is an area of future work, Appendix A
|
|
provides more information on the topic.
|
|
|
|
|
|
Replay Prevention
|
|
=====================
|
|
|
|
Both Session Request and Session Created messages must contain DateTime blocks.
|
|
|
|
Both Alice and Bob validate that the time is within a valid skew (recommended +/- 2 minutes)
|
|
and for replay prevention. Bob should reject duplicate Session Request messages
|
|
even if the skew is valid, via a Bloom filter or other mechanism.
|
|
|
|
Routers should use standard flow control and retransmission mechanisms to
|
|
detect and drop duplicate data phase messages.
|
|
|
|
|
|
|
|
Handshake Retransmission
|
|
===========================
|
|
|
|
Session Request
|
|
----------------
|
|
If no Session Created is received:
|
|
|
|
Maintain same source and connection IDs and ephemeral key. Increment packet number.
|
|
Re-encrypt Noise payload as AEAD (packet number) changed.
|
|
Re-protect header, re-obfuscate header, as packet number changed.
|
|
|
|
Recommended retransmission intervals: 3 and 6 seconds (3 and 9 seconds after first sent).
|
|
Recommended timeout: 15 seconds total
|
|
|
|
|
|
Session Created
|
|
----------------
|
|
If no Session Confirmed is received:
|
|
|
|
Maintain same source and connection IDs and ephemeral key. Increment packet number.
|
|
Re-encrypt Noise payload as AEAD (packet number) changed.
|
|
Re-protect header, re-obfuscate header, as packet number changed.
|
|
|
|
Recommended retransmission intervals: 3 and 6 seconds (3 and 9 seconds after first sent).
|
|
Recommended timeout: 15 seconds total
|
|
|
|
|
|
Session Confirmed
|
|
------------------
|
|
In SSU 1, Alice does not shift to the data phase until the first data packet is
|
|
received from Bob. This makes SSU 1 a two-round-trip setup.
|
|
Session Confirmed messages will be retransmitted
|
|
at 3 and 6 seconds (3 and 9 seconds after first sent).
|
|
|
|
There are several alternatives. All are 1 RTT:
|
|
|
|
1) Alice assumes Session Confirmed was received, sends data packets immediately,
|
|
never retransmit Session Confirmed. Data packets received out-of-order
|
|
(before Session Confirmed) will be undecryptable, but will get retransmitted.
|
|
If Session Confirmed is lost, all sent data packets will be dropped.
|
|
|
|
2) As in 1), send data packets immediately, but also retransmit Session Confirmed
|
|
until a data packet is received.
|
|
|
|
3) We could use IK instead of XK, as it has only two messages in the handshake, but
|
|
it uses an extra DH (4 instead of 3).
|
|
|
|
|
|
Retry
|
|
---------
|
|
If no Session Request is received:
|
|
|
|
Maintain same source and connection IDs. Increment packet number.
|
|
Re-protect header, re-obfuscate header, as packet number changed.
|
|
|
|
Recommended retransmission intervals: 3 and 6 seconds (3 and 9 seconds after first sent).
|
|
Recommended timeout: 15 seconds total
|
|
|
|
|
|
Total Timeout
|
|
--------------
|
|
Recommended total timeout for the handshake is 20 seconds.
|
|
|
|
|
|
Token
|
|
=============
|
|
|
|
The Token in the Session Request header is used for DoS mitigation.
|
|
|
|
If Bob does not accept the token in the Session Request message, Bob does NOT decrypt
|
|
the message, as it requires an expensive DH operation.
|
|
Bob simply sends a Retry message with a new token.
|
|
|
|
If a subsequent Session Request message then is received with that token,
|
|
Bob proceeds to decrypt that message and proceed with the handshake.
|
|
|
|
The token may be a randomly-generated 8 byte value, if the generator of the token
|
|
stores the values and associated IP and port (in-memory or persistently).
|
|
Alternatively, the generator may generate an opaque value, for example,
|
|
using the SipHash (with a secret seed K0, K1) of the IP, port, and current hour or day,
|
|
to create tokens that do not need to be saved in-memory.
|
|
Note that this method may make it difficult to reject reused tokens.
|
|
|
|
Tokens may only be used once.
|
|
A token sent from Bob to Alice in a Retry message must be used immediately, and expires
|
|
in a few seconds.
|
|
A token sent in a New Token block in an established session
|
|
may be used in a subsequent connection, and it
|
|
expires at the time specified in that block.
|
|
Expiration is specified by the sender; recommended values are
|
|
one hour minimum, several hours or days maximum.
|
|
A router should delete all its saved tokens if its IP, router hash, or keys change.
|
|
Tokens may optionally be persisted across router restarts, implementation dependent.
|
|
Acceptance of an unexpired token is not guaranteed; if Bob has forgotten or deleted
|
|
his saved tokens, he will send a Retry to Alice.
|
|
|
|
New Token blocks may be sent from Alice to Bob or Bob to Alice.
|
|
They would typically be sent once, soon after session establishment.
|
|
The token may be resent before or after expiration with a new expiration time,
|
|
or a new token may be sent.
|
|
|
|
A token is bound to the combination of source IP/port, destination IP/port,
|
|
static keys, and router hashes. A token received on IPv4 may not be used
|
|
for IPv6 or vice versa.
|
|
|
|
|
|
|
|
|
|
|
|
Router Info Fragmentation
|
|
===========================
|
|
|
|
SSU 1 contains a mechanism for Router Identity fragmentation in the Session Confirmed message
|
|
but it is unused, as the Router Identity is only 391 bytes
|
|
(387 for old DSA-SHA1 routers) and so fragmentation was never required.
|
|
The full Router Info was sent in a subsequent I2NP database store message in the data phase
|
|
and was fragmented as necessary.
|
|
|
|
In SSU2, the full Router Info is sent in the Session Confirmed message
|
|
(as in NTCP2), and validation of the signature
|
|
(and matching the static key in the Router Identity to that received in the Noise handshake)
|
|
is a vital part of the handshake.
|
|
|
|
Median Router Info sizes in the network are about 800 bytes, with a maximum size
|
|
of about 2000 bytes (uncompressed) or 1300 bytes (compressed).
|
|
Maximum Router Info sizes are expected to increase in the future,
|
|
due to additional Router Addresses.
|
|
If both SSU and SSU2 addresses are supported, or if multiple addresses for
|
|
different IPv4 or IPv6 IPs are supported (currently supported by i2pd but not Java i2p)
|
|
the sizes could increase significantly.
|
|
|
|
While a typical MTU and Router Info size would allow the Router Info to be sent
|
|
unfragmented, fragmentation will be necessary and this protocol must support it.
|
|
The Router Info block contains a fragmentation field (unlike in NTCP2 where it is not required).
|
|
|
|
If fragmentation is required, the first fragment is sent in the Session Confirmed message,
|
|
and subsequent fragments are sent in Data messages.
|
|
However, the session must be considered as in a pending state until all Router Info
|
|
fragments are received by Bob.
|
|
|
|
Alice must NOT send any I2NP blocks before all Router Info blocks are sent.
|
|
Alice MAY send I2NP blocks in the same message as the last RouterInfo fragment.
|
|
Bob MUST either queue or discard any I2NP blocks received from Alice before all Router Info blocks
|
|
are received and the signature and static key are validated.
|
|
Bob must NOT send any I2NP blocks to Alice before all Router Info blocks
|
|
are received and the signature and static key are validated.
|
|
|
|
|
|
|
|
|
|
I2NP Message Fragmentation
|
|
===========================
|
|
|
|
Differences from SSU 1
|
|
|
|
Note: As in SSU 1, the initial fragment does not contain information
|
|
on the total number of fragments or the total length.
|
|
Follow-on fragments do not contain information on their offset.
|
|
This provides the sender the flexibility of fragmenting "on the fly"
|
|
based on available space in the packet.
|
|
(Java I2P does not do this; it "pre-fragments" before the first fragment is sent)
|
|
However, it does burden the receiver to store fragments
|
|
received out-of-order and delay reassembly until all fragments are received.
|
|
|
|
As in SSU 1, any retransmission of fragments must preserve the length (and implicit offset)
|
|
of the fragment's previous tranmission.
|
|
|
|
SSU 2 does separate the three cases (full message, initial fragment, and follow-on fragment)
|
|
into three different block types, to improve processing efficiency.
|
|
|
|
|
|
|
|
Congestion Control
|
|
====================
|
|
|
|
Sequence numbers, acks, backoff, retransmission
|
|
|
|
|
|
|
|
Session Termination
|
|
=====================
|
|
|
|
Message or block? TBD
|
|
|
|
Upon any normal or abnormal termination, routers should
|
|
zero-out any in-memory ephemeral data, including handshake ephemeral keys,
|
|
symmetric crypto keys, and related information.
|
|
|
|
|
|
MTU
|
|
========
|
|
|
|
Requirements vary, based on whether the published address is shared with SSU 1.
|
|
Current SSU 1 IPv4 minimum is 620, which is probably too small.
|
|
|
|
SSU Address
|
|
------------
|
|
Shared address with SSU 1, must follow SSU 1 rules.
|
|
IPv4: Default and max is 1484. Min is 620.
|
|
(IPv4 MTU + 4) must be a multiple of 16.
|
|
IPv6: Must be published, min is 1280 and the max is 1488.
|
|
IPv6 MTU must be a multiple of 16.
|
|
|
|
SSU2 Address
|
|
------------
|
|
Must follow SSU 1 rules.
|
|
IPv4: Default and max is 1500. Min is TBD.
|
|
IPv6: Default and max is 1500. Min is 1280.
|
|
No multiple of 16 rules, but should probably be a multiple of 2 at least.
|
|
|
|
PMTU Discovery
|
|
---------------
|
|
For SSU 1, current Java I2P performs PMTU discovery by starting with small packets and
|
|
gradually increasing the size, or increasing based on received packet size.
|
|
This is crude and greatly reduces the efficiency.
|
|
Continuing this feature in SSU 2 is TBD.
|
|
|
|
Recent studies [PMTU]_ suggest that a minimum for IPv4 of 1200 or more would work
|
|
for more than 99% of connections. QUIC [RFC-9000]_ requires a minimum IP
|
|
packet size of 1280 bytes.
|
|
|
|
quote [RFC-9000]_:
|
|
|
|
The maximum datagram size is defined as the largest size of UDP
|
|
payload that can be sent across a network path using a single UDP
|
|
datagram. QUIC MUST NOT be used if the network path cannot support a
|
|
maximum datagram size of at least 1200 bytes.
|
|
|
|
QUIC assumes a minimum IP packet size of at least 1280 bytes. This
|
|
is the IPv6 minimum size [IPv6] and is also supported by most modern
|
|
IPv4 networks. Assuming the minimum IP header size of 40 bytes for
|
|
IPv6 and 20 bytes for IPv4 and a UDP header size of 8 bytes, this
|
|
results in a maximum datagram size of 1232 bytes for IPv6 and 1252
|
|
bytes for IPv4. Thus, modern IPv4 and all IPv6 network paths are
|
|
expected to be able to support QUIC.
|
|
|
|
Note: This requirement to support a UDP payload of 1200 bytes
|
|
limits the space available for IPv6 extension headers to 32
|
|
bytes or IPv4 options to 52 bytes if the path only supports the
|
|
IPv6 minimum MTU of 1280 bytes. This affects Initial packets
|
|
and path validation.
|
|
|
|
end quote
|
|
|
|
|
|
Handshake Min Size
|
|
-------------------------
|
|
|
|
QUIC requires that Initial datagrams in both directions be at least 1200 bytes,
|
|
to prevent amplification attacks. and ensure the PMTU supports it in both directions.
|
|
|
|
We could require this for Session Request and Session Created,
|
|
at substantial cost in bandwidth.
|
|
Perhaps we could do this only if we don't have a token,
|
|
or after a Retry message is received.
|
|
TBD
|
|
|
|
|
|
Path Message Min Size
|
|
-------------------------
|
|
|
|
QUIC requires that messages containing PATH_CHALLENGE or PATH_RESPONSE frames be at least 1200 bytes,
|
|
to prevent amplification attacks. and ensure the PMTU supports it in both directions.
|
|
|
|
We could require this as well, at substantial cost in bandwidth.
|
|
However, these cases should be rare.
|
|
TBD
|
|
|
|
|
|
|
|
Max Message Size
|
|
------------------
|
|
|
|
IPv4:
|
|
No IP fragmentation is assumed.
|
|
IP + datagram header is 28 bytes.
|
|
This assumes no IPv4 options.
|
|
Max message size is MTU - 28.
|
|
Data phase header is 16 bytes and MAC is 16 bytes, totalling 32 bytes.
|
|
Payload size is MTU - 60.
|
|
Max data phase payload is 1440 for a max 1500 MTU.
|
|
Max data phase payload is 1220 for a min 1280 MTU.
|
|
|
|
|
|
IPv6:
|
|
No IP fragmentation is allowed.
|
|
IP + datagram header is 48 bytes.
|
|
This assumes no IPv6 extension headers.
|
|
Max message size is MTU - 48.
|
|
Data phase header is 16 bytes and MAC is 16 bytes, totalling 32 bytes.
|
|
Payload size is MTU - 80.
|
|
Max data phase payload is 1420 for a max 1500 MTU.
|
|
Max data phase payload is 1200 for a min 1280 MTU.
|
|
|
|
|
|
|
|
Published Router Info
|
|
=====================
|
|
|
|
Address Properties
|
|
-------------------
|
|
|
|
The following address properties may be publiished, unchanged from SSU 1:
|
|
|
|
- caps: [B,C,4,6] capabilities
|
|
|
|
- host: IP (IPv4 or IPv6).
|
|
Shortened IPv6 address (with "::") is allowed.
|
|
May or may not be present if firewalled.
|
|
Host names are not allowed.
|
|
|
|
- iexp[0-2]: Expiration of this introducer.
|
|
ASCII digits, in seconds since the epoch.
|
|
Only present if firewalled, and introducers are required.
|
|
Optional (even if other properties for this introducer are present).
|
|
|
|
- ihost[0-2]: Introducer's IP (IPv4 or IPv6).
|
|
Shortened IPv6 address (with "::") is allowed.
|
|
Only present if firewalled, and introducers are required.
|
|
Host names are not allowed.
|
|
|
|
- ikey[0-2]: Introducer's Base 64 introduction key.
|
|
Only present if firewalled, and introducers are required.
|
|
|
|
- iport[0-2]: Introducer's port 1024 - 65535.
|
|
Only present if firewalled, and introducers are required.
|
|
|
|
- itag[0-2]: Introducer's tag 1 - (2**32 - 1)
|
|
ASCII digits.
|
|
Only present if firewalled, and introducers are required.
|
|
|
|
- key: Base 64 introduction key.
|
|
|
|
- mtu: Optional. See MTU section above.
|
|
|
|
- port: 1024 - 65535
|
|
May or may not be present if firewalled.
|
|
|
|
|
|
|
|
Published Addresses
|
|
-------------------
|
|
|
|
The published RouterAddress (part of the RouterInfo) will have a
|
|
protocol identifier of either "SSU" or "SSU2".
|
|
|
|
The RouterAddress must contain three options
|
|
to indicate SSU2 support:
|
|
|
|
- s=(Base64 key)
|
|
The current Noise static public key (s) for this RouterAddress.
|
|
Base 64 encoded using the standard I2P Base 64 alphabet.
|
|
32 bytes in binary, 44 bytes as Base 64 encoded,
|
|
little-endian X25519 public key.
|
|
|
|
- i=(Base64 IV)
|
|
The current IV for encrypting the headers for this RouterAddress.
|
|
Base 64 encoded using the standard I2P Base 64 alphabet.
|
|
16 bytes in binary, 24 bytes as Base 64 encoded,
|
|
big-endian.
|
|
|
|
- v=2
|
|
The current version (2).
|
|
When published as "SSU", additional support for version 1 is implied.
|
|
Support for future versions will be with comma-separated values,
|
|
e.g. v=2,3
|
|
Implementation should verify compatibility, including multiple
|
|
versions if a comma is present. Comma-separated versions must
|
|
be in numerical order.
|
|
|
|
|
|
Alice must verify that all three options are present and valid
|
|
before connecting using the SSU2 protocol.
|
|
|
|
When published as "SSU" with "s", "i", and "v" options,
|
|
the router must accept incoming connections on that host and port
|
|
for both SSU and SSU2 protocols, and automatically detect the protocol
|
|
version.
|
|
|
|
When published as "SSU2" with "s", "i", and "v" options,
|
|
the router accepts incoming connections on that host and port
|
|
for the SSU2 protocol only.
|
|
|
|
If a router supports both SSU1 and SSU2 connections but
|
|
does not implement automatic version detection for incoming connections,
|
|
it must advertise both "SSU" and "SSU2" addresses, and include
|
|
the SSU2 options in the "SSU2" address only.
|
|
The router should set a lower cost value (higher priority)
|
|
in the "SSU2" address than the "SSU" address, so SSU2 is preferred.
|
|
|
|
If multiple SSU2 RouterAddresses (either as "SSU" or "SSU2") are published
|
|
in the same RouterInfo (for additional IP addresses or ports),
|
|
all addresses specifying the same port must contain the identical SSU2 options and values.
|
|
In particular, all must contain the same static key and iv.
|
|
|
|
|
|
|
|
Unpublished SSU2 Address
|
|
-------------------------
|
|
|
|
If Alice does not publish her SSU2 address (as "SSU" or "SSU2") for incoming connections,
|
|
she must publish a "SSU2" router address containing only her static key and SSU2 version,
|
|
so that Bob may validate the key after receiving Alice's RouterInfo in Session Confirmed part 2.
|
|
|
|
- s=(Base64 key)
|
|
As defined above for published addresses.
|
|
|
|
- v=2
|
|
As defined above for published addresses.
|
|
|
|
This router address will not contain "i", "host" or "port" options,
|
|
as these are not required for outbound SSU2 connections.
|
|
The published cost for this address does not strictly matter, as it is inbound only;
|
|
however, it may be helpful to other routers if the cost is set higher (lower priority)
|
|
than other addresses. The suggested value is 14.
|
|
|
|
Alice may also simply add the "s" and "v" options to an existing published "SSU" address.
|
|
|
|
|
|
|
|
Public Key and IV Rotation
|
|
--------------------------
|
|
|
|
Using the same static keys for NTCP2 and SSU2 is allowed, but not recommended.
|
|
|
|
Due to caching of RouterInfos, routers must not rotate the static public key or IV
|
|
while the router is up, whether in a published address or not. Routers must
|
|
persistently store this key and IV for reuse after an immediate restart, so incoming
|
|
connections will continue to work, and restart times are not exposed. Routers
|
|
must persistently store, or otherwise determine, last-shutdown time, so that
|
|
the previous downtime may be calculated at startup.
|
|
|
|
Subject to concerns about exposing restart times, routers may rotate this key or IV
|
|
at startup if the router was previously down for some time (several days at
|
|
least).
|
|
|
|
If the router has any published SSU2 RouterAddresses (as SSU or SSU2), the
|
|
minimum downtime before rotation should be much longer, for example one month,
|
|
unless the local IP address has changed or the router "rekeys".
|
|
|
|
If the router has any published SSU RouterAddresses, but not SSU2 (as SSU or
|
|
SSU2) the minimum downtime before rotation should be longer, for example one
|
|
day, unless the local IP address has changed or the router "rekeys". This
|
|
applies even if the published SSU address has introducers.
|
|
|
|
If the router does not have any published RouterAddresses (SSU, SSU2, or
|
|
SSU), the minimum downtime before rotation may be as short as two hours, even
|
|
if the IP address changes, unless the router "rekeys".
|
|
|
|
If the router "rekeys" to a different Router Hash, it should generate a new
|
|
noise key and IV as well.
|
|
|
|
Implementations must be aware that changing the static public key or IV will prohibit
|
|
incoming SSU2 connections from routers that have cached an older RouterInfo.
|
|
RouterInfo publishing, tunnel peer selection (including both OBGW and IB
|
|
closest hop), zero-hop tunnel selection, transport selection, and other
|
|
implementation strategies must take this into account.
|
|
|
|
IV rotation is subject to identical rules as key rotation, except that IVs are not present
|
|
except in published RouterAddresses, so there is no IV for hidden or firewalled
|
|
routers. If anything changes (version, key, options?) it is recommended that
|
|
the IV change as well.
|
|
|
|
Note: The minimum downtime before rekeying may be modified to ensure network
|
|
health, and to prevent reseeding by a router down for a moderate amount of
|
|
time.
|
|
|
|
|
|
|
|
|
|
Identity Hiding
|
|
```````````````
|
|
Deniability is not a goal. See overview above.
|
|
|
|
Each pattern is assigned properties describing the confidentiality supplied to
|
|
the initiator's static public key, and to the responder's static public key.
|
|
The underlying assumptions are that ephemeral private keys are secure, and that
|
|
parties abort the handshake if they receive a static public key from the other
|
|
party which they don't trust.
|
|
|
|
This section only considers identity leakage through static public key fields
|
|
in handshakes. Of course, the identities of Noise participants might be
|
|
exposed through other means, including payload fields, traffic analysis, or
|
|
metadata such as IP addresses.
|
|
|
|
Alice: (8) Encrypted with forward secrecy to an authenticated party.
|
|
|
|
Bob: (3) Not transmitted, but a passive attacker can check candidates for the
|
|
responder's private key and determine whether the candidate is correct.
|
|
|
|
Bob publishes his static public key in the netdb. Alice may not, but must include it in the RI
|
|
sent to Bob.
|
|
|
|
|
|
|
|
|
|
Inbound Packet Handling
|
|
==========================
|
|
|
|
In SSU 1, inbound packet classification is difficult, because there is no
|
|
header to indicate session number. Routers must first match the source IP and port
|
|
to an existing peer state, and if not found, attempt multiple decryptions with different
|
|
keys to find the appropriate peer state or start a new one.
|
|
In the event that the source IP or port for an existing session changes,
|
|
possibly due to NAT behavior
|
|
the router may use expensive heuristics to attempt to match the packet to an existing session
|
|
and recover the contents.
|
|
|
|
SSU 2 is designed to minimize the inbound packet classification effort while maintaining
|
|
DPI resistance and other on-path threats. The session number is included in the header
|
|
for all message types, and obfuscated using AES with a known key and IV.
|
|
Additionally, the message type is also included in the header
|
|
(encrypted with header protection to a known key and then obfuscated with AES)
|
|
and may be used for additional classification.
|
|
In no case should a trial DH operation be necessary to classify a packet.
|
|
|
|
For almost all messages from all peers, the AES key and IV are the destination router's
|
|
router hash and IV as published in the netdb.
|
|
|
|
The only exceptions are the first messages sent from Bob to Alice (Session Created or Retry)
|
|
where Alice's router hash is not yet known to Bob. In these cases, Bob's router hash
|
|
and IV are used.
|
|
|
|
Therefore, the recommended processing steps are:
|
|
|
|
1) Remove the AES obfuscation to recover the session ID. If known, use that session
|
|
for further processing.
|
|
2) Remove the header protection to recover the version, net ID, message type,
|
|
and packet number fields. If all are sensible, and the message type is 0 (Session Request),
|
|
create a new session and use that session for further processing.
|
|
3) Look up a pending outbound session by the source IP/port of the packet;
|
|
if found, remove the session ID obfuscation using Bob's router hash and IV,
|
|
verify the session ID matches, and use that pending session for further processing.
|
|
|
|
|
|
Issues
|
|
--------
|
|
|
|
If Relay and Peer Test messages are allowed outside of a session, they may also require
|
|
additional processing steps to classify them.
|
|
|
|
|
|
|
|
Version Detection
|
|
--------------------
|
|
|
|
It may not be possible to efficiently detect if incoming packets are version 1 or 2 on the same inbound port.
|
|
The steps above may make sense to do before SSU 1 processing, to avoid attempting trial DH operations
|
|
using both protocol versions.
|
|
|
|
TBD if required.
|
|
|
|
|
|
|
|
Variants, Fallbacks, and General Issues
|
|
=======================================
|
|
|
|
TBD
|
|
|
|
|
|
|
|
Packet Overhead Analysis
|
|
=========================
|
|
|
|
Assumes IPv4, not including extra padding, not including IP and UDP header sizes.
|
|
Padding is mod-16 padding for SSU 1 only.
|
|
|
|
SSU 1
|
|
|
|
================== =========== ===== ====== ======= ====== =====
|
|
Message Header+MAC Keys Data Padding Total Notes
|
|
================== =========== ===== ====== ======= ====== =====
|
|
Session Request 40 256 5 3 304 Incl. extended options
|
|
Session Created 37 256 79 1 336 Incl. 64 byte Ed25519 sig
|
|
Session Confirmed 37 462 13 512 Incl. 391 byte ident and 64 byte sig
|
|
Data (RI) 37 1014 1051 Incl. 5 byte I2NP header, 1000 byte RI
|
|
Data (1 full msg) 37 14 51 Incl. 5 byte I2NP header
|
|
Total 2254
|
|
================== =========== ===== ====== ======= ====== =====
|
|
|
|
|
|
SSU 2
|
|
|
|
================== =========== ===== ====== ======= ====== =====
|
|
Message Header+MAC Keys Data Padding Total Notes
|
|
================== =========== ===== ====== ======= ====== =====
|
|
Session Request 48 32 7 87 DateTime block
|
|
Session Created 48 32 7 87 DateTime block
|
|
Session Confirmed 48 32 1003 1083 (2 macs) 1000 byte RI block
|
|
Data (1 full msg) 32 14 46
|
|
Total 1303
|
|
================== =========== ===== ====== ======= ====== =====
|
|
|
|
|
|
TODO UNLESS minimum packet size in Session Request and Created is enforced for PMTU.
|
|
|
|
|
|
|
|
|
|
|
|
References
|
|
==========
|
|
|
|
.. [ECIES]
|
|
{{ site_url('docs/spec/ecies', True) }}
|
|
|
|
.. [NetDB]
|
|
{{ site_url('docs/how/network-database', True) }}
|
|
|
|
.. [NOISE]
|
|
https://noiseprotocol.org/noise.html
|
|
|
|
.. [Nonces]
|
|
https://eprint.iacr.org/2019/624.pdf
|
|
|
|
.. [NTCP]
|
|
{{ site_url('docs/transport/ntcp', True) }}
|
|
|
|
.. [NTCP2]
|
|
{{ site_url('docs/spec/ntcp2', True) }}
|
|
|
|
.. [PMTU]
|
|
https://aura.abdn.ac.uk/bitstream/handle/2164/11693/tma2018_paper57.pdf
|
|
|
|
.. [Prop104]
|
|
{{ proposal_url('104') }}
|
|
|
|
.. [Prop109]
|
|
{{ proposal_url('109') }}
|
|
|
|
.. [RFC-2104]
|
|
https://tools.ietf.org/html/rfc2104
|
|
|
|
.. [RFC-3526]
|
|
https://tools.ietf.org/html/rfc3526
|
|
|
|
.. [RFC-5869]
|
|
https://tools.ietf.org/html/rfc5869
|
|
|
|
.. [RFC-6151]
|
|
https://tools.ietf.org/html/rfc6151
|
|
|
|
.. [RFC-6437]
|
|
https://tools.ietf.org/html/rfc6437
|
|
|
|
.. [RFC-7539]
|
|
https://tools.ietf.org/html/rfc7539
|
|
|
|
.. [RFC-7748]
|
|
https://tools.ietf.org/html/rfc7748
|
|
|
|
.. [RFC-7905]
|
|
https://tools.ietf.org/html/rfc7905
|
|
|
|
.. [RFC-9000]
|
|
https://datatracker.ietf.org/doc/html/rfc9000
|
|
|
|
.. [RFC-9001]
|
|
https://datatracker.ietf.org/doc/html/rfc9001
|
|
|
|
.. [RouterAddress]
|
|
{{ ctags_url('RouterAddress') }}
|
|
|
|
.. [RouterIdentity]
|
|
{{ ctags_url('RouterIdentity') }}
|
|
|
|
.. [SigningPublicKey]
|
|
{{ ctags_url('SigningPublicKey') }}
|
|
|
|
.. [SipHash]
|
|
https://www.131002.net/siphash/
|
|
|
|
.. [SSU]
|
|
{{ site_url('docs/transport/ssu', True) }}
|
|
|
|
.. [STS]
|
|
Diffie, W.; van Oorschot P. C.; Wiener M. J., Authentication and
|
|
Authenticated Key Exchanges
|
|
|
|
.. [Ticket1112]
|
|
https://{{ i2pconv('trac.i2p2.i2p') }}/ticket/1112
|
|
|
|
.. [Ticket1849]
|
|
https://{{ i2pconv('trac.i2p2.i2p') }}/ticket/1849
|
|
|
|
.. [WireGuard]
|
|
https://www.wireguard.com/protocol/
|