RFC 8489
Session Traversal Utilities for NAT (STUN)
Session Traversal Utilities for NAT (STUN) ๐ฆ
okay so bestie, this is RFC 8489 ๐ It's an Internet Standards Track doc from the IETF (Internet Engineering Task Force), published February 2020. It's giving official protocol energy โจ The authors are M. Petit-Huguenin (Impedance Mismatch), G. Salgueiro (Cisco), J. Rosenberg (Five9), D. Wing (Citrix), R. Mahy (Unaffiliated), and P. Matthews (Nokia) ๐ซถ It's also the ISSN 2070-1721 one, and it obsoletes RFC 5389, so that older version is officially replaced now ๐
Abstract ๐ธ
okay so Session Traversal Utilities for NAT (STUN) is a protocol that acts as a tool for other protocols dealing with NAT traversal ๐ง An endpoint can use it to find out the IP address and port a NAT allocated to it. It can also check connectivity between two endpoints, and it works as a keep-alive to keep NAT bindings alive ๐ฅ The best part is that STUN works with tons of existing NATs and doesn't need any special behavior from them. no cap, that's so iconic ๐
STUN is not a NAT traversal solution by itself ๐ It's a tool you use inside a NAT traversal solution, so think of it as a helper, not the whole main character ๐
This document obsoletes RFC 5389 โจ
Status of This Memo ๐
This is an Internet Standards Track document ๐
It's a product of the IETF, and it represents the consensus of the IETF community ๐ซถ It got public review and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more info on Internet Standards, check out Section 2 of RFC 7841 ๐
For the current status of this document, any errata, and how to give feedback, go to https://www.rfc-editor.org/info/rfc8489 ๐ฆ
Copyright Notice ๐
Copyright (c) 2020 IETF Trust and the persons identified as the document authors. All rights reserved ๐
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they stand on the date this document was published. Please read these carefully, bestie, because they explain your rights and restrictions for this document ๐ Any Code Components pulled out of this document must include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions. They come without warranty, as described in the Simplified BSD License โ ๏ธ
Table of Contents ๐ง
1. Introduction ....................................................4
2. Overview of Operation ...........................................5
3. Terminology .....................................................7
4. Definitions .....................................................7
5. STUN Message Structure ..........................................9
6. Base Protocol Procedures .......................................11
6.1. Forming a Request or an Indication ........................11
6.2. Sending the Request or Indication .........................12
6.2.1. Sending over UDP or DTLS-over-UDP ..................13
6.2.2. Sending over TCP or TLS-over-TCP ...................14
6.2.3. Sending over TLS-over-TCP or DTLS-over-UDP .........15
6.3. Receiving a STUN Message ..................................16
6.3.1. Processing a Request ...............................17
6.3.1.1. Forming a Success or Error Response .......17
6.3.1.2. Sending the Success or Error Response .....18
6.3.2. Processing an Indication ...........................18
6.3.3. Processing a Success Response ......................19
6.3.4. Processing an Error Response .......................19
7. FINGERPRINT Mechanism ..........................................20
8. DNS Discovery of a Server ......................................20
8.1. STUN URI Scheme Semantics .................................21
9. Authentication and Message-Integrity Mechanisms ................22
9.1. Short-Term Credential Mechanism ...........................23
9.1.1. HMAC Key ...........................................23
9.1.2. Forming a Request or Indication ....................23
9.1.3. Receiving a Request or Indication ..................23
9.1.4. Receiving a Response ...............................25
9.1.5. Sending Subsequent Requests ........................25
9.2. Long-Term Credential Mechanism ............................26
9.2.1. Bid-Down Attack Prevention .........................27
9.2.2. HMAC Key ...........................................27
9.2.3. Forming a Request ..................................28
9.2.3.1. First Request .............................28
9.2.3.2. Subsequent Requests .......................29
9.2.4. Receiving a Request ................................29
9.2.5. Receiving a Response ...............................31
10. ALTERNATE-SERVER Mechanism ....................................33
11. Backwards Compatibility with RFC 3489 .........................34
12. Basic Server Behavior .........................................34
13. STUN Usages ...................................................35
14. STUN Attributes ...............................................36
14.1. MAPPED-ADDRESS ...........................................37
14.2. XOR-MAPPED-ADDRESS .......................................38
14.3. USERNAME .................................................39
14.4. USERHASH .................................................40
14.5. MESSAGE-INTEGRITY ........................................40
14.6. MESSAGE-INTEGRITY-SHA256 .................................41
14.7. FINGERPRINT ..............................................41
14.8. ERROR-CODE ...............................................42
14.9. REALM ....................................................44
14.10. NONCE ...................................................44
14.11. PASSWORD-ALGORITHMS .....................................44
14.12. PASSWORD-ALGORITHM ......................................45
14.13. UNKNOWN-ATTRIBUTES ......................................45
14.14. SOFTWARE ................................................46
14.15. ALTERNATE-SERVER ........................................46
14.16. ALTERNATE-DOMAIN ........................................46
15. Operational Considerations ....................................47
16. Security Considerations .......................................47
16.1. Attacks against the Protocol .............................47
16.1.1. Outside Attacks ...................................47
16.1.2. Inside Attacks ....................................48
16.1.3. Bid-Down Attacks ..................................48
16.2. Attacks Affecting the Usage ..............................50
16.2.1. Attack I: Distributed DoS (DDoS) against a
Target ............................................51
16.2.2. Attack II: Silencing a Client .....................51
16.2.3. Attack III: Assuming the Identity of a Client .....52
16.2.4. Attack IV: Eavesdropping ..........................52
16.3. Hash Agility Plan ........................................52
17. IAB Considerations ............................................53
18. IANA Considerations ...........................................53
18.1. STUN Security Features Registry ..........................53
18.2. STUN Methods Registry ....................................54
18.3. STUN Attributes Registry .................................54
18.3.1. Updated Attributes ................................55
18.3.2. New Attributes ....................................55
18.4. STUN Error Codes Registry ................................56
18.5. STUN Password Algorithms Registry ........................56
18.5.1. Password Algorithms ...............................57
18.5.1.1. MD5 ......................................57
18.5.1.2. SHA-256 ..................................57
18.6. STUN UDP and TCP Port Numbers ............................57
19. Changes since RFC 5389 ........................................57
20. References ....................................................58
20.1. Normative References .....................................58
20.2. Informative References ...................................61
Appendix A. C Snippet to Determine STUN Message Types ............64
Appendix B. Test Vectors .........................................64
B.1. Sample Request with Long-Term Authentication with
MESSAGE-INTEGRITY-SHA256 and USERHASH .....................65
Acknowledgements ..................................................66
Contributors ......................................................66
Authors' Addresses ................................................67
1. Introduction โจ
okay so this spec defines Session Traversal Utilities for NAT (STUN), and it's a tool for dealing with Network Address Translators (NATs) ๐ง It gives an endpoint a way to find out the IP address and port that a NAT allocated, matching its private IP address and port ๐ฆ It also gives endpoints a way to keep a NAT binding alive ๐ With some extensions, STUN can do connectivity checks between two endpoints [RFC8445] or relay packets between two endpoints [RFC5766] ๐ฅ
Staying true to its tool nature, this spec defines an extensible packet format, defines how it operates over several transport protocols, and provides two forms of authentication ๐
STUN is meant to be used in the context of one or more NAT traversal solutions ๐ These solutions are called "STUN Usages" โจ Each usage describes how STUN gets used to achieve the NAT traversal solution ๐ Usually, a usage says when STUN messages get sent, which optional attributes to include, what server gets used, and what authentication mechanism is to be used ๐ซถ Interactive Connectivity Establishment (ICE) [RFC8445] is one usage of STUN ๐ SIP Outbound [RFC5626] is another usage of STUN ๐ In some cases, a usage will require extensions to STUN ๐ A STUN extension can come in the form of new methods, attributes, or error response codes ๐ More info on STUN Usages is in Section 13 ๐
2. Overview of Operation โจ
This section is descriptive only. ๐
/-----\
// STUN \\
| Server |
\\ //
\-----/
+--------------+ Public Internet
................| NAT 2 |.......................
+--------------+
+--------------+ Private Network 2
................| NAT 1 |.......................
+--------------+
/-----\
// STUN \\
| Client |
\\ // Private Network 1
\-----/
Figure 1: One Possible STUN Configuration
okay so bestie, look at Figure 1 ๐ฆ this is one possible STUN setup, and it's giving clean layout. There are two entities (called STUN agents) that implement the STUN protocol. The lower agent in the figure is the client, chilling on private network 1. That network connects to private network 2 through NAT 1, and private network 2 connects to the public Internet through NAT 2. The upper agent is the server, and it lives on the public Internet ๐
STUN is a client-server protocol, and it supports two types of transactions ๐ The first is a request/response transaction, where a client sends a request to a server and the server sends back a response. The second is an indication transaction, where either agent (client or server) sends an indication and it generates no response. Both types include a transaction ID, which is a randomly selected 96-bit number โจ For request/response transactions, that ID lets the client match the response to the request that made it. For indications, the transaction ID is just a debugging aid ๐
Every STUN message starts with a fixed header that has a method, a class, and the transaction ID. The method tells you which request or indication this is. This specification defines just one method, Binding, but other methods are expected to be defined in other documents ๐ง The class tells you whether the message is a request, a success response, an error response, or an indication. After the fixed header come zero or more attributes, which are Type-Length-Value extensions that carry extra info for that specific message ๐
This document defines a single method called "Binding" ๐ The Binding method can be used in request/response transactions or in indication transactions. In request/response transactions, it can be used to find out the particular binding a NAT has allocated to a STUN client. In either kind of transaction, it can also be used to keep those bindings alive ๐ซถ
Here's the Binding flow, iykyk. A Binding request goes from a STUN client to a STUN server. When it arrives, it may have passed through one or more NATs between them (in Figure 1, there are two). As the request passes through a NAT, the NAT modifies the source transport address (that's the source IP address and source port) of the packet. So the source transport address the server receives will be the public IP address and port created by the NAT closest to the server. This is called a "reflexive transport address" ๐ฆ The STUN server copies that source transport address into an XOR-MAPPED-ADDRESS attribute in the Binding response and sends the response back to the client. On the way back through a NAT, the NAT modifies the destination transport address in the IP header, but the transport address inside the XOR-MAPPED-ADDRESS attribute in the body stays untouched ๐ So the client can learn its reflexive transport address, the one allocated by the outermost NAT with respect to the STUN server. Main character energy, literally ๐
Some usages have to multiplex STUN with other protocols (e.g., [RFC8445] and [RFC5626]). In those usages, there has to be a way to inspect a packet and tell whether it's a STUN packet or not. STUN gives you three fields in the STUN header with fixed values that can be used for this purpose ๐ธ If that's not enough, STUN packets can also contain a FINGERPRINT value, which can further be used to tell packets apart ๐ฅ
STUN defines a set of optional procedures that a usage can choose to use, called "mechanisms" ๐ These include DNS discovery, a redirection technique to an alternate server, a fingerprint attribute for demultiplexing, and two authentication and message-integrity exchanges. The authentication mechanisms revolve around a username, a password, and a message-integrity value. Two of them, the long-term credential mechanism and the short-term credential mechanism, are defined in this specification. Each usage specifies which mechanisms are allowed with that usage ๐
In the long-term credential mechanism, the client and server share a pre-provisioned username and password, and they do a digest challenge/response exchange inspired by the one defined for HTTP [RFC7616] but different in the details ๐ In the short-term credential mechanism, the client and server swap a username and password through some out-of-band method before the STUN exchange. For example, in the ICE usage [RFC8445], the two endpoints use out-of-band signaling to exchange a username and password. These are used to integrity protect and authenticate the request and response. And there's no challenge or nonce used, so no extra back-and-forth ๐ซง
3. Terminology ๐
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here ๐โจ
4. Definitions ๐
Okay, let's get the vocab down so we're on the same page, bestie ๐ซถ
STUN Agent: A STUN agent is an entity that implements the STUN protocol. The entity can be either a STUN client or a STUN server. ๐ง
STUN Client: A STUN client is an entity that sends STUN requests and receives STUN responses and STUN indications. A STUN client can also send indications. In this specification, the terms "STUN client" and "client" are synonymous. ๐ฆ
STUN Server: A STUN server is an entity that receives STUN requests and STUN indications and that sends STUN responses. A STUN server can also send indications. In this specification, the terms "STUN server" and "server" are synonymous. ๐
Transport Address: The combination of an IP address and port number (such as a UDP or TCP port number). ๐ธ
Reflexive Transport Address: A transport address learned by a client that identifies that client as seen by another host on an IP network, typically a STUN server. When there is an intervening NAT between the client and the other host, the reflexive transport address represents the mapped address allocated to the client on the public side of the NAT. Reflexive transport addresses are learned from the mapped address attribute (MAPPED-ADDRESS or XOR-MAPPED-ADDRESS) in STUN responses. ๐
Mapped Address: Same meaning as reflexive address. This term is retained only for historic reasons and due to the naming of the MAPPED-ADDRESS and XOR-MAPPED-ADDRESS attributes. ๐
Long-Term Credential: A username and associated password that represent a shared secret between client and server. Long-term credentials are generally granted to the client when a subscriber enrolls in a service and persist until the subscriber leaves the service or explicitly changes the credential. ๐
Long-Term Password: The password from a long-term credential. ๐
Short-Term Credential: A temporary username and associated password that represent a shared secret between client and server. Short-term credentials are obtained through some kind of protocol mechanism between the client and server, preceding the STUN exchange. A short-term credential has an explicit temporal scope, which may be based on a specific amount of time (such as 5 minutes) or on an event (such as termination of a Session Initiation Protocol (SIP) [RFC3261] dialog). The specific scope of a short-term credential is defined by the application usage. โณ
Short-Term Password: The password component of a short-term credential. ๐
STUN Indication: A STUN message that does not receive a response. ๐ฆ
Attribute: The STUN term for a Type-Length-Value (TLV) object that can be added to a STUN message. Attributes are divided into two types: comprehension-required and comprehension-optional. STUN agents can safely ignore comprehension-optional attributes they don't understand, but they cannot successfully process a message if it contains comprehension-required attributes that are not understood. ๐งฉ
RTO: Retransmission TimeOut, which defines the initial period of time between transmission of a request and the first retransmit of that request. โฐ
5. STUN Message Structure โจ
okay bestie, so STUN messages are encoded in binary using network order, which is big-endian. That means the most significant byte or octet goes first ๐ The full transmission order is in Appendix B of [RFC0791]. Unless it says otherwise, numeric constants are in decimal (base 10) ๐ข
Every STUN message is a 20-byte header followed by zero or more attributes ๐ The header holds the message type, the message length, the magic cookie, and the transaction ID ๐
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0| STUN Message Type | Message Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Magic Cookie |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Transaction ID (96 bits) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 2: Format of STUN Message Header ๐ฆ
The most significant 2 bits of every STUN message MUST be zeroes ๐ This is what lets you tell STUN packets apart from other protocols when STUN is multiplexed with them on the same port ๐
The message type tells you the message class (request, success response, error response, or indication) and the message method (the main job of the message) ๐ง There are four message classes, but there are only two kinds of transactions in STUN: request/response transactions (a request message plus a response message) and indication transactions (just one indication message). Response classes are split into error and success responses so the STUN message can be processed quickly โก
The STUN Message Type field breaks down like this:
0 1
2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
|M |M |M|M|M|C|M|M|M|C|M|M|M|M|
|11|10|9|8|7|1|6|5|4|0|3|2|1|0|
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 3: Format of STUN Message Type Field ๐
Here the bits in the STUN Message Type field go from most significant (M11) down to least significant (M0). M11 through M0 are a 12-bit encoding of the method, and C1 and C0 are a 2-bit encoding of the class. A class of 0b00 is a request, 0b01 is an indication, 0b10 is a success response, and 0b11 is an error response. This specification defines just one method, Binding ๐ธ The method and class are orthogonal, which means every method can have a request, success response, error response, and indication all at once. Extensions that define new methods MUST indicate which classes are permitted for that method ๐
For example, a Binding request has class=0b00 (request) and method=0b000000000001 (Binding), and it gets encoded into the first 16 bits as 0x0001. A Binding response has class=0b10 (success response) and method=0b000000000001, and it gets encoded into the first 16 bits as 0x0101 โจ
Note: This unfortunate encoding is due to assignment of values in [RFC3489] that did not consider encoding indication messages, success responses, and errors responses using bit fields. ๐
The Magic Cookie field MUST contain the fixed value 0x2112A442 in network byte order ๐ In [RFC3489], those 32 bits were part of the transaction ID. Putting the magic cookie in this spot lets a server detect whether the client will understand certain attributes that were added to STUN by [RFC5389]. It also helps tell STUN packets apart from packets of other protocols when STUN is multiplexed with them on the same port ๐ซถ
The transaction ID is a 96-bit identifier that uniquely identifies STUN transactions ๐ For request/response transactions, the STUN client picks the transaction ID for the request, and the server echoes it back in the response. For indications, the agent sending the indication picks it. Its main job is matching requests with responses, though it also plays a small part in preventing certain kinds of attacks ๐ก๏ธ The server also uses the transaction ID as a key to identify each transaction uniquely across all clients. So the transaction ID MUST be uniformly and randomly chosen from the interval 0 .. 2**96-1 and MUST be cryptographically random ๐ฒ Resends of the same request reuse the same transaction ID, but the client MUST choose a new transaction ID for new transactions, unless the new request is bit-wise identical to the previous request and sent from the same transport address to the same IP address. Success and error responses MUST carry the same transaction ID as their corresponding request. When an agent is acting as a STUN server and a STUN client on the same port, the transaction IDs in the requests it sends have no relationship to the transaction IDs in the requests it receives ๐
The message length MUST contain the size of the message in bytes, not including the 20-byte STUN header ๐ All STUN attributes are padded to a multiple of 4 bytes, so the last 2 bits of this field are always zero. That's another handy way to tell STUN packets apart from packets of other protocols ๐
After the fixed part of the header come zero or more attributes. Each attribute is TLV (Type-Length-Value) encoded ๐งฉ The details of the encoding, and the attributes themselves, are in Section 14 ๐
6. Base Protocol Procedures ๐
This section lays out the base procedures of the STUN protocol. It covers how messages are formed, how they get sent, and how they're processed when they arrive ๐ฌ It also defines the detailed processing for the Binding method. Other sections in this document describe optional procedures that a usage may choose to use in certain situations. Other documents may define other STUN extensions by adding new methods, new attributes, or new error response codes ๐
6.1. Forming a Request or an Indication ๐ง
When you're putting together a request or indication, the agent MUST follow the rules in Section 5 when it creates the header ๐ On top of that, the message class MUST be either "Request" or "Indication" (whichever fits), and the method must be either Binding or some method defined in another document ๐
Then the agent adds any attributes the method or the usage specifies. For example, some usages may say the agent has to use an authentication method (Section 9) or the FINGERPRINT attribute (Section 7) ๐
If the agent is sending a request, it SHOULD add a SOFTWARE attribute to the request. Agents MAY include a SOFTWARE attribute in indications, depending on the method. Extensions to STUN should discuss whether SOFTWARE is useful in new indications. Heads up, though: including a SOFTWARE attribute may have security implications, so check Section 16.1.2 for details ๐
For the Binding method with no authentication, no attributes are required unless the usage specifies otherwise โจ
All STUN messages sent over UDP or DTLS-over-UDP [RFC6347] SHOULD be less than the path MTU, if it's known ๐ฆ
If the path MTU is unknown for UDP, messages SHOULD be the smaller of 576 bytes and the first-hop MTU for IPv4 [RFC1122], and 1280 bytes for IPv6 [RFC8200]. This value is the overall size of the IP packet. So for IPv4, the actual STUN message would need to be less than 548 bytes (576 minus the 20-byte IP header, minus the 8-byte UDP header, assuming no IP options are used) ๐งฎ
If the path MTU is unknown for DTLS-over-UDP, the rules in the previous paragraph need to be adjusted to account for the size of the (13-byte) DTLS Record header, the Message Authentication Code (MAC) size, and the padding size ๐ง
STUN has no way to handle the case where the request is smaller than the MTU but the response is larger than the MTU. It isn't expected to be a problem for STUN ๐ค The MTU limitation is a SHOULD, not a MUST, to cover cases where STUN itself is being used to probe for MTU characteristics [RFC5780]. See also [STUN-PMTUD] for a framework that uses STUN to add Path MTU Discovery to protocols that lack such a mechanism ๐ Outside of this or similar applications, the MTU constraint MUST be followed ๐จ
6.2. Sending the Request or Indication ๐ค
Next, the agent sends the request or indication ๐ This document specifies how to send STUN messages over UDP, TCP, TLS-over-TCP, or DTLS-over-UDP. Other transport protocols may be added in the future ๐ธ The STUN Usage must specify which transport protocol is used and how the agent works out the IP address and port of the recipient. Section 8 describes a DNS-based method of finding the IP address and port of a server, which a usage may choose to use ๐บ๏ธ
At any time, a client MAY have multiple outstanding STUN requests with the same STUN server (that is, multiple transactions in progress, each with a different transaction ID) ๐ Absent other limits on the rate of new transactions (such as those specified by ICE for connectivity checks, or when STUN is run over TCP), a client SHOULD limit itself to ten outstanding transactions to the same server ๐
6.2.1. Sending over UDP or DTLS-over-UDP
okay so bestie, when STUN runs over UDP or DTLS-over-UDP [RFC7350] ๐ฆ, the network is allowed to just... drop the message ๐ญ. So the way STUN gets reliability for request/response transactions is that the client app literally resends its own request ๐. Indications? Not retransmitted at all ๐, so indication transactions over UDP or DTLS-over-UDP are not reliable. Know your limits, babe ๐ซถ.
A client SHOULD retransmit a STUN request message starting with an interval of RTO ("Retransmission TimeOut"), doubling after each retransmission โจ. The RTO is basically an estimate of the round-trip time (RTT) ๐ธ, and it gets computed as described in [RFC6298], with two exceptions ๐. First, the initial value for RTO SHOULD be greater than or equal to 500 ms. The exceptions to this "SHOULD" are when other mechanisms are used to derive congestion thresholds (like the ones defined in ICE for fixed-rate streams) or when STUN is used in non-Internet environments with known network capacities ๐. On fixed-line access links, a value of 500 ms is RECOMMENDED ๐ . Second, the value of RTO SHOULD NOT be rounded up to the nearest second ๐ โโ๏ธ. Rather, a 1 ms accuracy SHOULD be maintained ๐. Just like TCP, the usage of Karn's algorithm is RECOMMENDED [KARN87] ๐ง. When applied to STUN, it means RTT estimates SHOULD NOT be computed from STUN transactions that result in the retransmission of a request. Don't measure the RTT off a request you already resent, it's giving confusing data ๐.
The value for RTO SHOULD be cached by a client after the completion of the transaction and used as the starting value for RTO for the next transaction to the same server (based on equality of IP address) ๐. The value SHOULD be considered stale and discarded if no transactions have occurred to the same server in the last 10 minutes โฐ. Mood: stale values are not it ๐ฅ.
Retransmissions continue until a response is received or until a total of Rc requests have been sent ๐. Rc SHOULD be configurable and SHOULD have a default of 7. If, after the last request, a duration equal to Rm times the RTO has passed without a response (giving ample time to get a response if only this final request actually succeeds), the client SHOULD consider the transaction to have failed ๐ค. Rm SHOULD be configurable and SHOULD have a default of 16. A STUN transaction over UDP or DTLS-over-UDP is also considered failed if there has been a hard ICMP error [RFC1122] ๐จ. For example, assuming an RTO of 500 ms, requests would be sent at times 0 ms, 500 ms, 1500 ms, 3500 ms, 7500 ms, 15500 ms, and 31500 ms. If the client has not received a response after 39500 ms, the client will consider the transaction to have timed out โ๐ฆ.
0 ms 500 ms 1500 ms 3500 ms 7500 ms 15500 ms 31500 ms 39500 ms
|---------|----------|----------|----------|----------|----------|----------|
Request 1 Request 2 Request 3 Request 4 Request 5 Request 6 Request 7 Timeout
6.2.2. Sending over TCP or TLS-over-TCP
For TCP and TLS-over-TCP [RFC8446] ๐, the client opens a TCP connection to the server ๐.
In some usages of STUN, STUN is the only protocol over the TCP connection. In that case, it can be sent without any extra framing or demultiplexing ๐. In other usages, or with other extensions, it may be multiplexed with other data over a TCP connection. In that case, STUN MUST be run on top of some kind of framing protocol, specified by the usage or extension, which lets the agent pull out complete STUN messages and complete application-layer messages ๐. The STUN service running on the well-known port or ports discovered through the DNS procedures in Section 8 is for STUN alone, and not for STUN multiplexed with other data ๐ง. So no framing protocols are used in connections to those servers ๐ โโ๏ธ. When additional framing is used, the usage will specify how the client knows to apply it and what port to connect to. For example, for ICE connectivity checks, this info is learned through out-of-band negotiation between client and server ๐ค.
Reliability of STUN over TCP and TLS-over-TCP is handled by TCP itself, so there are no retransmissions at the STUN protocol level ๐ . However, for a request/response transaction, if the client has not received a response by Ti seconds after it sent the request message, it considers the transaction to have timed out โณ. Ti SHOULD be configurable and SHOULD have a default of 39.5 s. This value was chosen to equalize the TCP and UDP timeouts for the default initial RTO โ๏ธ.
Also, if the client is unable to establish the TCP connection, or the TCP connection is reset or fails before a response is received, any request/response transaction in progress is considered to have failed ๐.
The client MAY send multiple transactions over a single TCP (or TLS-over-TCP) connection, and it MAY send another request before receiving a response to the previous request ๐ง. The client SHOULD keep the connection open until it:
- has no further STUN requests or indications to send over that connection,
- has no plans to use any resources (such as a mapped address (MAPPED-ADDRESS or XOR-MAPPED-ADDRESS) or relayed address [RFC5766]) that were learned through STUN requests sent over that connection,
- if multiplexing other application protocols over that port, has finished using those other protocols,
- if using that learned port with a remote peer, has established communications with that remote peer, as is required by some TCP NAT traversal techniques (e.g., [RFC6544]).
The details of an eventual keep-alive mechanism are left to each STUN Usage ๐ซง. In any case, if a transaction fails because an idle TCP connection doesn't work anymore, the client SHOULD send a RST and try to open a new TCP connection ๐.
On the server end, the server SHOULD keep the connection open and let the client close it, unless the server has determined that the connection has timed out (for example, because the client disconnected from the network) ๐. Bindings learned by the client will remain valid in intervening NATs only while the connection remains open ๐. Only the client knows how long it needs the binding ๐. The server SHOULD NOT close a connection if a request was received over that connection for which a response was not sent ๐. A server MUST NOT ever open a connection back towards the client in order to send a response ๐ซ. Servers SHOULD follow best practices regarding connection management in cases of overload ๐งฏ.
6.2.3. Sending over TLS-over-TCP or DTLS-over-UDP
When STUN is run by itself over TLS-over-TCP or DTLS-over-UDP, the TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 and TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ciphersuites MUST be implemented (for compatibility with older versions of this protocol), except if deprecated by rules of a specific STUN usage ๐. Other ciphersuites MAY be implemented ๐. Note that STUN clients and servers that implement TLS version 1.3 [RFC8446] or subsequent versions are also required to implement mandatory ciphersuites from those specifications, and SHOULD disable usage of deprecated ciphersuites when they detect support for those specifications ๐ง. Perfect Forward Secrecy (PFS) ciphersuites MUST be preferred over non-PFS ciphersuites ๐. Ciphersuites with known weaknesses, such as those based on (single) DES and RC4, MUST NOT be used ๐ซ๐. Implementations MUST disable TLS-level compression ๐ โโ๏ธ.
These recommendations are just part of the recommendations in [BCP195] that implementations and deployments of a STUN Usage using TLS or DTLS MUST follow ๐.
When it receives the TLS Certificate message, the client MUST verify the certificate and inspect the site identified by the certificate ๐ต๏ธโโ๏ธ. If the certificate is invalid or revoked, or if it does not identify the appropriate party, the client MUST NOT send the STUN message or otherwise proceed with the STUN transaction ๐. The client MUST verify the identity of the server. To do that, it follows the identification procedures defined in [RFC6125], with a certificate containing an identifier of type DNS-ID or CN-ID, optionally with a wildcard character as the leftmost label, but not of type SRV-ID or URI-ID ๐ชช.
When STUN is run multiplexed with other protocols over a TLS-over-TCP connection or a DTLS-over-UDP association, the mandatory ciphersuites and TLS handling procedures operate as defined by those protocols ๐งฉ.
6.3. Receiving a STUN Message
This section specifies the processing of a STUN message ๐ฌ. The processing specified here is for STUN messages as defined in this specification. Additional rules for backwards compatibility are defined in Section 11, and those additional procedures are optional, so usages can elect to use them ๐ฆ. First, a set of processing operations is applied that is independent of the class ๐ง . This is followed by class-specific processing, described in the subsections that follow ๐.
When a STUN agent receives a STUN message, it first checks that the message obeys the rules of Section 5 ๐. It checks that the first two bits are 0, that the Magic Cookie field has the correct value, that the message length is sensible, and that the method value is a supported method. It checks that the message class is allowed for the particular method. If the message class is "Success Response" or "Error Response", the agent checks that the transaction ID matches a transaction that is still in progress. If the FINGERPRINT extension is being used, the agent checks that the FINGERPRINT attribute is present and contains the correct value. If any errors are detected, the message is silently discarded ๐คซ. In the case when STUN is being multiplexed with another protocol, an error may indicate that this is not really a STUN message; in this case, the agent should try to parse the message as a different protocol ๐.
The STUN agent then does any checks that are required by an authentication mechanism that the usage has specified (see Section 9) ๐.
Once the authentication checks are done, the STUN agent checks for unknown attributes and known-but-unexpected attributes in the message. Unknown comprehension-optional attributes MUST be ignored by the agent ๐. Known-but-unexpected attributes SHOULD be ignored by the agent ๐ . Unknown comprehension-required attributes cause processing that depends on the message class, and that is described below ๐.
At this point, further processing depends on the message class of the request ๐.
6.3.1. Processing a Request โจ
okay so, if the request has one or more unknown comprehension-required attributes, the server replies with an error response with an error code of 420 (Unknown Attribute). It also includes an UNKNOWN-ATTRIBUTES attribute listing those unknown comprehension-required attributes ๐
Otherwise, the server does any extra checking that the method or the specific usage needs. If all the checks pass, the server formulates a success response, as described below ๐
When this runs over UDP or DTLS-over-UDP, a request the server gets could be the first request of a transaction, or it could be a retransmission. The server MUST respond to retransmissions in a way that keeps this property: if the client gets the response to the retransmission and not the response to the original request, the overall state on the client and server is identical to the case where only the response to the original retransmission is received, or where both responses are received (in which case the client will use the first one). ๐ฆ The easiest way to meet this is for the server to remember all transaction IDs received over UDP or DTLS-over-UDP, and their corresponding responses, for the last 40 seconds. But this means the server has to hold state, which is inappropriate for any requests that are not authenticated ๐ญ Another way is to reprocess the request and recompute the response. This latter technique MUST only be applied to requests that are idempotent (a request is considered idempotent when the same request can be safely repeated without impacting the overall state of the system) and that result in the same success response for the same request. The Binding method is considered to be idempotent ๐ธ Also, note that there are certain rare network events that could cause the reflexive transport address value to change, which means a different mapped address could show up in different success responses. Extensions to STUN MUST discuss the implications of request retransmissions on servers that do not store transaction state. ๐ง
6.3.1.1. Forming a Success or Error Response
When forming the response (success or error), the server follows the rules of Section 6. The method of the response is the same as that of the request, and the message class is either "Success Response" or "Error Response" ๐
For an error response, the server MUST add an ERROR-CODE attribute containing the error code specified in the processing above. The reason phrase isn't fixed, but it SHOULD be something suitable for the error code โจ For certain errors, additional attributes get added to the message. These are spelled out in the description where the error code is specified. For example, for an error code of 420 (Unknown Attribute), the server MUST include an UNKNOWN-ATTRIBUTES attribute. Certain authentication errors also cause attributes to be added (see Section 9). Extensions may define other errors and/or additional attributes to add in error cases ๐
If the server authenticated the request using an authentication mechanism, then the server SHOULD add the appropriate authentication attributes to the response (see Section 9) ๐ฅ
The server also adds any attributes required by the specific method or usage. On top of that, the server SHOULD add a SOFTWARE attribute to the message ๐
For the Binding method, no additional checking is required unless the usage says otherwise. When forming the success response, the server adds an XOR-MAPPED-ADDRESS attribute to the response. This attribute contains the source transport address of the request message. For UDP or DTLS-over-UDP, that's the source IP address and source UDP port of the request message. For TCP and TLS-over-TCP, it's the source IP address and source TCP port of the TCP connection as seen by the server ๐
6.3.1.2. Sending the Success or Error Response
The response (success or error) gets sent over the same transport the request was received on. If the request came in over UDP or DTLS-over-UDP, the destination IP address and port of the response are the source IP address and port of the received request message. The source IP address and port of the response are equal to the destination IP address and port of the received request message. If the request came in over TCP or TLS-over-TCP, the response goes back on the same TCP connection the request was received on ๐ฆ
The server is allowed to send responses in a different order than it received the requests in โจ
6.3.2. Processing an Indication
If the indication contains unknown comprehension-required attributes, the indication is discarded and processing ceases ๐
Otherwise, the agent does any extra checking that the method or the specific usage needs. If all the checks pass, the agent then processes the indication. No response is generated for an indication ๐
For the Binding method, no additional checking or processing is required, unless the usage says otherwise. The mere receipt of the message by the agent has refreshed the bindings in the intervening NATs ๐ธ
Since indications are not re-transmitted over UDP or DTLS-over-UDP (unlike requests), there's no need to handle retransmissions of indications at the sending agent ๐ซถ
6.3.3. Processing a Success Response
If the success response contains unknown comprehension-required attributes, the response is discarded and the transaction is considered to have failed ๐ญ
Otherwise, the client does any extra checking that the method or the specific usage needs. If all the checks pass, the client then processes the success response ๐
For the Binding method, the client checks that the XOR-MAPPED-ADDRESS attribute is present in the response. The client also checks the address family specified. If it's an unsupported address family, the attribute SHOULD be ignored. If it's an unexpected but supported address family (for example, the Binding transaction was sent over IPv4, but the address family specified is IPv6), then the client MAY accept and use the value ๐
6.3.4. Processing an Error Response
If the error response contains unknown comprehension-required attributes, or if the error response does not contain an ERROR-CODE attribute, then the transaction is simply considered to have failed ๐
Otherwise, the client does any processing specified by the authentication mechanism (see Section 9). This may result in a new transaction attempt ๐
The processing at this point depends on the error code, the method, and the usage. The following are the default rules:
- If the error code is 300 through 399, the client SHOULD consider the transaction as failed unless the ALTERNATE-SERVER extension (Section 10) is being used.
- If the error code is 400 through 499, the client declares the transaction failed. In the case of
420(Unknown Attribute), the response should contain anUNKNOWN-ATTRIBUTESattribute that gives additional information. - If the error code is 500 through 599, the client MAY resend the request. Clients that do so MUST limit the number of times they do this. Unless a specific error code specifies a different value, the number of retransmissions SHOULD be limited to 4.
Any other error code causes the client to consider the transaction failed ๐
7. FINGERPRINT Mechanism โจ
This section describes an optional mechanism for STUN that helps tell STUN messages apart from packets of other protocols when the two are multiplexed on the same transport address ๐ This mechanism is optional, and a STUN Usage must describe if and when it's used. The FINGERPRINT mechanism is not backwards compatible with RFC 3489, so it can't be used in environments where that compatibility is required ๐ โโ๏ธ
In some usages, STUN messages are multiplexed on the same transport address as other protocols, such as the Real-Time Transport Protocol (RTP). To apply the processing described in Section 6, STUN messages must first be separated from the application packets ๐
Section 5 describes three fixed fields in the STUN header that can be used for this purpose. In some cases, though, those three fixed fields might not be enough ๐ค
When the FINGERPRINT extension is used, an agent includes the FINGERPRINT attribute in messages it sends to another agent. Section 14.7 describes the placement and value of this attribute ๐ง
When an agent receives what it believes is a STUN message, then, in addition to other basic checks, the agent also checks that the message contains a FINGERPRINT attribute and that the attribute contains the correct value. Section 6.3 describes when the FINGERPRINT check happens in the overall processing of a STUN message. This extra check helps the agent detect messages of other protocols that might otherwise look like STUN messages ๐
8. DNS Discovery of a Server
This section describes an optional procedure for STUN that lets a client use DNS to find the IP address and port of a server ๐ A STUN Usage must describe if and when this extension is used. To use this procedure, the client must know a STUN URI [RFC7064], and the usage must also describe how the client obtains this URI. Hard-coding a STUN URI into software is NOT RECOMMENDED, in case the domain name is lost or needs to change for legal or other reasons ๐
When a client wants to find a STUN server on the public Internet that accepts Binding request/response transactions, the STUN URI scheme is stun. When it wants to find a STUN server that accepts Binding request/response transactions over a TLS or DTLS session, the URI scheme is stuns ๐
The syntax of the stun and stuns URIs is defined in Section 3.1 of [RFC7064]. STUN Usages MAY define additional URI schemes ๐
8.1. STUN URI Scheme Semantics
okay so if the <host> part of a "stun" URI has an IP address in it, that address gets used directly to contact the server ๐ง but a "stuns" URI with an IP address in it MUST be rejected ๐ซ no exceptions bestie. a future STUN extension or usage might relax this, but only if it shows how to authenticate the STUN server and stop man-in-the-middle attacks ๐ต๏ธโโ๏ธ (that's a big ask and I respect it).
if the URI doesn't have an IP address, the domain name in the <host> part gets turned into a transport address using the SRV procedures from [RFC2782] ๐ธ the DNS SRV service name is whatever the <scheme> part says, and the protocol in the SRV lookup is the transport the client is gonna run STUN over: "udp" for UDP and "tcp" for TCP ๐
the procedures of RFC 2782 get followed to pick the server. RFC 2782 explains how a set of SRV records gets sorted and then tried, which is so iconic ๐ but it only says the client should "try to connect to the (protocol, address, service)" and doesn't say what happens when something fails ๐ญ so here's the add-on: if the STUN transaction times out without a response, the client SHOULD retry the request to the next server in the order defined by RFC 2782 ๐ that retry only works for request/response transmissions, since indications don't get a response or a timeout (no answer, no retry, that's just how it goes ๐คทโโ๏ธ).
also, instead of only asking for the A or the AAAA records of a domain name, a dual-stack IPv4/IPv6 client MUST query both and try the requests with all the IP addresses it gets back, as specified in [RFC8305] ๐ both tabs open, obsessed.
the default port for STUN requests is 3478, for both TCP and UDP ๐ the default port for STUN over TLS and STUN over DTLS requests is 5349 ๐ servers can run STUN over DTLS on the same port as STUN over UDP if the server software can tell whether the first message is a DTLS message or a STUN message ๐ฆ and servers can run STUN over TLS on the same port as STUN over TCP if the software can tell whether the first message is a TLS message or a STUN message โจ
administrators of STUN servers SHOULD use these ports in their SRV records for UDP and TCP ๐ and in every case, the port in DNS MUST reflect the one the server is actually listening on ๐ซถ no mismatch allowed, periodt.
if no SRV records get found, the client does both an A and an AAAA lookup of the domain name, as described in [RFC8305] ๐ท the result is a list of IP addresses, and each one can be contacted at the default port over UDP or TCP at the same time, no matter which STUN Usage it is ๐ซ for usages that need TLS, the client connects to those IP addresses using the default STUN over TLS port ๐ and for usages that need DTLS, it connects using the default STUN over DTLS port ๐ก๏ธ
9. Authentication and Message-Integrity Mechanisms โจ
okay this section is the security glow-up ๐ it defines two mechanisms that a client and server can use to get authentication and message integrity: the short-term credential mechanism and the long-term credential mechanism ๐ both of them are optional, and each usage has to say whether and when they get used. so clients and servers always know which mechanism (if any) to follow, just from knowing which usage is in play ๐ง for example, a STUN server on the public Internet that supports ICE wouldn't have any authentication, whereas the STUN server bit inside an agent doing connectivity checks would use short-term credentials ๐ you can get an overview of these two mechanisms in Section 2 ๐ธ
each mechanism spells out the extra processing it needs, on top of the processing from Section 6 ๐งฉ that extra processing happens in three spots: when forming a message, when receiving a message right after the basic checks are done, and when doing the detailed processing of error responses ๐
now, the big rule ๐จ agents MUST ignore all attributes that follow MESSAGE-INTEGRITY, except for the MESSAGE-INTEGRITY-SHA256 and FINGERPRINT attributes ๐ โโ๏ธ similarly, agents MUST ignore all attributes that follow the MESSAGE-INTEGRITY-SHA256 attribute if the MESSAGE-INTEGRITY attribute isn't present, except for the FINGERPRINT attribute ๐ read those twice bestie, they're load-bearing ๐ญ
9.1. Short-Term Credential Mechanism
the short-term credential mechanism assumes that, before the STUN transaction happens, the client and server already used some other protocol to swap a credential, which is a username and a password ๐๏ธ this credential is time-limited, and the usage decides what the time limit is ๐ฐ๏ธ for example, in the ICE usage [RFC8445], the two endpoints use out-of-band signaling to agree on a username and password, and those stay valid for the whole media session ๐
this credential gets used to make a message-integrity check in every request and in a lot of responses ๐ there's no challenge-and-response like in the long-term mechanism, so replay attacks are limited by the fact that the credential only lasts for a set time โณ clever, honestly.
9.1.1. HMAC Key
for short-term credentials, the Hash-Based Message Authentication Code (HMAC) key is defined like this ๐ซ
key = OpaqueString(password)
where the OpaqueString profile is defined in [RFC8265] ๐ง the encoding used is UTF-8 [RFC3629] ๐
9.1.2. Forming a Request or Indication
for a request or indication message, the agent MUST include the USERNAME, MESSAGE-INTEGRITY-SHA256, and MESSAGE-INTEGRITY attributes in the message ๐จ unless the agent already knows from some external mechanism which message integrity algorithm both agents support ๐ค in that case, either MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 MUST be included, along with USERNAME ๐ the HMAC for the MESSAGE-INTEGRITY attribute gets computed as described in Section 14.5, and the HMAC for the MESSAGE-INTEGRITY-SHA256 attribute gets computed as described in Section 14.6 ๐งฎ and note that the password is never included in the request or indication, so it never leaves the room ๐คซ
9.1.3. Receiving a Request or Indication
after the agent does the basic processing of a message, it runs the checks below in the order listed ๐
- if the message does not contain 1) a MESSAGE-INTEGRITY or a MESSAGE-INTEGRITY-SHA256 attribute and 2) a USERNAME attribute:
- if the message is a request, the server MUST reject the request with an error response ๐ โโ๏ธ this response MUST use an error code of 400 (Bad Request) ๐
- if the message is an indication, the agent MUST silently discard the indication ๐ซฅ
- if the USERNAME doesn't contain a username value that's currently valid within the server:
- if the message is a request, the server MUST reject the request with an error response, and this response MUST use an error code of 401 (Unauthenticated) ๐ช
- if the message is an indication, the agent MUST silently discard the indication ๐ซฅ
- if the MESSAGE-INTEGRITY-SHA256 attribute is present, compute the value for the message integrity as described in Section 14.6, using the password tied to the username ๐ if the MESSAGE-INTEGRITY-SHA256 attribute isn't present, use that same password to compute the value for the message integrity as described in Section 14.5 ๐ง if the result doesn't match the contents of the matching attribute (MESSAGE-INTEGRITY-SHA256 or MESSAGE-INTEGRITY):
- if the message is a request, the server MUST reject the request with an error response, and this response MUST use an error code of 401 (Unauthenticated) ๐ซ
- if the message is an indication, the agent MUST silently discard the indication ๐ซฅ
if these checks all pass, the agent carries on and processes the request or indication ๐ฅณ any response a server generates to a request that has a MESSAGE-INTEGRITY-SHA256 attribute MUST include the MESSAGE-INTEGRITY-SHA256 attribute, computed with the password used to authenticate the request ๐ any response a server generates to a request that only has a MESSAGE-INTEGRITY attribute MUST include the MESSAGE-INTEGRITY attribute, computed with the password used to authenticate the request ๐ this means only one of those attributes can show up in a response ๐ซฐ and the response MUST NOT contain the USERNAME attribute ๐
if any of the checks fail, a server MUST NOT include a MESSAGE-INTEGRITY-SHA256, MESSAGE-INTEGRITY, or USERNAME attribute in the error response ๐ญ the reason is that, in these failure cases, the server can't figure out the shared secret it needs to compute the MESSAGE-INTEGRITY-SHA256 or MESSAGE-INTEGRITY attributes ๐ซ
9.1.4. Receiving a Response
the client looks for the MESSAGE-INTEGRITY or the MESSAGE-INTEGRITY-SHA256 attribute in the response ๐ if it's there, and if the client only sent one of MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 in the request (because of the external indication in Section 9.1.2, or because this is a subsequent request as defined in Section 9.1.5), then the algorithm in the response has to match ๐งฉ otherwise, the response MUST be discarded ๐๏ธ
then the client computes the message integrity over the response, as defined in Section 14.5 for MESSAGE-INTEGRITY or Section 14.6 for MESSAGE-INTEGRITY-SHA256, using the same password it used for the request ๐งฎ if the result matches the contents of MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 respectively, the response is considered authenticated โ if it doesn't match, or if both MESSAGE-INTEGRITY and MESSAGE-INTEGRITY-SHA256 are absent, then what happens next depends on whether the request was sent over a reliable or an unreliable transport ๐ฆ
if the request was sent over an unreliable transport, the response MUST be discarded, as if it had never been received ๐ป that means retransmits, if they apply, will keep going ๐ and if all the responses received get discarded, then instead of signaling a timeout after ending the transaction, the layer MUST signal that the integrity protection was violated ๐จ
if the request was sent over a reliable transport, the response MUST be discarded, and the layer MUST immediately end the transaction and signal that the integrity protection was violated ๐ฅ no second chances, bestie.
9.1.5. Sending Subsequent Requests
a client sending subsequent requests to the same server MUST send only the MESSAGE-INTEGRITY-SHA256 or the MESSAGE-INTEGRITY attribute that matches the attribute received in the response to the initial request ๐ฏ and here, "same server" means the same IP address and port number, not just the same URI or the same SRV lookup result ๐งโโ๏ธ ๐
9.2. Long-Term Credential Mechanism โจ
okay so the long-term credential mechanism is giving "traditional login" energy ๐ it runs on a username and password that the client and server both share. It's called long-term because the credential gets handed out to a user and stays valid until that user stops being a subscriber or the credential gets changed. Basically the same username and password people already use to log in to things ๐
Since these usernames and passwords stick around for ages, replay prevention comes from a digest challenge ๐ก๏ธ Here's how it goes. The client starts by sending a request with no credentials and no integrity checks at all. The server says "nope" and rejects it, but it hands over a realm (which helps the user or agent pick the right username and password) and a nonce. The nonce gives limited replay protection. It's a cookie the server picks, encoded so it shows how long it's valid for or which client it's valid for. Only the server needs to understand what's inside the cookie, so don't worry about the client poking at it ๐ช
Next, the client retries. This time it includes its username, the realm, and it echoes back the nonce the server gave it. It also adds one of the message-integrity attributes from this document, which is an HMAC over the entire request, nonce included ๐ The server checks the nonce and the message integrity. If both match, the request is authenticated and everyone's happy ๐ If the nonce has expired, it's called "stale," and the server rejects the request again, this time with a fresh nonce โฐ
For later requests to the same server, the client reuses the nonce, username, realm, and password from before. That means requests keep going through without getting bounced, until the server decides the nonce is no longer valid. Then it rejects the request and sends a new nonce so the client can keep going ๐
Heads up bestie: the long-term credential mechanism cannot be used to protect indications, because indications can't be challenged ๐ โโ๏ธ Any usage that sends indications has to either use a short-term credential or skip authentication and message integrity for them. No exceptions, iykyk ๐
To show that it supports this spec, a server MUST prepend the NONCE attribute value with the string "obMatJos2", followed by the (4-character) base64 [RFC4648] encoding of the 24-bit STUN Security Features from Section 18.1 โจ Those 24 bits are packed into 3 bytes, where bit 0 is the most significant bit of the first byte and bit 23 is the least significant bit of the third byte. If no security features are being used, the server MUST encode a byte array with all 24 bits set to zero instead ๐ธ From here on, the "nonce cookie" means that full 13-character string tacked onto the front of the NONCE value ๐ง
nonce cookie = "obMatJos2" || base64(24-bit STUN Security Features)
= 9 characters + 4 characters = 13 characters
Okay now the security part, and it's serious ๐ญ The long-term credential mechanism is open to offline dictionary attacks, so deployments SHOULD use passwords that are hard to guess ๐ If the credentials aren't typed in by a user and are instead put on a client device during device provisioning, the password SHOULD have at least 128 bits of randomness ๐ If a user is typing the credentials in, those passwords should follow current best practices for password structure ๐ซถ
9.2.1. Bid-Down Attack Prevention
okay this section is about two brand new security features ๐ฆ One lets you pick the algorithm used to protect the password, and the other lets you use an anonymous username. Both are optional so that older versions of STUN still work the way they always have ๐
Here's the catch though: these features are vulnerable to bid-down attacks ๐ฌ That's when someone sitting in the message path strips these capabilities out and forces weaker security onto everyone. To make sure that kind of sneaky move doesn't go unnoticed, the nonce gets extra information baked in ๐ต๏ธโโ๏ธ
The value of the "nonce cookie" changes depending on which STUN Security Feature bits are selected. Whenever this document mentions the "nonce cookie" in a section about a specific STUN Security Feature, it's understood that the matching STUN Security Feature bit in the "nonce cookie" is set to 1 โจ
For example, when the PASSWORD-ALGORITHMS security feature (defined in Section 9.2.4) is used, the matching "Password algorithms" bit (defined in Section 18.1) is set to 1 in the "nonce cookie" ๐
9.2.2. HMAC Key
For long-term credentials that don't use a different algorithm (the kind you'd pick with the PASSWORD-ALGORITHM attribute), the key is 16 bytes ๐
key = MD5(username ":" OpaqueString(realm)
":" OpaqueString(password))
Here MD5 comes from [RFC1321] and [RFC6151], and the OpaqueString profile is defined in [RFC8265]. The encoding is UTF-8 [RFC3629] ๐
So the 16-byte key is the MD5 hash of five fields smooshed together ๐ (1) the username, with any quotes and trailing nulls stripped, taken from the USERNAME attribute (and OpaqueString has already been applied in that case); (2) a single colon; (3) the realm, with any quotes and trailing nulls stripped and then run through OpaqueString; (4) another single colon; and (5) the password, with any trailing nulls stripped and then run through OpaqueString. For example, if the username is 'user', the realm is 'realm', and the password is 'pass', then the 16-byte HMAC key is the MD5 hash of the string 'user:realm:pass', which comes out to 0x8493fbc53ba582fb4c044c456bdc40eb ๐ค
This key structure is super handy for systems that also use SIP [RFC3261] ๐ SIP systems that use its digest authentication usually don't store the actual password in the database. They store something called "H(A1)" instead, which is exactly the key we just defined. This mechanism can be used with the authentication extensions in [RFC5090] ๐
When a PASSWORD-ALGORITHM is used, the key length and algorithm to use are described in Section 18.5.1 โจ
9.2.3. Forming a Request
The first request from the client to the server is handled by the rules in Section 9.2.3.1 ๐ The server is identified by hostname if the DNS procedures of Section 8 are used, and by IP address if they aren't. When the client starts a subsequent request after a previous request/response transaction finished successfully, it follows the rules in Section 9.2.3.2 ๐ฆ Forming a request because of a 401 (Unauthenticated) or 438 (Stale Nonce) error response is covered in Section 9.2.5, and it doesn't count as a "subsequent request," so the rules in Section 9.2.3.2 don't apply to it ๐ โโ๏ธ Each of these request types has its own different set of mandatory attributes ๐
9.2.3.1. First Request
If the client hasn't completed a successful request/response transaction with the server yet, it MUST omit the USERNAME, USERHASH, MESSAGE-INTEGRITY, MESSAGE-INTEGRITY-SHA256, REALM, NONCE, PASSWORD-ALGORITHMS, and PASSWORD-ALGORITHM attributes ๐ซ Basically, the first request goes out as if there's no authentication or message integrity happening at all ๐
9.2.3.2. Subsequent Requests
Once a request/response transaction is complete, the client will have been given a realm and a nonce by the server, and it will have picked a username and password to authenticate with ๐ The client SHOULD cache the username, password, realm, and nonce for future communication with the server ๐ง When the client sends a subsequent request, it MUST include either the USERNAME or USERHASH, REALM, NONCE, and PASSWORD-ALGORITHM attributes with those cached values ๐ญ It MUST also include a MESSAGE-INTEGRITY attribute or a MESSAGE-INTEGRITY-SHA256 attribute, computed as described in Sections 14.5 and 14.6 using the cached password โจ Which of the two it uses depends on the attribute that came back in the response to the first request ๐ซถ
9.2.4. Receiving a Request โจ
okay bestie, once the server finishes the basic processing of a request, it runs through the checks below in the order listed ๐
Also, it is RECOMMENDED that the REALM value be the domain name of the provider of the STUN server ๐ธ
- If the message does not contain a
MESSAGE-INTEGRITYorMESSAGE-INTEGRITY-SHA256attribute, the server MUST generate an error response with an error code of 401 (Unauthenticated) ๐ This response MUST include aREALMvalue. It MUST also include aNONCEthat the server picks itself. The server MUST NOT choose the sameNONCEfor two requests unless they have the same source IP address and port. The server MAY support alternate password algorithms, and if it does, it can list them in preferential order in aPASSWORD-ALGORITHMSattribute. If the server adds aPASSWORD-ALGORITHMSattribute, it MUST set the STUN Security Feature "Password algorithms" bit to 1. The server MAY support anonymous usernames, and if it does, it MUST set the STUN Security Feature "Username anonymity" bit to 1. The response SHOULD NOT contain aUSERNAME,USERHASH,MESSAGE-INTEGRITY, orMESSAGE-INTEGRITY-SHA256attribute.
Note: Reusing a NONCE for different source IP addresses or ports was not explicitly forbidden in [RFC5389]. ๐
- If the message contains a
MESSAGE-INTEGRITYor aMESSAGE-INTEGRITY-SHA256attribute, but is missing either theUSERNAMEorUSERHASH,REALM, orNONCEattribute, the server MUST generate an error response with an error code of 400 (Bad Request) ๐ This response SHOULD NOT include aUSERNAME,USERHASH,NONCE, orREALMattribute. The response cannot contain aMESSAGE-INTEGRITYorMESSAGE-INTEGRITY-SHA256attribute, because the stuff needed to generate them is missing. - If the
NONCEattribute starts with the "nonce cookie" and the STUN Security Feature "Password algorithms" bit is set to 1, the server performs these checks in the order specified:- If the request contains neither the
PASSWORD-ALGORITHMSnor thePASSWORD-ALGORITHMattribute, then the request is processed as thoughPASSWORD-ALGORITHMwere MD5 โจ - Otherwise, unless (1)
PASSWORD-ALGORITHMandPASSWORD-ALGORITHMSare both present, (2)PASSWORD-ALGORITHMSmatches the value sent in the response that sent thisNONCE, and (3)PASSWORD-ALGORITHMmatches one of the entries inPASSWORD-ALGORITHMS, the server MUST generate an error response with an error code of 400 (Bad Request) ๐ซถ
- If the request contains neither the
- If the value of the
USERNAMEorUSERHASHattribute is not valid, the server MUST generate an error response with an error code of 401 (Unauthenticated) ๐ญ This response MUST include aREALMvalue. It MUST include aNONCEthat the server picks. It MUST include aPASSWORD-ALGORITHMSattribute. The response SHOULD NOT contain aUSERNAMEorUSERHASHattribute. The response MAY include aMESSAGE-INTEGRITYorMESSAGE-INTEGRITY-SHA256attribute, calculated with the previous key. - If the
MESSAGE-INTEGRITY-SHA256attribute is present, compute the message integrity value as described in Section 14.6, using the password associated with the username. Otherwise, using that same password, compute theMESSAGE-INTEGRITYvalue as described in Section 14.5. If the result does not match the contents of theMESSAGE-INTEGRITYattribute or theMESSAGE-INTEGRITY-SHA256attribute, the server MUST reject the request with an error response ๐ฅ That response MUST use an error code of 401 (Unauthenticated). It MUST include theREALMandNONCEattributes, and SHOULD NOT include theUSERNAME,USERHASH,MESSAGE-INTEGRITY, orMESSAGE-INTEGRITY-SHA256attribute. - If the
NONCEis no longer valid, the server MUST generate an error response with an error code of 438 (Stale Nonce) ๐ฅ This response MUST includeNONCE,REALM, andPASSWORD-ALGORITHMSattributes, and SHOULD NOT include theUSERNAMEandUSERHASHattributes. TheNONCEattribute value MUST be valid. The response MAY include aMESSAGE-INTEGRITYorMESSAGE-INTEGRITY-SHA256attribute, calculated with the previousNONCE. Servers can revoke nonces for extra security ๐ For guidelines, check Section 5.4 of [RFC7616].
If these checks pass, the server keeps processing the request โจ Any response the server generates MUST include the MESSAGE-INTEGRITY-SHA256 attribute, computed with the username and password used to authenticate the request. The one exception is when the request was processed as though PASSWORD-ALGORITHM were MD5 (because it had neither PASSWORD-ALGORITHMS nor PASSWORD-ALGORITHM). In that case, the MESSAGE-INTEGRITY attribute MUST be used instead of MESSAGE-INTEGRITY-SHA256, and the REALM, NONCE, USERNAME, and USERHASH attributes SHOULD NOT be included ๐
9.2.5. Receiving a Response โจ
okay, this part is all about what the client does when a response comes back ๐ฆ
If the response is an error response with an error code of 401 (Unauthenticated) or 438 (Stale Nonce), the client MUST check whether the NONCE attribute value starts with the "nonce cookie" ๐ If it does, and that "nonce cookie" has the STUN Security Feature "Password algorithms" bit set to 1 but no PASSWORD-ALGORITHMS attribute is present, then the client MUST NOT retry the request with a new transaction ๐ซ
If the response is an error response with an error code of 401 (Unauthenticated), the client SHOULD retry the request with a new transaction ๐ This request MUST contain a USERNAME or a USERHASH, which the client works out as the right username for the REALM from the error response. If the "nonce cookie" is present and has the STUN Security Feature "Username anonymity" bit set to 1, then the USERHASH attribute MUST be used. Otherwise, the USERNAME attribute MUST be used. The request MUST contain the REALM, copied from the error response. The request MUST contain the NONCE, also copied from the error response. If the response contains a PASSWORD-ALGORITHMS attribute, the request MUST contain the PASSWORD-ALGORITHMS attribute with the same content. If the response contains a PASSWORD-ALGORITHMS attribute and that attribute has at least one algorithm the client supports, then the request MUST contain a PASSWORD-ALGORITHM attribute set to the first supported algorithm on the list ๐ If the response contains a PASSWORD-ALGORITHMS attribute and none of the algorithms in it are supported by the client, then the client MUST NOT retry the request with a new transaction ๐
โโ๏ธ The client MUST NOT do this retry if it isn't changing the USERNAME, USERHASH, REALM, or its associated password from the previous attempt.
If the response is an error response with an error code of 438 (Stale Nonce), the client MUST retry the request using the new NONCE attribute from the 438 (Stale Nonce) response ๐ This retry MUST also include either the USERNAME or USERHASH, the REALM, and either the MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 attribute.
For all other responses, if the NONCE attribute starts with the "nonce cookie" and the STUN Security Feature "Password algorithms" bit is set to 1 but PASSWORD-ALGORITHMS is not present, the response MUST be ignored ๐ง
If the response is an error response with an error code of 400 (Bad Request) and does not contain either the MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 attribute, then the response MUST be discarded, as if it were never received ๐ซ That means any retransmits, if they apply, will keep going.
Note: In this case, the 400 response will never reach the application, so you'll get a timeout instead. ๐ญ
The client looks for a MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 attribute in the response, whether it's a success or a failure ๐ If one is there, the client calculates the message integrity over the response as defined in Sections 14.5 or 14.6, using the same password it used for the request. If the result matches the contents of the MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 attribute, the response is considered authenticated โ
If the value doesn't match, or if both MESSAGE-INTEGRITY and MESSAGE-INTEGRITY-SHA256 are absent, what happens next depends on whether the request was sent over a reliable or an unreliable transport.
If the request was sent over an unreliable transport, the response MUST be discarded, as if it had never been received. That means any retransmits, if they apply, will keep going. If every response received gets discarded, then instead of signaling a timeout after ending the transaction, the layer MUST signal that the integrity protection was violated ๐จ
If the request was sent over a reliable transport, the response MUST be discarded, and the layer MUST immediately end the transaction and signal that the integrity protection was violated ๐ฅ
If the response contains a PASSWORD-ALGORITHMS attribute, all subsequent requests MUST be authenticated using MESSAGE-INTEGRITY-SHA256 only ๐
10. ALTERNATE-SERVER Mechanism โจ
okay so this section is all about how a STUN server can redirect a client to a different server ๐ฆ this extension is optional, and a usage has to define if and when it gets used. the ALTERNATE-SERVER attribute carries an IP address ๐
a server using this extension redirects a client by answering a request with an error response that has error code 300 (Try Alternate) ๐ the server MUST include at least one ALTERNATE-SERVER attribute in that error response, and it MUST contain an IP address of the same address family as the source IP address of the request message. the server SHOULD also add a second ALTERNATE-SERVER attribute after the mandatory one, containing an IP address from the other address family (the one that isn't the source IP address of the request). the error response MAY be authenticated ๐ but there are use cases where authenticating it isn't possible or practical.
now the domain stuff ๐ธ if the transaction uses TLS or DTLS, if it's authenticated by a MESSAGE-INTEGRITY-SHA256 attribute, and if the server wants to redirect to a server that has a different certificate, then the server MUST include an ALTERNATE-DOMAIN attribute containing the name inside the subjectAltName of that certificate. those conditions on MESSAGE-INTEGRITY-SHA256 basically say "this transaction is authenticated, and the client implements this spec, so it can actually process ALTERNATE-DOMAIN" ๐ซถ
a client using this extension handles a 300 (Try Alternate) error code like this ๐ง it looks for an ALTERNATE-SERVER attribute in the error response. if it finds one, it treats the current transaction as failed and retries the request with the server named in the attribute, using the same transport protocol as the previous request. if that retry is authenticated, it MUST utilize the same credentials the client would have used with the server that did the redirecting. if the transport protocol uses TLS or DTLS, the client looks for an ALTERNATE-DOMAIN attribute. if it finds one, that domain MUST be used to validate the certificate, following the recommendations in [RFC6125]. the certificate MUST contain an identifier of type DNS-ID or CN-ID (eventually with wildcards) but not of type SRV-ID or URI-ID. if there's no ALTERNATE-DOMAIN attribute, the same domain that was used for the original request MUST be used to validate the certificate.
and here's the loop-breaker ๐ if the client has already sent this request to a server it's now being redirected to within the last five minutes, it MUST ignore the redirection and consider the transaction failed. this stops endless ping-ponging between servers when there's a redirection loop ๐ โโ๏ธ
11. Backwards Compatibility with RFC 3489 ๐
on top of the backwards compatibility already covered in Section 12 of [RFC5389], there's one extra rule ๐ DTLS MUST NOT be used with [RFC3489] (referred to as "classic STUN"). any STUN request or indication without the magic cookie (see Section 6 of [RFC5389]) sent over DTLS MUST be considered invalid. so all requests MUST generate a 500 (Server Error) error response, and indications MUST be ignored ๐
12. Basic Server Behavior ๐
this section defines the behavior of a basic, stand-alone STUN server โจ
historically, "classic STUN" [RFC3489] only defined a server that gave clients server reflexive transport addresses by receiving and replying to STUN Binding requests. then [RFC5389] reimagined the protocol as an extensible framework, and the server job became the only STUN Usage defined in that document. this STUN Usage is also called "Basic STUN Server" ๐
the STUN server MUST support the Binding method. it SHOULD NOT utilize the short-term or long-term credential mechanism, because authenticating the request takes more work than just processing it ๐ it SHOULD NOT utilize the ALTERNATE-SERVER mechanism for that same reason. it MUST support UDP and TCP. it MAY support STUN over TCP/TLS or STUN over UDP/DTLS, though DTLS and TLS give minimal security benefits in this basic mode ๐ it doesn't require a keep-alive mechanism, because a TCP or TLS-over-TCP connection gets closed after the end of the Binding transaction. it MAY utilize the FINGERPRINT mechanism but MUST NOT require it. the stand-alone server only runs STUN, so FINGERPRINT gives no benefit there. requiring it would break compatibility with RFC 3489, and that compatibility is desirable in a stand-alone server ๐ฆ stand-alone STUN servers SHOULD support backwards compatibility with clients using [RFC3489], as described in Section 11.
it is RECOMMENDED that STUN server administrators provide DNS entries for those servers, as described in Section 8 ๐ธ if both A and AAAA resource records come back, the client can send STUN Binding requests to the IPv4 and IPv6 addresses at the same time (as specified in [RFC8305]), since the Binding request is idempotent. also, the MAPPED-ADDRESS or XOR-MAPPED-ADDRESS attributes that come back won't necessarily match the address family of the server address that was used ๐
a basic STUN server isn't a NAT traversal solution all by itself ๐ but it can be part of a solution through STUN Usages. more on that in Section 13 ๐ง
13. STUN Usages ๐
STUN by itself isn't a fix for the NAT traversal problem ๐ญ instead, it's a tool you use inside a bigger solution. the term "STUN Usage" means any solution that uses STUN as a component ๐
a STUN Usage defines how STUN actually gets used: when to send requests, what to do with the responses, and which optional procedures defined here (or in an extension to STUN) are used. a usage also defines:
- Which STUN methods are used.
- What transports are used. If DTLS-over-UDP is used, then implementing the denial-of-service countermeasure described in Section 4.2.1 of [RFC6347] is mandatory.
- What authentication and message-integrity mechanisms are used.
- The considerations around manual vs. automatic key derivation for the integrity mechanism, as discussed in [RFC4107].
- What mechanisms are used to tell STUN messages apart from other messages. When STUN is run over TCP or TLS-over-TCP, a framing mechanism may be required.
- How a STUN client figures out the IP address and port of the STUN server.
- How simultaneous use of IPv4 and IPv6 addresses (Happy Eyeballs [RFC8305]) works with non-idempotent transactions when both address families are found for the STUN server.
- Whether backwards compatibility to RFC 3489 is required.
- What optional attributes defined here (such as FINGERPRINT and ALTERNATE-SERVER) or in other extensions are required.
- If MESSAGE-INTEGRITY-SHA256 truncation is permitted, and the limits permitted for truncation.
- The keep-alive mechanism if STUN is run over TCP or TLS-over-TCP.
- If anycast addresses can be used for the server in case 1) TCP or TLS-over-TCP or 2) authentication is used.
on top of that, any STUN Usage must think about the security implications of using STUN in that usage ๐จ a bunch of attacks against STUN are known (see the Security Considerations section in this document), and any usage must consider how to thwart or mitigate them. honestly, this part is serious business ๐ญ
finally, a usage must consider whether it's an example of the Unilateral Self-Address Fixing approach to NAT traversal. if it is, it needs to address the questions raised in RFC 3424 [RFC3424] ๐
14. STUN Attributes ๐
after the STUN header come zero or more attributes โจ each attribute MUST be TLV encoded, with a 16-bit type, a 16-bit length, and a value. each STUN attribute MUST end on a 32-bit boundary. as mentioned above, all fields in an attribute are sent most significant bit first ๐ง
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Value (variable) ....
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 4: Format of STUN Attributes
the value in the Length field MUST contain the length of the Value part of the attribute, before padding, measured in bytes ๐ since STUN aligns attributes on 32-bit boundaries, any attribute whose content isn't a multiple of 4 bytes gets padded with 1, 2, or 3 bytes so the value is a multiple of 4 bytes. the padding bits MUST be set to zero when sending and MUST be ignored by the receiver ๐ซถ
any attribute type MAY appear more than once in a STUN message ๐ unless specified otherwise, the order of appearance matters: only the first occurrence needs to be processed by a receiver, and any duplicates MAY be ignored by a receiver.
to let future revisions add new attributes if needed, the attribute space is split into two ranges ๐ฐ attributes with type values between 0x0000 and 0x7FFF are comprehension-required attributes, which means the STUN agent cannot successfully process the message unless it understands the attribute. attributes with type values between 0x8000 and 0xFFFF are comprehension-optional attributes, which means the STUN agent can ignore them if it doesn't understand them ๐
the set of STUN attribute types is maintained by IANA ๐ the initial set defined by this specification is found in Section 18.3.
the rest of this section describes the format of the various attributes defined in this specification ๐ง
14.1. MAPPED-ADDRESS
the MAPPED-ADDRESS attribute indicates a reflexive transport address of the client ๐ช it's made of an 8-bit address family and a 16-bit port, followed by a fixed-length value holding the IP address. if the address family is IPv4, the address MUST be 32 bits. if the address family is IPv6, the address MUST be 128 bits. all fields must be in network byte order.
the format of the MAPPED-ADDRESS attribute is:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0 0 0 0 0 0 0| Family | Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Address (32 bits or 128 bits) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 5: Format of MAPPED-ADDRESS Attribute
the address family can be one of these values ๐ฏ
0x01:IPv4
0x02:IPv6
the first 8 bits of the MAPPED-ADDRESS MUST be set to 0 and MUST be ignored by receivers. these bits are there to line parameters up on natural 32-bit boundaries ๐
this attribute is only used by servers to achieve backwards compatibility with [RFC3489] clients ๐ฅน
14.2. XOR-MAPPED-ADDRESS โจ
okay so XOR-MAPPED-ADDRESS is basically MAPPED-ADDRESS's glow-up ๐ same exact job, except the reflexive transport address gets scrambled with the XOR function so nobody (including sketchy middleboxes) can just read it off the wire ๐
The format of the XOR-MAPPED-ADDRESS is:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0 0 0 0 0 0 0| Family | X-Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| X-Address (Variable)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 6: Format of XOR-MAPPED-ADDRESS Attribute
The Family field is the IP address family, and it's encoded exactly the same way as the Family field in MAPPED-ADDRESS ๐ธ
Now the fun part, the XOR math ๐งฎ X-Port is the mapped port XOR'd with the most significant 16 bits of the magic cookie. If the family is IPv4, X-Address is the mapped IP address XOR'd with the magic cookie. If the family is IPv6, X-Address is the mapped IP address XOR'd with the magic cookie concatenated with the 96-bit transaction ID ๐ฆ And in every single case, the XOR works on its inputs in network byte order, which just means the order they'll be encoded in the message. No freestyling the byte order, bestie ๐
The rules for encoding and processing the first 8 bits of the attribute's value, the rules for handling multiple occurrences of the attribute, and the rules for processing address families are all the same as for MAPPED-ADDRESS. Copy-paste energy, no notes ๐ซถ
Note: XOR-MAPPED-ADDRESS and MAPPED-ADDRESS only differ in how they encode the transport address. XOR-MAPPED-ADDRESS XORs it with the magic cookie, and MAPPED-ADDRESS just stores it in plain binary. RFC 3489 originally only had MAPPED-ADDRESS ๐ But then deployment experience showed that some NATs rewrite the 32-bit binary payloads containing the NAT's public IP address, like STUN's MAPPED-ADDRESS attribute, in a well-meaning but misguided attempt at a generic Application Layer Gateway (ALG) function. ๐ญ That kind of behavior messes with STUN and also makes STUN's message-integrity checking fail.
14.3. USERNAME ๐
The USERNAME attribute is used for message integrity. It tells you which username and password combo was used in the message-integrity check, so it's basically the ID badge for the credentials ๐ชช
The value of USERNAME is a variable-length value holding the authentication username. It MUST contain a UTF-8-encoded [RFC3629] sequence of fewer than 509 bytes, and it MUST have been processed using the OpaqueString profile [RFC8265]. A compliant implementation MUST be able to parse a UTF-8-encoded sequence of 763 or fewer octets so it stays compatible with [RFC5389] โจ
Note: [RFC5389] accidentally pointed at the definition of UTF-8 in [RFC2279]. ๐ [RFC2279] allowed up to 6 octets per encoded character, but it got replaced by [RFC3629], which only allows 4 octets per encoded character, matching changes made in Unicode 2.0 and ISO/IEC 10646.
Note: This spec uses the OpaqueString profile instead of the UsernameCasePreserved profile for username string processing, so it plays nicer with password stores that already exist ๐ Lots of password databases used for HTTP and SIP Digest authentication store the MD5 hash of username:realm:password instead of a plain text password. [RFC3489] was designed so STUN authentication would be compatible with those databases as much as possible. It did no pre-processing of usernames and passwords, except banning non-space ASCII control characters, just like SIP and HTTP. The next revision, [RFC5389], used the SASLprep [RFC4013] stringprep [RFC3454] profile to pre-process usernames and passwords instead. SASLprep uses Unicode Normalization Form KC (Compatibility Decomposition, followed by Canonical Composition) [UAX15], and it prohibits various control, space, and non-text, deprecated, or inappropriate codepoints. Then the PRECIS framework [RFC8264] obsoleted stringprep, and PRECIS handling of usernames and passwords [RFC8265] uses Unicode Normalization Form C (Canonical Decomposition, followed by Canonical Composition).
Note (continued): Sure, there are a few specific cases where different username strings under HTTP Digest could get mapped to a single STUN username processed with OpaqueString, but those cases are super unlikely and easy to detect and fix ๐ With a UsernameCasePreserved profile, it'd be way more likely that valid HTTP Digest usernames wouldn't match their processed forms, especially usernames with bidirectional text and compatibility forms. ๐ฌ And operators are free to further restrict the allowed codepoints in usernames to dodge problematic characters.
14.4. USERHASH ๐
The USERHASH attribute is used as a replacement for the USERNAME attribute when username anonymity is supported. Basically, it hides the actual username from anyone snooping ๐ฆ
The value of USERHASH has a fixed length of 32 bytes. The username MUST have been processed using the OpaqueString profile [RFC8265], and the realm MUST have been processed using the OpaqueString profile [RFC8265] before hashing. Both of those MUSTs are doing heavy lifting here ๐ซถ
The following is the operation that the client will perform to hash the username:
userhash = SHA-256(OpaqueString(username) ":" OpaqueString(realm))
14.5. MESSAGE-INTEGRITY ๐ฅ
The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [RFC2104] of the STUN message. It can show up in any STUN message type โจ Since it uses the SHA-1 hash, the HMAC will be 20 bytes.
The key for the HMAC depends on which credential mechanism is in use. Section 9.1.1 defines the key for the short-term credential mechanism, and Section 9.2.2 defines the key for the long-term credential mechanism. Other credential mechanisms MUST define the key that gets used for the HMAC. Don't wing it, bestie ๐ โโ๏ธ
The text used as input to HMAC is the STUN message, up to and including the attribute right before the MESSAGE-INTEGRITY attribute. The Length field of the STUN message header gets adjusted to point to the end of the MESSAGE-INTEGRITY attribute, and the value of the MESSAGE-INTEGRITY attribute is set to a dummy value for now ๐ง
Once the computation is done, the value of the MESSAGE-INTEGRITY attribute gets filled in, and the length in the STUN header is set to its correct value, which is the length of the entire message. When you're validating the MESSAGE-INTEGRITY, the Length field in the STUN header must be adjusted to point to the end of the MESSAGE-INTEGRITY attribute before you calculate the HMAC over the STUN message, up to and including the attribute right before MESSAGE-INTEGRITY. That adjustment is necessary when attributes like FINGERPRINT and MESSAGE-INTEGRITY-SHA256 show up after MESSAGE-INTEGRITY ๐ See also [RFC5769] for examples of these calculations.
14.6. MESSAGE-INTEGRITY-SHA256 ๐ธ
The MESSAGE-INTEGRITY-SHA256 attribute contains an HMAC-SHA256 [RFC2104] of the STUN message. It can be present in any STUN message type. It actually contains an initial portion of the HMAC-SHA-256 [RFC2104] of the STUN message, not the whole thing ๐ The value will be at most 32 bytes, but it MUST be at least 16 bytes and MUST be a multiple of 4 bytes. The value must be the full 32 bytes unless the STUN Usage explicitly specifies that truncation is allowed. STUN Usages may specify a minimum length longer than 16 bytes, so check your usage spec, babe ๐
The key for the HMAC depends on which credential mechanism is in use. Section 9.1.1 defines the key for the short-term credential mechanism, and Section 9.2.2 defines the key for the long-term credential mechanism. Other credential mechanism MUST define the key that is used for the HMAC ๐
The text used as input to HMAC is the STUN message, up to and including the attribute right before the MESSAGE-INTEGRITY-SHA256 attribute. The Length field of the STUN message header is adjusted to point to the end of the MESSAGE-INTEGRITY-SHA256 attribute, and the value of the MESSAGE-INTEGRITY-SHA256 attribute is set to a dummy value.
Once the computation is performed, the value of the MESSAGE-INTEGRITY-SHA256 attribute is filled in, and the length in the STUN header is set to its correct value, the length of the entire message. When validating the MESSAGE-INTEGRITY-SHA256, the Length field in the STUN header must be adjusted to point to the end of the MESSAGE-INTEGRITY-SHA256 attribute before calculating the HMAC over the STUN message, up to and including the attribute right before MESSAGE-INTEGRITY-SHA256. That adjustment is necessary when attributes like FINGERPRINT appear after MESSAGE-INTEGRITY-SHA256. See also Appendix B.1 for examples of these calculations ๐งฎ
14.7. FINGERPRINT ๐ง
The FINGERPRINT attribute MAY be present in all STUN messages. It's the optional little checksum charm that helps you tell STUN packets apart from everybody else's packets โจ
The value of the attribute is the CRC-32 of the STUN message up to (but not including) the FINGERPRINT attribute itself, XOR'd with the 32-bit value 0x5354554e. ๐ That XOR is there so the FINGERPRINT test won't report a false positive on a packet that has a CRC-32 generated by some other application protocol. The 32-bit CRC is the one defined in ITU V.42 [ITU.V42.2002], with the generator polynomial x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1. If you want sample CRC-32 code, see Section 8 of [RFC1952] ๐ซถ
When it's present, the FINGERPRINT attribute MUST be the last attribute in the message, so it'll show up after MESSAGE-INTEGRITY and MESSAGE-INTEGRITY-SHA256 ๐
The FINGERPRINT attribute can help distinguish STUN packets from packets of other protocols. See Section 7 ๐ฆ
Just like MESSAGE-INTEGRITY and MESSAGE-INTEGRITY-SHA256, the CRC used in the FINGERPRINT attribute covers the Length field from the STUN message header. So before you compute the CRC, that value must be correct and must include the CRC attribute as part of the message length ๐ When you use the FINGERPRINT attribute in a message, the attribute first goes into the message with a dummy value. Then the CRC gets computed, and the attribute's value gets updated. If the MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 attribute is also present, it must already be there with the correct message-integrity value before the CRC is computed, since the CRC is done over the values of the MESSAGE-INTEGRITY and MESSAGE-INTEGRITY-SHA256 attributes too. Order of operations matters, bestie, no shortcuts ๐
14.8. ERROR-CODE ๐จ
okay so ERROR-CODE is the attribute that shows up whenever a request goes sideways ๐ It carries a numeric error code in the range of 300 to 699, plus a text reason phrase encoded in UTF-8 [RFC3629]. It's also consistent with SIP [RFC3261] and HTTP [RFC7231] when it comes to code assignments and meanings, which is so iconic of it ๐ซถ The reason phrase is just for diagnostics, so it can say whatever fits the code. The IANA registry for error codes lists recommended reason phrases for the defined codes. The reason phrase MUST be a UTF-8-encoded [RFC3629] sequence of fewer than 128 characters (it can be as long as 509 bytes when encoding and 763 bytes when decoding).
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved, should be 0 |Class| Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reason Phrase (variable) ..
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 7: Format of ERROR-CODE Attribute ๐
To make processing easier, the class (the hundreds digit) gets its own slot, separate from the rest of the code, as you can see in Figure 7 โจ
The Reserved bits SHOULD be 0 and are there for alignment on 32-bit boundaries. Receivers MUST ignore these bits. The Class is the hundreds digit of the error code, and its value MUST be between 3 and 6. The Number is the binary encoding of the error code modulo 100, and its value MUST be between 0 and 99.
The following error codes, along with their recommended reason phrases, are defined:
300 Try Alternate: The client should contact an alternate server for this request. This error response MUST only be sent if the request included either a USERNAME or USERHASH attribute and a valid MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 attribute; otherwise, it MUST NOT be sent and error code 400 (Bad Request) is suggested. This error response MUST be protected with the MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 attribute, and receivers MUST validate the MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 of this response before redirecting themselves to an alternate server.- Note: Failure to generate and validate message integrity for a 300 response allows an on-path attacker to falsify a 300 response, thus causing subsequent STUN messages to be sent to a victim. ๐ฑ
400 Bad Request: The request was malformed. The client SHOULD NOT retry the request without modification from the previous attempt. The server may not be able to generate a valid MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 for this error, so the client MUST NOT expect a valid MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 attribute on this response. ๐401 Unauthenticated: The request did not contain the correct credentials to proceed. The client should retry the request with proper credentials. ๐420 Unknown Attribute: The server received a STUN packet containing a comprehension-required attribute that it did not understand. The server MUST put this unknown attribute in the UNKNOWN-ATTRIBUTE attribute of its error response. ๐งฉ438 Stale Nonce: The NONCE used by the client was no longer valid. The client should retry, using the NONCE provided in the response. โฐ500 Server Error: The server has suffered a temporary error. The client should try again. ๐ฅบ
14.9. REALM ๐
The REALM attribute may be present in requests and responses. It contains text that meets the grammar for "realm-value" as described in [RFC3261], just without the double quotes and their surrounding whitespace. So it's an unquoted realm-value, which means it's a sequence of qdtext or quoted-pair. It MUST be a UTF-8-encoded [RFC3629] sequence of fewer than 128 characters (as long as 509 bytes when encoding them and as long as 763 bytes when decoding them), and it MUST have been processed using the OpaqueString profile [RFC8265]. ๐
Presence of the REALM attribute in a request means long-term credentials are being used for authentication. Presence in certain error responses means the server wants the client to use a long-term credential in that realm for authentication. very specific, very intentional ๐
14.10. NONCE ๐
The NONCE attribute may be present in requests and responses. It contains a sequence of qdtext or quoted-pair, which are defined in [RFC3261]. Quick note: that means the NONCE attribute won't include the actual surrounding quote characters ๐ซ The NONCE attribute MUST be fewer than 128 characters (as long as 509 bytes when encoding them and as long as 763 bytes when decoding them). If you want guidance on picking nonce values as a server, check out Section 5.4 of [RFC7616] โจ
14.11. PASSWORD-ALGORITHMS ๐
The PASSWORD-ALGORITHMS attribute may be present in requests and responses. It holds the list of algorithms the server can use to derive the long-term password. the vibe is "here are my options, bestie"
The set of known algorithms is maintained by IANA. The initial set defined by this spec is in Section 18.5.
The attribute holds a list of algorithm numbers and variable-length parameters. The algorithm number is a 16-bit value as defined in Section 18.5. Each parameters block starts with its length (before padding) as a 16-bit value, followed by the parameters specific to that algorithm. The parameters are padded to a 32-bit boundary, the same way an attribute is.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Algorithm 1 | Algorithm 1 Parameters Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Algorithm 1 Parameters (variable)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Algorithm 2 | Algorithm 2 Parameters Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Algorithm 2 Parameters (variable)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ...
Figure 8: Format of PASSWORD-ALGORITHMS Attribute ๐
14.12. PASSWORD-ALGORITHM ๐ง
The PASSWORD-ALGORITHM attribute is present only in requests. It holds the algorithm that the server must use to derive a key from the long-term password. It's giving "one choice, no drama" ๐
The set of known algorithms is maintained by IANA, and the initial set defined by this spec is in Section 18.5.
The attribute holds an algorithm number and variable-length parameters. The algorithm number is a 16-bit value as defined in Section 18.5. The parameters start with their length (before padding) as a 16-bit value, followed by the parameters specific to the algorithm. The parameters are padded to a 32-bit boundary, the same way an attribute is. Similarly, the padding bits MUST be set to zero on sending and MUST be ignored by the receiver. ๐ซถ
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Algorithm | Algorithm Parameters Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Algorithm Parameters (variable)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 9: Format of PASSWORD-ALGORITHM Attribute โจ
14.13. UNKNOWN-ATTRIBUTES ๐งฉ
The UNKNOWN-ATTRIBUTES attribute is present only in an error response where the ERROR-CODE attribute's response code is 420 (Unknown Attribute).
It holds a list of 16-bit values, and each one is an attribute type the server didn't understand.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Attribute 1 Type | Attribute 2 Type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Attribute 3 Type | Attribute 4 Type ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 10: Format of UNKNOWN-ATTRIBUTES Attribute ๐ฆ
Note: In [RFC3489], this field was padded to 32 by duplicating the last attribute. In this version of the specification, the normal padding rules for attributes are used instead. ๐
14.14. SOFTWARE ๐ป
The SOFTWARE attribute holds a text description of the software the sending agent is running. Clients and servers both use it. Its value SHOULD include the manufacturer and version number. It has zero impact on how the protocol works and is purely a diagnostic and debugging tool ๐ The value is variable length. It MUST be a UTF-8-encoded [RFC3629] sequence of fewer than 128 characters (as long as 509 when encoding them and as long as 763 bytes when decoding them).
14.15. ALTERNATE-SERVER ๐ง
The alternate server is a transport address pointing to a different STUN server that the STUN client should try. It's encoded the same way as MAPPED-ADDRESS, so it refers to one server by IP address. Basically a "try my friend instead" card ๐ซถ
14.16. ALTERNATE-DOMAIN ๐ธ
The alternate domain is the domain name used to verify the IP address in the ALTERNATE-SERVER attribute when the transport uses TLS or DTLS.
The value is variable length. It MUST be a valid DNS name [RFC1123] (including A-labels [RFC5890]) of 255 or fewer ASCII characters. ๐
15. Operational Considerations โญ
STUN MAY be used with anycast addresses, but only with UDP and only in STUN Usages where authentication is not used. anycast is a whole mood, but the rules are strict ๐
16. Security Considerations ๐
Okay, this section is serious business, so no skipping ๐จ
Implementations and deployments of a STUN Usage using TLS or DTLS MUST follow the recommendations in [BCP195].
Implementations and deployments of a STUN Usage using the long-term credential mechanism (Section 9.2) MUST follow the recommendations in Section 5 of [RFC7616]. this is not optional, bestie ๐ฅ
16.1. Attacks against the Protocol ๐ก๏ธ
16.1.1. Outside Attacks โจ
okay bestie, let's talk about the scary people on the network ๐๐ so an attacker can try to mess with STUN messages while they're in transit ๐ to make the STUN thing fail. these attacks get caught for both requests and responses thanks to the message-integrity mechanism, using either a short-term or long-term credential ๐ and once it's caught, the messed-up packets get dropped, so the STUN transaction just kinda fizzles out ๐ this only works for an on-path attacker, so they have to be sitting right in the middle of the route ๐ค๏ธ
now the sneakier one: an attacker that can watch STUN messages but not change them (think somebody chilling on the same Wi-Fi ๐ถ) can spot a STUN request and then instantly send back a STUN response, usually an error response, to mess up STUN processing ๐ message-integrity also stops this for messages that use MESSAGE-INTEGRITY โ BUT some error responses, especially the ones about authentication, can't be protected by MESSAGE-INTEGRITY ๐ญ and when STUN itself runs over a secure transport like TLS, these attacks are completely mitigated ๐ซถ๐
it depends on the STUN Usage how bad this stuff is ๐ some of these attacks are super minor, so they don't need message integrity to deal with them ๐ธ like, if STUN is used to talk to a basic STUN server to find a server reflexive candidate for ICE, authentication and message integrity aren't required, because those attacks get caught during the connectivity check phase ๐ฆ BUT the connectivity checks themselves do need protection so ICE works properly overall ๐ as Section 13 explains, STUN Usages describe when authentication and message integrity are needed ๐
since STUN uses the HMAC of a shared secret for authentication and integrity protection, it's open to offline dictionary attacks ๐ซฃ when authentication is used, it SHOULD be with a strong password that isn't easy to crack offline ๐ช and protecting the channel itself with TLS or DTLS helps mitigate these attacks ๐โจ
STUN supports both MESSAGE-INTEGRITY and MESSAGE-INTEGRITY-SHA256, which makes it vulnerable to bid-down attacks from an on-path attacker ๐ฑ the attacker could strip the MESSAGE-INTEGRITY-SHA256 attribute, leaving only MESSAGE-INTEGRITY, and then exploit a potential vulnerability there ๐ again, protecting the channel with TLS or DTLS mitigates these attacks ๐ซถ and removing support for MESSAGE-INTEGRITY in a future version of STUN is necessary, so it needs to happen on time โฐ
Note: using SHA-256 for password hashing doesn't meet modern standards ๐จ modern standards want password hashing to be slow, so that exhaustive password searches take a long time to compute the hash ๐ข better algorithms like Argon2 [Argon2] exist, but SHA-256 was picked for consistency with [RFC7616] ๐
16.1.2. Inside Attacks ๐ต๏ธโโ๏ธ
okay so a rogue client might try a DoS attack on a server by sending it a huge pile of STUN requests ๐ฆ luckily, a server can process STUN requests statelessly, which makes these attacks hard to pull off effectively ๐ชโจ
a rogue client can also use a STUN server as a reflector ๐ช by sending it requests with a falsified source IP address and port, the response gets delivered to that source IP and port ๐ฌ there's no amplification of the number of packets here (the STUN server sends one packet for each packet the client sends) ๐ BUT there's a small bump in the amount of data, since STUN responses are usually bigger than requests ๐ this attack gets mitigated by ingress source address filtering ๐ก๏ธ
revealing the exact software version of the agent through the SOFTWARE attribute might make them more vulnerable to attacks on software that's known to have security holes ๐ฌ implementers SHOULD make using the SOFTWARE attribute a configurable option โ๏ธ๐
16.1.3. Bid-Down Attacks ๐
this document adds the ability to pick different algorithms to protect the confidentiality of passwords stored on the server side when using the long-term credential mechanism ๐ while still staying compatible with MD5, which was the algorithm used in [RFC5389] ๐ง the way it works is the server sends the client a list of supported algorithms in a PASSWORD-ALGORITHMS attribute, and the client sends back a PASSWORD-ALGORITHM attribute with the one it picked ๐ค
okay here's the catch ๐ the PASSWORD-ALGORITHMS attribute has to be sent in an unauthenticated response, so an on-path attacker who wants to exploit an eventual MD5 vulnerability can just strip PASSWORD-ALGORITHMS out of the unprotected response ๐ and then the server acts like the client is using the version of this protocol defined in [RFC5389] ๐
to protect against this and other similar bid-down attacks, the nonce gets extra security bits that show which security features are in use ๐โจ for password algorithm selection, the matching bit gets set in the nonce the server returns in the same response that has the PASSWORD-ALGORITHMS attribute ๐ the nonce in later authenticated transactions gets checked by the server to be identical to what it originally sent, so an on-path attacker can't modify it ๐ โโ๏ธ also, the client is required to copy the received PASSWORD-ALGORITHMS attribute into the next authenticated transaction to that server ๐
if an on-path attacker removes PASSWORD-ALGORITHMS, it gets detected, because the client won't be able to send it back in the next authenticated transaction ๐จ the client catches it since the security bit is set but the matching attribute is missing, and that ends the session ๐ a client using an older version of this protocol won't send PASSWORD-ALGORITHMS back, but it can only use MD5 anyway, so the attack doesn't matter here ๐คทโโ๏ธ
the on-path attacker might also try removing the security bit along with PASSWORD-ALGORITHMS, but the server will catch that when the next authenticated transaction has an invalid nonce ๐ต๏ธโโ๏ธ
if an on-path attacker removes some algorithms from PASSWORD-ALGORITHMS, that also fails, because the attribute will be different from the original one when the server checks it in the next authenticated transaction ๐ โโ๏ธ๐
note that the bid-down protection in this document has a built-in limit ๐ฅบ an attack can't be detected until the server gets the second request after the 401 (Unauthenticated) response ๐ญ
SHA-256 was picked as the new default for password hashing for its compatibility with [RFC7616] ๐ธ but SHA-256 (like MD5) is comparatively fast, so it doesn't do much to stop brute-force attacks ๐ซ this means that if the user has a weak password, an attacker who captures a single exchange can brute-force it to learn the password, then possibly impersonate the user to the server and to other servers where the same password was used ๐จ and yep, that attacker can impersonate the user to the server itself without any brute-force at all ๐
a stronger (aka slower) algorithm, like Argon2 [Argon2], would help both of these cases ๐ช but in the first case, it would only help after the database entry for this user gets updated to use only that stronger mechanism ๐
the bid-down defenses in this protocol stop an attacker from forcing the client and server to finish a handshake with weaker algorithms than they both support ๐ but only if the weakest shared algorithm is strong enough that brute force can't crack it ๐งฑ this doesn't defend against lots of attacks on those algorithms though ๐ฌ for example, an on-path attacker might bid-down a client that supports both Argon2 [Argon2] and SHA-256 for password hashing, then use that to collect a MESSAGE-INTEGRITY-SHA256 value for an offline brute-force attack ๐ the server would detect this when it gets the second request, but that doesn't stop the attacker from getting the MESSAGE-INTEGRITY-SHA256 value ๐ญ
same deal with the USERHASH mechanism ๐ an attack on it won't succeed in setting up a session, since the server will notice the feature was dropped on path ๐ but the client would still have been tricked into sending its username in the clear in the USERNAME attribute, which discloses it to the attacker ๐ฑ
finally, when the bid-down protection is used for a future upgrade of the HMAC algorithm that protects messages, it only offers limited protection if the current HMAC algorithm is already compromised ๐ฅ
16.2. Attacks Affecting the Usage ๐
this section lists attacks that might be launched against a usage of STUN ๐ every STUN Usage has to think about whether these attacks apply to it and, if they do, talk about countermeasures ๐
most of the attacks in this section are about an attacker messing with the reflexive address a STUN client learns through a Binding request/response transaction ๐ช since how the reflexive address is used depends on the usage, whether these attacks apply and how to fix them are usage-specific ๐งฉ in common situations, changing the reflexive address with an on-path attacker is super easy ๐ฉ for example, in the common case where STUN runs directly over UDP, an on-path attacker can change the source IP address of the Binding request before it arrives at the STUN server ๐ฅท the STUN server then returns that IP address in the XOR-MAPPED-ADDRESS attribute to the client and sends the response back to that falsified IP address and port ๐ญ if the attacker can also intercept this response, they can send it back toward the client ๐โโ๏ธ
message-integrity can't protect against this one ๐ โโ๏ธ a message-integrity value can't cover the source IP address, and the intervening NAT has to be able to modify that value anyway ๐ so one solution to prevent the attacks listed below is for the client to verify the reflexive address it learned, the same way ICE [RFC8445] does โ
other usages might use other ways to prevent these attacks ๐
16.2.1. Attack I: Distributed DoS (DDoS) against a Target ๐ฅ
in this attack, the attacker gives one or more clients the same faked reflexive address that points at the intended target ๐ฏ this tricks the STUN clients into thinking their reflexive addresses are equal to the target's ๐คก if the clients hand out that reflexive address to receive traffic on it (for example, in SIP messages), the traffic gets sent to the target instead ๐ฑ this attack can provide substantial amplification, especially with clients using STUN for multimedia applications ๐ BUT it can only be launched against targets where packets from the STUN server to the target pass through the attacker, so it's limited to certain cases ๐โจ
16.2.2. Attack II: Silencing a Client
Okay so in this one, the attacker gives a STUN client a faked reflexive address ๐. That fake address routes to absolutely nowhere, so once the client hands it out, it never gets the packets it's waiting for ๐. Honestly, it's not the most iconic move for an attacker ๐ฅฑ. It only takes out one client, and that client usually isn't the actual target. Plus, anyone who can pull this off could just shut the client down in other ways, like stopping it from hearing back from the STUN server or even from a DHCP server ๐ . Same as the attack in Section 16.2.1, this only works when the attacker is on path for packets going from the STUN server toward this unused IP address ๐ค๏ธ.
16.2.3. Attack III: Assuming the Identity of a Client
This one is giving Attack II vibes, but with a twist โจ. The faked reflexive address points to the attacker themselves ๐. That means the attacker gets to receive traffic that was meant for the client. Main character energy for the wrong reasons ๐.
16.2.4. Attack IV: Eavesdropping
In this attack, the attacker tricks the client into using a reflexive address that routes right back to them ๐. Then they just forward whatever packets they catch on to the client ๐ฆ. This lets the attacker see every packet sent to the client ๐ญ. BUT, to pull this off, the attacker already has to be able to watch packets going from the client to the STUN server. In most cases (like when the attack happens from an access network), that means they could already see packets sent to the client anyway ๐. So this attack is only really useful for spying on attackers who sit on the path from the client to the STUN server, not on the path of packets being routed toward the client ๐ง.
Note that this attack can be trivially launched by the STUN server itself ๐จ. So users of STUN servers should trust the users of STUN servers as much as they'd trust any other node that can insert itself into the communication flow ๐ซถ.
16.3. Hash Agility Plan
Okay, let's plan for the day HMAC-SHA256 gets cracked ๐. This spec uses HMAC-SHA256 for message integrity, sometimes paired with HMAC-SHA1. If HMAC-SHA256 ever turns out to be compromised, the fix should look like this:
- A new message-integrity attribute and a new STUN Security Feature bit will both get allocated in a Standards Track document ๐. The new message-integrity attribute's value will be computed with a brand new hash. The STUN Security Feature bit will do two jobs at once: 1) it tells a STUN client using the long-term credential mechanism that this server supports the new hash algorithm, and 2) it prevents bid-down attacks on the new message-integrity attribute ๐ก๏ธ.
- STUN clients and servers using the short-term credential mechanism will need to update the external mechanism they use to signal which message-integrity attributes are in use ๐.
The bid-down protection in this document is brand new ๐, so it can't yet stop a bid-down attack that drops the hash algorithm all the way down to HMAC-SHA1 ๐ฌ. That's why, after a transition period, a new document updating this one will assign a new STUN Security Feature bit for deprecating HMAC-SHA1. When that bit is used, it signals that HMAC-SHA1 is deprecated and should no longer be used ๐ซ.
Same deal if HMAC-SHA256 is ever found to be compromised as a userhash: a new userhash attribute and a new STUN Security Feature bit will be allocated in a Standards Track document ๐งฉ. The new userhash attribute's value will be computed using a new hash. The STUN Security Feature bit will simultaneously 1) signal to a STUN client using the long-term credential mechanism that this server supports this new hash algorithm for the userhash attribute, and 2) prevent bid-down attacks on the new userhash attribute ๐.
17. IAB Considerations
The IAB has looked into Unilateral Self-Address Fixing (UNSAF) ๐. That's the general process where a client tries to figure out its address in another realm on the far side of a NAT, using a collaborative protocol reflection mechanism [RFC3424]. STUN can handle this job with a Binding request/response transaction, as long as one agent is behind a NAT and the other is on the public side of that NAT ๐.
The IAB has suggested that protocols built for this purpose document a specific set of considerations ๐. Some STUN Usages provide UNSAF functions (like ICE [RFC8445]) and some don't (like SIP Outbound [RFC5626]). So those usages need to address these considerations themselves ๐ .
18. IANA Considerations
18.1. STUN Security Features Registry
A STUN Security Feature set defines 24 bits as flags ๐ฉ.
IANA has created a new registry for the STUN Security Features that are protected by the bid-down attack prevention mechanism in Section 9.2.1 ๐. The initial STUN Security Features are:
Bit 0: Password algorithms
Bit 1: Username anonymity
Bit 2-23: Unassigned
Bits get assigned starting from the most significant side of the bit set, so Bit 0 is the leftmost bit and Bit 23 is the rightmost bit ๐ง . New Security Features are assigned by Standards Action [RFC8126].
18.2. STUN Methods Registry
A STUN method is a hex number in the range 0x000-0x0FF ๐ข. The encoding of a STUN method into a STUN message is described in Section 5 โจ.
STUN methods in the range 0x000-0x07F are assigned by IETF Review [RFC8126]. STUN methods in the range 0x080-0x0FF are assigned by Expert Review [RFC8126]. The expert's job is to check that the selected codepoint(s) aren't already in use and that the request isn't for an abnormally large number of codepoints ๐งโ๐ผ. Technical review of the extension itself is outside the expert's scope ๐ โโ๏ธ.
IANA has updated the name for method 0x002 (more on that below) and updated the reference from RFC 5389 to RFC 8489 for the following STUN methods:
0x000: Reserved
0x001: Binding
0x002: Reserved; was SharedSecret prior to [RFC5389]
18.3. STUN Attributes Registry
A STUN attribute type is a hex number in the range 0x0000-0xFFFF ๐ข. Attribute types in the range 0x0000-0x7FFF are considered comprehension-required, and attribute types in the range 0x8000-0xFFFF are considered comprehension-optional ๐ง. A STUN agent handles unknown comprehension-required and comprehension-optional attributes differently ๐ค.
Attribute types in the first half of the comprehension-required range (0x0000-0x3FFF) and in the first half of the comprehension-optional range (0x8000-0xBFFF) are assigned by IETF Review [RFC8126]. Attribute types in the second half of the comprehension-required range (0x4000-0x7FFF) and in the second half of the comprehension-optional range (0xC000-0xFFFF) are assigned by Expert Review [RFC8126]. The expert verifies that the selected codepoint(s) are not in use and that the request isn't for an abnormally large number of codepoints. Technical review of the extension itself is outside the expert's scope ๐งโ๐ผ.
18.3.1. Updated Attributes
IANA has updated the names for attributes 0x0002, 0x0004, 0x0005, 0x0007, and 0x000B, and updated the reference from RFC 5389 to RFC 8489 for each of the following STUN methods ๐.
Also, [RFC5389] made a mistake with the name of attribute 0x0003 ๐. It called it CHANGE-ADDRESS when it was actually previously called CHANGE-REQUEST. So IANA has updated the description for 0x0003 to read "Reserved; was CHANGE-REQUEST prior to [RFC5389]" ๐ ๏ธ.
Comprehension-required range (0x0000-0x7FFF):
0x0000: Reserved
0x0001: MAPPED-ADDRESS
0x0002: Reserved; was RESPONSE-ADDRESS prior to [RFC5389]
0x0003: Reserved; was CHANGE-REQUEST prior to [RFC5389]
0x0004: Reserved; was SOURCE-ADDRESS prior to [RFC5389]
0x0005: Reserved; was CHANGED-ADDRESS prior to [RFC5389]
0x0006: USERNAME
0x0007: Reserved; was PASSWORD prior to [RFC5389]
0x0008: MESSAGE-INTEGRITY
0x0009: ERROR-CODE
0x000A: UNKNOWN-ATTRIBUTES
0x000B: Reserved; was REFLECTED-FROM prior to [RFC5389]
0x0014: REALM
0x0015: NONCE
0x0020: XOR-MAPPED-ADDRESS
Comprehension-optional range (0x8000-0xFFFF)
0x8022: SOFTWARE
0x8023: ALTERNATE-SERVER
0x8028: FINGERPRINT
18.3.2. New Attributes
IANA has added the following attributes to the "STUN Attributes" registry โจ:
Comprehension-required range (0x0000-0x7FFF):
0x001C: MESSAGE-INTEGRITY-SHA256
0x001D: PASSWORD-ALGORITHM
0x001E: USERHASH
Comprehension-optional range (0x8000-0xFFFF)
0x8002: PASSWORD-ALGORITHMS
0x8003: ALTERNATE-DOMAIN
18.4. STUN Error Codes Registry
A STUN error code is a number in the range 0-699 ๐ข. Each one comes with a textual reason phrase in UTF-8 [RFC3629]. That phrase is only meant for human eyes and can say whatever's appropriate, though this document only proposes suggested values ๐ฌ.
STUN error codes match SIP [RFC3261] and HTTP [RFC7231] in codepoint assignments and semantics ๐ค.
New STUN error codes are assigned based on IETF Review [RFC8126]. The specification must carefully consider how clients that don't understand the error code will process it before granting the request. See the rules in Section 6.3.4 ๐งพ.
IANA has updated the reference from RFC 5389 to RFC 8489 for the error codes defined in Section 14.8 ๐. IANA has also changed the name of the 401 error code from "Unauthorized" to "Unauthenticated" ๐.
18.5. STUN Password Algorithms Registry
IANA has created a new registry titled "STUN Password Algorithms" ๐.
A password algorithm is a hex number in the range 0x0000-0xFFFF ๐ข.
The initial contents of the "Password Algorithm" registry are:
0x0000: Reserved
0x0001: MD5
0x0002: SHA-256
0x0003-0xFFFF: Unassigned
Password algorithms in the first half of the range (0x0000-0x7FFF) are assigned by IETF Review [RFC8126]. Password algorithms in the second half of the range (0x8000-0xFFFF) are assigned by Expert Review [RFC8126] ๐งโ๐ผ.
18.5.1. Password Algorithms
18.5.1.1. MD5
This password algorithm is taken from [RFC1321] ๐.
The key length is 16 bytes, and the parameters value is empty.
Note: This algorithm MUST only be used for compatibility with legacy systems ๐จ.
key = MD5(username ":" OpaqueString(realm)
":" OpaqueString(password))
18.5.1.2. SHA-256
This password algorithm is taken from [RFC7616] ๐ธ.
The key length is 32 bytes, and the parameters value is empty.
key = SHA-256(username ":" OpaqueString(realm)
":" OpaqueString(password))
18.6. STUN UDP and TCP Port Numbers
IANA has updated the reference from RFC 5389 to RFC 8489 for the following ports in the "Service Name and Transport Protocol Port Number Registry" ๐ฆ.
stun 3478/tcp Session Traversal Utilities for NAT (STUN) port
stun 3478/udp Session Traversal Utilities for NAT (STUN) port
stuns 5349/tcp Session Traversal Utilities for NAT (STUN) port
19. Changes since RFC 5389 ๐
okay so this spec obsoletes [RFC5389], which means it's the glow-up of the old one ๐ฆ here's everything that's different:
- Added support for DTLS-over-UDP [RFC6347] โจ
- Made it super clear that the RTO counts as stale if there are no transactions with the server ๐ซถ
- Lined up the RTO calculation with [RFC6298] ๐
- Updated the ciphersuites for TLS ๐
- Added support for STUN URI [RFC7064] ๐ธ
- Added support for SHA256 message integrity ๐ฅ
- Updated the Preparation, Enforcement, and Comparison of Internationalized Strings (PRECIS) support to [RFC8265] ๐
- Added a protocol and a registry for choosing the password encryption algorithm ๐
- Added support for anonymous username ๐ง
- Added a protocol and a registry for preventing bid-down attacks ๐ก๏ธ
- Specified that sharing a NONCE is no longer permitted ๐
- Added the possibility of using a domain name in the alternate server mechanism ๐
- Added more C snippets ๐ป
- Added test vector ๐
20. References
20.1. Normative References
the normative refs are the ones you truly need to read before this spec makes sense, so here they are, every single one ๐
[ITU.V42.2002]International Telecommunication Union, "Error-correcting procedures for DCEs using asynchronous-to-synchronous conversion", ITU-T Recommendation V.42, March 2002.[KARN87]Karn, P. and C. Partridge, "Improving Round-Trip Time Estimates in Reliable Transport Protocols", SIGCOMM '87, Proceedings of the ACM workshop on Frontiers in computer communications technology, Pages 2-7, DOI 10.1145/55483.55484, August 1987.[RFC0791]Postel, J., "Internet Protocol", STD 5, RFC 791, DOI 10.17487/RFC0791, September 1981, <https://www.rfc-editor.org/info/rfc791>.[RFC1122]Braden, R., Ed., "Requirements for Internet Hosts - Communication Layers", STD 3, RFC 1122, DOI 10.17487/RFC1122, October 1989, <https://www.rfc-editor.org/info/rfc1122>.[RFC1123]Braden, R., Ed., "Requirements for Internet Hosts - Application and Support", STD 3, RFC 1123, DOI 10.17487/RFC1123, October 1989, <https://www.rfc-editor.org/info/rfc1123>.[RFC1321]Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, DOI 10.17487/RFC1321, April 1992, <https://www.rfc-editor.org/info/rfc1321>.[RFC2104]Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-Hashing for Message Authentication", RFC 2104, DOI 10.17487/RFC2104, February 1997, <https://www.rfc-editor.org/info/rfc2104>.[RFC2119]Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.[RFC2782]Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for specifying the location of services (DNS SRV)", RFC 2782, DOI 10.17487/RFC2782, February 2000, <https://www.rfc-editor.org/info/rfc2782>.[RFC3629]Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2003, <https://www.rfc-editor.org/info/rfc3629>.[RFC4648]Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006, <https://www.rfc-editor.org/info/rfc4648>.[RFC5890]Klensin, J., "Internationalized Domain Names for Applications (IDNA): Definitions and Document Framework", RFC 5890, DOI 10.17487/RFC5890, August 2010, <https://www.rfc-editor.org/info/rfc5890>.[RFC6125]Saint-Andre, P. and J. Hodges, "Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS)", RFC 6125, DOI 10.17487/RFC6125, March 2011, <https://www.rfc-editor.org/info/rfc6125>.[RFC6151]Turner, S. and L. Chen, "Updated Security Considerations for the MD5 Message-Digest and the HMAC-MD5 Algorithms", RFC 6151, DOI 10.17487/RFC6151, March 2011, <https://www.rfc-editor.org/info/rfc6151>.[RFC6298]Paxson, V., Allman, M., Chu, J., and M. Sargent, "Computing TCP's Retransmission Timer", RFC 6298, DOI 10.17487/RFC6298, June 2011, <https://www.rfc-editor.org/info/rfc6298>.[RFC6347]Rescorla, E. and N. Modadugu, "Datagram Transport Layer Security Version 1.2", RFC 6347, DOI 10.17487/RFC6347, January 2012, <https://www.rfc-editor.org/info/rfc6347>.[RFC7064]Nandakumar, S., Salgueiro, G., Jones, P., and M. Petit-Huguenin, "URI Scheme for the Session Traversal Utilities for NAT (STUN) Protocol", RFC 7064, DOI 10.17487/RFC7064, November 2013, <https://www.rfc-editor.org/info/rfc7064>.[RFC7350]Petit-Huguenin, M. and G. Salgueiro, "Datagram Transport Layer Security (DTLS) as Transport for Session Traversal Utilities for NAT (STUN)", RFC 7350, DOI 10.17487/RFC7350, August 2014, <https://www.rfc-editor.org/info/rfc7350>.[RFC7616]Shekh-Yusef, R., Ed., Ahrens, D., and S. Bremer, "HTTP Digest Access Authentication", RFC 7616, DOI 10.17487/RFC7616, September 2015, <https://www.rfc-editor.org/info/rfc7616>.[RFC8174]Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.[RFC8200]Deering, S. and R. Hinden, "Internet Protocol, Version 6 (IPv6) Specification", STD 86, RFC 8200, DOI 10.17487/RFC8200, July 2017, <https://www.rfc-editor.org/info/rfc8200>.[RFC8265]Saint-Andre, P. and A. Melnikov, "Preparation, Enforcement, and Comparison of Internationalized Strings Representing Usernames and Passwords", RFC 8265, DOI 10.17487/RFC8265, October 2017, <https://www.rfc-editor.org/info/rfc8265>.[RFC8305]Schinazi, D. and T. Pauly, "Happy Eyeballs Version 2: Better Connectivity Using Concurrency", RFC 8305, DOI 10.17487/RFC8305, December 2017, <https://www.rfc-editor.org/info/rfc8305>.
20.2. Informative References โจ
okay so these are the informative references, the "good to know" reading list ๐. Nothing here is required reading to implement the protocol, but it's where all the backstory lives ๐
- [Argon2] Biryukov, A., Dinu, D., Khovratovich, D., and S. Josefsson, "The memory-hard Argon2 password hash and proof-of-work function", Work in Progress, draft-irtf-cfrg-argon2-09, November 2019.
- [BCP195] Sheffer, Y., Holz, R., and P. Saint-Andre, "Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)", BCP 195, RFC 7525, May 2015, https://www.rfc-editor.org/info/bcp195.
- [RFC1952] Deutsch, P., "GZIP file format specification version 4.3", RFC 1952, DOI 10.17487/RFC1952, May 1996, https://www.rfc-editor.org/info/rfc1952.
- [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO 10646", RFC 2279, DOI 10.17487/RFC2279, January 1998, https://www.rfc-editor.org/info/rfc2279.
- [RFC3261] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, A., Peterson, J., Sparks, R., Handley, M., and E. Schooler, "SIP: Session Initiation Protocol", RFC 3261, DOI 10.17487/RFC3261, June 2002, https://www.rfc-editor.org/info/rfc3261.
- [RFC3424] Daigle, L., Ed. and IAB, "IAB Considerations for UNilateral Self-Address Fixing (UNSAF) Across Network Address Translation", RFC 3424, DOI 10.17487/RFC3424, November 2002, https://www.rfc-editor.org/info/rfc3424.
- [RFC3454] Hoffman, P. and M. Blanchet, "Preparation of Internationalized Strings ("stringprep")", RFC 3454, DOI 10.17487/RFC3454, December 2002, https://www.rfc-editor.org/info/rfc3454.
- [RFC3489] Rosenberg, J., Weinberger, J., Huitema, C., and R. Mahy, "STUN - Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs)", RFC 3489, DOI 10.17487/RFC3489, March 2003, https://www.rfc-editor.org/info/rfc3489.
- [RFC4013] Zeilenga, K., "SASLprep: Stringprep Profile for User Names and Passwords", RFC 4013, DOI 10.17487/RFC4013, February 2005, https://www.rfc-editor.org/info/rfc4013.
- [RFC4107] Bellovin, S. and R. Housley, "Guidelines for Cryptographic Key Management", BCP 107, RFC 4107, DOI 10.17487/RFC4107, June 2005, https://www.rfc-editor.org/info/rfc4107.
- [RFC5090] Sterman, B., Sadolevsky, D., Schwartz, D., Williams, D., and W. Beck, "RADIUS Extension for Digest Authentication", RFC 5090, DOI 10.17487/RFC5090, February 2008, https://www.rfc-editor.org/info/rfc5090.
- [RFC5389] Rosenberg, J., Mahy, R., Matthews, P., and D. Wing, "Session Traversal Utilities for NAT (STUN)", RFC 5389, DOI 10.17487/RFC5389, October 2008, https://www.rfc-editor.org/info/rfc5389.
- [RFC5626] Jennings, C., Ed., Mahy, R., Ed., and F. Audet, Ed., "Managing Client-Initiated Connections in the Session Initiation Protocol (SIP)", RFC 5626, DOI 10.17487/RFC5626, October 2009, https://www.rfc-editor.org/info/rfc5626.
- [RFC5766] Mahy, R., Matthews, P., and J. Rosenberg, "Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN)", RFC 5766, DOI 10.17487/RFC5766, April 2010, https://www.rfc-editor.org/info/rfc5766.
- [RFC5769] Denis-Courmont, R., "Test Vectors for Session Traversal Utilities for NAT (STUN)", RFC 5769, DOI 10.17487/RFC5769, April 2010, https://www.rfc-editor.org/info/rfc5769.
- [RFC5780] MacDonald, D. and B. Lowekamp, "NAT Behavior Discovery Using Session Traversal Utilities for NAT (STUN)", RFC 5780, DOI 10.17487/RFC5780, May 2010, https://www.rfc-editor.org/info/rfc5780.
- [RFC6544] Rosenberg, J., Keranen, A., Lowekamp, B., and A. Roach, "TCP Candidates with Interactive Connectivity Establishment (ICE)", RFC 6544, DOI 10.17487/RFC6544, March 2012, https://www.rfc-editor.org/info/rfc6544.
- [RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content", RFC 7231, DOI 10.17487/RFC7231, June 2014, https://www.rfc-editor.org/info/rfc7231.
- [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, https://www.rfc-editor.org/info/rfc8126.
- [RFC8264] Saint-Andre, P. and M. Blanchet, "PRECIS Framework: Preparation, Enforcement, and Comparison of Internationalized Strings in Application Protocols", RFC 8264, DOI 10.17487/RFC8264, October 2017, https://www.rfc-editor.org/info/rfc8264.
- [RFC8445] Keranen, A., Holmberg, C., and J. Rosenberg, "Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal", RFC 8445, DOI 10.17487/RFC8445, July 2018, https://www.rfc-editor.org/info/rfc8445.
- [RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018, https://www.rfc-editor.org/info/rfc8446.
- [STUN-PMTUD] Petit-Huguenin, M., Salgueiro, G., and F. Garrido, "Packetization Layer Path MTU Discovery (PLMTUD) For UDP Transports Using Session Traversal Utilities for NAT (STUN)", Work in Progress, draft-ietf-tram-stun-pmtud-15, December 2019.
- [UAX15] Unicode Standard Annex #15, "Unicode Normalization Forms", edited by Mark Davis and Ken Whistler. An integral part of The Unicode Standard, http://unicode.org/reports/tr15/.
Appendix A. C Snippet to Determine STUN Message Types ๐งฉ
okay this one's my favourite ๐ค it's a tiny bit of C that lets you figure out what kind of STUN message you're looking at ๐
Given a 16-bit STUN message type value in host byte order in msg_type parameter, below are C macros to determine the STUN message types:
#define IS_REQUEST(msg_type) (((msg_type) & 0x0110) == 0x0000)
#define IS_INDICATION(msg_type) (((msg_type) & 0x0110) == 0x0010)
#define IS_SUCCESS_RESP(msg_type) (((msg_type) & 0x0110) == 0x0100)
#define IS_ERR_RESP(msg_type) (((msg_type) & 0x0110) == 0x0110)
A function to convert method and class into a message type:
int type(int method, int cls) {
return (method & 0x1F80) << 2 | (method & 0x0070) << 1
| (method & 0x000F) | (cls & 0x0002) << 7
| (cls & 0x0001) << 4;
}
A function to extract the method from the message type:
int method(int type) {
return (type & 0x3E00) >> 2 | (type & 0x00E0) >> 1
| (type & 0x000F);
}
A function to extract the class from the message type:
int cls(int type) {
return (type & 0x0100) >> 7 | (type & 0x0010) >> 4;
}
Appendix B. Test Vectors ๐งช
this section adds MESSAGE-INTEGRITY-SHA256 to the test vectors from [RFC5769] ๐ so you can check your code against known-good bytes โจ
All the formats and definitions listed in Section 2 of [RFC5769] apply here.
B.1. Sample Request with Long-Term Authentication with MESSAGE-INTEGRITY-SHA256 and USERHASH ๐ธ
this request is the main character ๐ here are the parameters it uses:
- Username:
"<U+30DE><U+30C8><U+30EA><U+30C3><U+30AF><U+30B9>"(without quotes) unaffected by OpaqueString [RFC8265] processing - Password:
"The<U+00AD>M<U+00AA>tr<U+2168>"and"TheMatrIX"(without quotes) respectively before and after OpaqueString [RFC8265] processing - Nonce:
"obMatJos2AAACf//499k954d6OL34oL9FSTvy64sA"(without quotes) - Realm:
"example.org"(without quotes)
And here's the full message, byte by byte ๐
00 01 00 9c Request type and message length
21 12 a4 42 Magic cookie
78 ad 34 33 }
c6 ad 72 c0 } Transaction ID
29 da 41 2e }
00 1e 00 20 USERHASH attribute header
4a 3c f3 8f }
ef 69 92 bd }
a9 52 c6 78 }
04 17 da 0f } Userhash value (32 bytes)
24 81 94 15 }
56 9e 60 b2 }
05 c4 6e 41 }
40 7f 17 04 }
00 15 00 29 NONCE attribute header
6f 62 4d 61 }
74 4a 6f 73 }
32 41 41 41 }
43 66 2f 2f }
34 39 39 6b } Nonce value and padding (3 bytes)
39 35 34 64 }
36 4f 4c 33 }
34 6f 4c 39 }
46 53 54 76 }
79 36 34 73 }
41 00 00 00 }
00 14 00 0b REALM attribute header
65 78 61 6d }
70 6c 65 2e } Realm value (11 bytes) and padding (1 byte)
6f 72 67 00 }
00 1c 00 20 MESSAGE-INTEGRITY-SHA256 attribute header
e4 68 6c 8f }
0e de b5 90 }
13 e0 70 90 }
01 0a 93 ef } HMAC-SHA256 value
cc bc cc 54 }
4c 0a 45 d9 }
f8 30 aa 6d }
6f 73 5a 01 }
Acknowledgements ๐
huge thanks to everyone who dropped comments, suggestions, and questions that made this doc better ๐ซถ you're all iconic ๐ฅน
Thanks to Michael Tuexen, Tirumaleswar Reddy, Oleg Moskalenko, Simon Perreault, Benjamin Schwartz, Rifaat Shekh-Yusef, Alan Johnston, Jonathan Lennox, Brandon Williams, Olle Johansson, Martin Thomson, Mihaly Meszaros, Tolga Asveren, Noriyuki Torii, Spencer Dawkins, Dale Worley, Matthew Miller, Peter Saint-Andre, Julien Elie, Mirja Kuehlewind, Eric Rescorla, Ben Campbell, Adam Roach, Alexey Melnikov, and Benjamin Kaduk for the comments, suggestions, and questions that helped improve this document.
The Acknowledgements section of RFC 5389 appeared as follows:
The authors would like to thank Cedric Aoun, Pete Cordell, Cullen Jennings, Bob Penfield, Xavier Marjou, Magnus Westerlund, Miguel Garcia, Bruce Lowekamp, and Chris Sullivan for their comments, and Baruch Sterman and Alan Hawrylyshen for initial implementations. Thanks for Leslie Daigle, Allison Mankin, Eric Rescorla, and Henning Schulzrinne for IESG and IAB input on this work.
Contributors ๐ง
the OG crew ๐ฐ๏ธโจ
Christian Huitema and Joel Weinberger were original coauthors of RFC 3489.
Authors' Addresses ๐ฎ
the people behind the protocol ๐ here's how to reach them ๐ฆ
Marc Petit-Huguenin Impedance Mismatch
Email: marc@petit-huguenin.org
Gonzalo Salgueiro Cisco 7200-12 Kit Creek Road Research Triangle Park, NC 27709 United States of America
Email: gsalguei@cisco.com
Jonathan Rosenberg Five9 Edison, NJ United States of America
Email: jdrosen@jdrosen.net URI: http://www.jdrosen.net
Dan Wing Citrix Systems, Inc. United States of America
Email: dwing-ietf@fuggles.com
Rohan Mahy Unaffiliated
Email: rohan.ietf@gmail.com
Philip Matthews Nokia 600 March Road Ottawa, Ontario K2K 2T6 Canada
Phone: 613-784-3139 Email: philip_matthews@magma.ca
๐ฆ where this page comes from
- ietf: rfc8489 2020-02
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms