RFC 6314
NAT Traversal Practices for Client-Server SIP
Part 1 of 15 π
RFC 6314: NAT Traversal Practices for Client-Server SIP π
okay bestie, welcome to RFC 6314 π¦ It's an Informational doc from July 2011, published under ISSN 2070-1721. The authors are C. Boulton (NS-Technologies), J. Rosenberg (Skype), G. Camarillo (Ericsson) and F. Audet (Skype). This title block doesn't list anything it obsoletes or updates, so there's no drama there β¨
Abstract
Getting SIP, and the sessions it sets up, through NATs is a seriously complicated problem π There are so many deployment scenarios and so many traversal mechanisms for media traffic. This doc gives concrete recommendations and one unified method for NAT traversal, and it also writes down the flows that go with it. It's giving clarity π
Status of This Memo
This document is not an Internet Standards Track specification. It's published for informational purposes πΈ
This doc is a product of the Internet Engineering Task Force (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). Not every IESG-approved document is a candidate for any level of Internet Standard, so check Section 2 of RFC 5741 if you're curious π§
More info about the status of this doc, any errata, and how to send feedback lives at http://www.rfc-editor.org/info/rfc6314.
Copyright Notice
Copyright (c) 2011 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 (http://trustee.ietf.org/license-info) as they stand on the publication date. Please read these carefully, because they spell out your rights and restrictions for this doc π«Ά Any Code Components pulled out of this document have to include the Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come with no warranty, as described in the Simplified BSD License.
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
2. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 4
3. Problem Statement . . . . . . . . . . . . . . . . . . . . . . 4
4. Solution Technology Outline Description . . . . . . . . . . . 8
4.1. SIP Signaling . . . . . . . . . . . . . . . . . . . . . . 8
4.1.1. Symmetric Response . . . . . . . . . . . . . . . . . . 8
4.1.2. Client-Initiated Connections . . . . . . . . . . . . . 9
4.2. Media Traversal . . . . . . . . . . . . . . . . . . . . . 10
4.2.1. Symmetric RTP/RTCP . . . . . . . . . . . . . . . . . . 10
4.2.2. RTCP . . . . . . . . . . . . . . . . . . . . . . . . . 10
4.2.3. STUN/TURN/ICE . . . . . . . . . . . . . . . . . . . . 11
5. NAT Traversal Scenarios . . . . . . . . . . . . . . . . . . . 12
5.1. Basic NAT SIP Signaling Traversal . . . . . . . . . . . . 12
5.1.1. Registration (Registrar/Edge Proxy Co-Located) . . . . 12
5.1.2. Registration(Registrar/Edge Proxy Not Co-Located) . . 16
5.1.3. Initiating a Session . . . . . . . . . . . . . . . . . 19
5.1.4. Receiving an Invitation to a Session . . . . . . . . . 22
5.2. Basic NAT Media Traversal . . . . . . . . . . . . . . . . 27
5.2.1. Endpoint-Independent NAT . . . . . . . . . . . . . . . 28
5.2.2. Address/Port-Dependent NAT . . . . . . . . . . . . . . 48
6. IPv4-IPv6 Transition . . . . . . . . . . . . . . . . . . . . . 57
6.1. IPv4-IPv6 Transition for SIP Signaling . . . . . . . . . . 57
7. Security Considerations . . . . . . . . . . . . . . . . . . . 57
8. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 57
9. References . . . . . . . . . . . . . . . . . . . . . . . . . . 58
9.1. Normative References . . . . . . . . . . . . . . . . . . . 58
9.2. Informative References . . . . . . . . . . . . . . . . . . 59
1. Introduction π
okay so NAT (Network Address Translator) traversal has been known as a complicated problem for a long time π It gets even messier when you bring in the Session Initiation Protocol (SIP) [RFC3261] and its media, like the Real-time Transport Protocol (RTP) [RFC3550]. What makes it worse is how many kinds of NATs are out there and how many possible deployment scenarios there are. If you want the details on how different NATs behave, check "NAT Behavioral Requirements for Unicast UDP" [RFC4787] π
The IETF has been busy with lots of NAT traversal specs, like Session Traversal Utilities for NAT (STUN) [RFC5389], Interactive Connectivity Establishment (ICE) [RFC5245], symmetric response [RFC3581], symmetric RTP [RFC4961], Traversal Using Relay NAT (TURN) [RFC5766], SIP Outbound [RFC5626], the Session Description Protocol (SDP) attribute for RTP Control Protocol (RTCP) [RFC3605], "Multiplexing RTP Data and Control Packets on a Single Port" [RFC5761], and more π Each one is a piece of the puzzle, but none of them shows the big picture of how the NAT traversal problem gets broken down and solved across the whole collection. That's the gap this doc fills π¦ Also, this doc deliberately does not use the 'Best Current Practice' machinery defined in RFC 2026 [RFC2026], so just know that going in π«Ά
The doc is split into two distinct sections:
- Section 4 gives a definitive set of best common practices for getting SIP and its media through NAT devices π
- Section 5 gives non-normative examples of SIP interactions across various NAT deployment types π
The doc doesn't propose any new functionality. It draws on existing solutions for both core SIP signaling and media traversal, as defined in Section 4 β¨
The best practices in here are for traditional "client-server"-style SIP. That term means the classic SIP setup where User Agents talk to a series of intermediaries on the path to reach a remote User Agent π§ Other groups using SIP, like peer-to-peer SIP (P2PSIP), will probably recommend these same practices between a P2PSIP client and a P2PSIP peer. But for use between peers in a peer-to-peer network, they'll probably recommend different practices π
2. Terminology π
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [RFC2119] π₯
Quick heads-up: when this doc says 'Endpoint-Independent NAT', it means a NAT that is both Endpoint-Independent Filtering and Endpoint-Independent Mapping, per the definitions in RFC 4787 [RFC4787] β¨
3. Problem Statement π
Okay bestie, let's talk about why SIP and NATs are literally not friends π Getting SIP through NATs splits into two categories that both need attention: the core SIP signaling, and the media traversal. This document assumes NATs without SIP-aware Application Layer Gateways (ALGs), which makes a lot of the issues discussed here not applicable β¨. ALGs have limitations (as per RFC 4787 [RFC4787] Section 7, RFC 3424 [RFC3424], and [RFC5245] Section 18.6), and experience shows they can seriously mess with SIP functionality π. That includes problems like requiring the media and signaling to traverse the same device, and not working with encrypted signaling and/or payload.
The use of non-TURN-based media intermediaries is not considered in this document. If you want more info, check out [RFC5853] and [MIDDLEBOXES] π¦
The core SIP signaling has a bunch of issues when it goes through NATs, so let's get into it πΈ
SIP response routing over UDP, as defined in RFC 3261 [RFC3261] without extensions, causes the response to be delivered to the source IP address in the topmost Via header, or the 'received' parameter of the topmost 'Via' header. The port gets pulled out of the SIP 'Via' header to complete the IP address/port combo for returning the response. The destination is correct, but the port in the 'Via' header is the listening port of the originating client, not the port representing the open pinhole on the NAT π. So responses get sent back to the NAT, but to a port that's likely not open for SIP traffic, and the NAT drops the response. Figure 1 shows a SIP response being returned to port 5060 (the chaos is real π):
Private NAT Public
Network | Network
|
|
-------- SIP Request |open port 10923 --------
| |-------------------->--->-----------------------| |
| | | | |
| Client | |port 5060 SIP Response | Proxy |
| | x<------------------------| |
| | | | |
-------- | --------
|
|
|
Figure 1: Failed Response
Secondly, there are two cases where new requests reuse existing connections π. The first is when you're using a reliable, connection-oriented transport protocol like TCP. SIP has an inherent mechanism where SIP responses reuse the connection that was created or used for the corresponding transactional request, which is iconic. BUT, SIP doesn't give you a mechanism that lets new requests going the reverse direction use the existing connection, like the TCP connection the client made to the server during registration. So the registered contact address doesn't get bound to the "connection" in the case of TCP, and requests get blocked at the NAT, as shown in Figure 2 π. The second case is when you're using an unreliable transport protocol like UDP, where the external NAT mappings need to be reused to reach a SIP entity on the private side of the network.
Private NAT Public
Network | Network
|
|
-------- (UAC 8023) REGISTER/Response (UAS 5060) --------
| |-------------------->---<-----------------------| |
| | | | |
| Client | |5060 INVITE (UAC 8015)| Proxy |
| | x<------------------------| |
| | | | |
-------- | --------
|
|
|
Figure 2: Failed Request
In Figure 2, the original REGISTER request is sent from the client on port 8023 and received by the proxy on port 5060, which sets up a connection and opens a pinhole in the NAT π¦. Then the proxy generates a new request, and that request is destined for the registered entity (the contact IP address), which isn't reachable from the public network. So the new SIP request ends up trying to create a connection to a private network address π©. This problem would be solved if the original connection were reused. This problem has been talked about in the context of connection-oriented protocols like TCP, but it actually exists for SIP signaling over any transport protocol π. The impact of connection reuse on connection-oriented transports (TCP, TLS, etc.) is covered in more detail in the connection reuse specification [RFC5923]. The approach proposed for this problem in Section 4 of this document is relevant for all SIP signaling in conjunction with connection reuse, regardless of the transport protocol β¨.
NAT policy can dictate that connections get closed after a period of inactivity. That inactivity period can be anywhere from a number of seconds to hours β°. SIP signaling can't be relied on to keep connections alive, for two reasons. First, SIP entities can sometimes have no signaling traffic for long stretches, which has the potential to exceed the inactivity timer. That can cause endpoints to be unavailable to receive incoming requests, because the connection has already been closed π. Second, if a low inactivity timer is specified, SIP signaling isn't appropriate as a keep-alive mechanism, because it has the potential to add a huge amount of traffic to the network. That burns valuable resources and also needs processing at a SIP stack, which is a waste of processing resources too π.
Media associated with SIP calls also has problems traversing NATs π. RTP [RFC3550] runs over UDP and is one of the most common media transport types used with SIP signaling. RTP is negotiated during SIP session establishment using the Session Description Protocol (SDP) [RFC4566] and a SIP offer/answer exchange [RFC3264]. During that offer/answer exchange, each client in a session specifies an IP address and port combination as a way of receiving media such as RTP. The problem shows up when a client advertises an address to receive media, and that address sits in a private network that isn't accessible from outside the NAT π¬. Figure 3 illustrates this problem.
NAT Public Network NAT
| |
| |
| |
-------- | SIP Signaling Session | --------
| |---------------------->Proxy<-------------------| |
| | | | | |
| Client | | | | Client |
| A |>=====>RTP>==Unknown Address==>X | | B |
| | | X<==Unknown Address==<RTP<===<| |
-------- | | --------
| |
| |
| |
Figure 3: Failed Media
The connection addresses of clients behind NATs will nominally contain a private IPv4 address that isn't routable across the public Internet π«. To make things even worse, Client A tends to send media to the destination address it received in the signaling confirmation message. That address may actually correspond to a host inside the private network, which is suddenly hit with incoming RTP packets it never asked for (and likewise, Client B may send media to a host inside its private network that didn't solicit those packets) π±. Finally, to complicate things even further, a number of different NAT topologies with different default behaviors make it harder to arrive at a unified approach π. This problem exists for all media transport protocols that might be NATted (e.g., TCP, UDP, the Stream Control Transmission Protocol (SCTP), the Datagram Congestion Control Protocol (DCCP)).
In general, the problems associated with NAT traversal can be categorized as follows π.
For signaling:
- Responses do not reuse the NAT mapping and filtering entries created by the request.
- Inbound requests are filtered out by the NAT because there is no long-term connection between the client and the proxy.
For media:
- Each endpoint has a variety of addresses that can be used to reach it (e.g., native interface address, public NATted address). In different situations, a different pair of (local endpoint, remote endpoint) addresses should be used, and it is not clear when to use which pair π€.
- Many NATs filter inbound packets if the local endpoint has not recently sent an outbound packet to the sender.
- Classic RTCP usage is to run RTCP on the next highest port. However, NATs do not necessarily preserve port adjacency π.
- Classic RTP and RTCP usage is to use different 5-tuples for traffic in each direction. Though not really a problem, doing this through NATs is more work than using the same 5-tuple in both directions π .
4. Solution Technology Outline Description π§
As mentioned previously, getting SIP through existing NATs can be divided into two discrete problem areas: getting the SIP signaling across NATs, and enabling the media (as specified by SDP in a SIP offer/answer exchange) to flow between endpoints π«Ά.
4.1. SIP Signaling
SIP signaling has two areas that result in transactional failure when traversing NATs, as described in Section 3 of this document. The remaining sub-sections describe appropriate solutions that get SIP signaling traversing NATs, regardless of transport protocol. It is advised that SIP-compliant entities follow the guidelines in this section to enable traversal of SIP signaling through NATs β¨
4.1.1. Symmetric Response β¨
okay so, like we said in Section 3 of this document, when you're using an unreliable transport like UDP, SIP responses get sent to the IP address and port combo in the SIP Via header (or the default port for the transport protocol if there isn't one) π«Ά. Figure 4 shows the response sneaking back through the open pinhole using the Symmetric techniques from RFC 3581 [RFC3581] π¦
Private NAT Public
Network | Network
|
|
-------- | --------
| | | | |
| |send request---------------------------------->| |
| Client |<---------------------------------send response| SIP |
| A | | | Proxy |
| | | | |
-------- | --------
|
|
|
Figure 4: Symmetric Response
the outgoing request from Client A opens a pinhole in the NAT πΈ. The SIP Proxy would normally respond to the port available in the SIP Via header, as in Figure 1. But the SIP Proxy honors the rport parameter in the SIP Via header and routes the response to the port it was sent from, which is so iconic π
. The exact functionality for this method of response traversal is called 'Symmetric Response', and the details are documented in RFC 3581 [RFC3581]. Additional requirements are imposed on SIP entities in RFC 3581 [RFC3581] too, like listening and sending SIP requests/responses from the same port π.
4.1.2. Client-Initiated Connections π§
the second problem with SIP signaling, as defined in Section 3 and illustrated in Figure 2, is making sure incoming requests get routed properly. It's giving main character problem π.
Guidelines for devices such as User Agents that can only generate outbound connections through NATs are documented in "Managing Client-Initiated Connections in the Session Initiation Protocol (SIP)" [RFC5626]. The document gets into techniques that use a unique User Agent instance identifier (instance-id) together with a flow identifier (reg-id). The combination of the two identifiers gives you a key to a particular connection (both UDP and TCP) that gets stored alongside registration bindings. When an incoming request comes in for a SIP Address-Of-Record (AOR), a proxy/registrar routes it to the associated flow created by the registration, and that's how it gets a route through NATs. It also provides a keep-alive mechanism so clients can keep their NAT bindings alive β¨. This is done by multiplexing a ping-pong mechanism over the SIP signaling connection (STUN for UDP and CRLF/operating system keepalive for reliable transports like TCP). Usage of [RFC5626] is RECOMMENDED. This mechanism is not transport specific and should be used for any transport protocol π.
Even if the SIP Outbound mechanism isn't used, clients generating SIP requests SHOULD use the same IP address and port (i.e., socket) for both sending and receiving SIP messages. Doing so lets the vast majority of industry provided solutions function properly (e.g., NAT traversal that is Session Border Control (SBC) hosted) π. Deployments should also consider the mechanism described in the Connection Reuse [RFC5923] specification for routing bidirectional messages securely between trusted SIP Proxy servers π₯.
4.2. Media Traversal π
the issues of media traversal through NATs are not straightforward, and they need a combo of a number of traversal methodologies. The technologies outlined in the rest of this section provide the required solution set π«Ά.
4.2.1. Symmetric RTP/RTCP π¦
the primary problem identified in Section 3 of this document is that internal IP address/port combinations can't be reached from the public side of NATs. For media like RTP, this means no audio gets through the NAT (as illustrated in Figure 3) π. To fix this, a technique called 'Symmetric RTP/RTCP' [RFC4961] can be used. It involves a SIP endpoint both sending and receiving RTP/RTCP traffic from the same IP address/port combination. When operating behind a NAT and using the 'latching' technique described in [MIDDLEBOXES], SIP User Agents MUST implement Symmetric RTP/RTCP. This is what allows RTP to traverse the NAT π.
4.2.2. RTCP πΈ
normal practice when picking a port for RTP Control Protocol (RTCP) [RFC3550] is consecutive-order numbering (so, an incremented port for RTCP from the one used for RTP). That assumption breaks RTCP traffic when it goes through certain types of NATs for various reasons (e.g., an already allocated port, or randomized port allocation) π. To combat this, a specific address and port need to be specified in the SDP rather than relying on that assumption. RFC 3605 [RFC3605] defines an SDP attribute that explicitly specifies transport connection information for RTCP, so a separate, explicit NAT binding can be set up just for it π. The address details can be obtained using any appropriate method, including those detailed in this section (e.g., STUN, TURN, ICE).
A further enhancement to RFC 3605 [RFC3605] is defined in [RFC5761], which specifies 'muxing' both RTP and RTCP on the same IP/PORT combination π§.
4.2.3. STUN/TURN/ICE π
ICE, STUN, and TURN are a suite of 3 inter-related protocols that work together to give you a complete media traversal solution for NATs. The following sections break down each component part π«Ά.
4.2.3.1. STUN π₯
Session Traversal Utilities for NAT or STUN is defined in RFC 5389 [RFC5389]. STUN is a lightweight tool kit and protocol that tells you the external IP address/port combination the NAT device uses to represent the internal entity on the public-facing side of NATs π. Once a client learns this external representation, it can use it as the connection address in SDP to get NAT traversal. Using terminology defined in "NAT Behavioral Requirements for Unicast UDP" [RFC4787], STUN does work with Endpoint-Independent Mapping but does not work with either Address-Dependent Mapping or Address and Port-Dependent Mapping type NATs π. Using STUN with either of the previous two NAT mappings to probe for the external IP address/port representation will give a different result from what's needed for traversal by an alternative SIP entity. The IP address/port combination deduced for the STUN server would be blocked for RTP packets from the remote SIP User Agent π.
As mentioned in Section 4.1.2, STUN is also used as a client-to-server keep-alive mechanism to refresh NAT bindings π¦.
4.2.3.2. TURN π
As described in Section 4.2.3.1, the STUN protocol doesn't work for UDP traversal through certain identified NAT mappings. 'Traversal Using Relays around NAT' is a usage of the STUN protocol for deriving (from a TURN server) an address that gets used to relay packets towards a client π§. TURN gives you an external address (globally routable) at a TURN server that acts as a media relay, trying to let traffic reach the associated internal address. The full details of the TURN specification are defined in [RFC5766]. A TURN service will almost always carry media traffic for a SIP entity, but it is RECOMMENDED that this method only be used as a last resort and not as a general mechanism for NAT traversal π. That's because TURN has high performance costs when relaying media traffic and can lead to unwanted latency π.
4.2.3.3. ICE π
Interactive Connectivity Establishment (ICE) is the RECOMMENDED method for traversing existing NATs if Symmetric RTP and media latching aren't sufficient β¨. ICE is a methodology that uses existing technologies such as STUN, TURN, and any other protocol compliant with Unilateral Self-Address Fixing (NSAF) [RFC3424] to provide a unified solution π«Ά. This is achieved by gathering as many representative IP address/port combinations as possible using technologies such as STUN/TURN (note: an ICE endpoint can also use other mechanisms (e.g., the NAT Port Mapping Protocol [NAT-PMP], Universal Plug and Play Internet Gateway Device [UPnP-IGD]) to learn public IP addresses and ports, and populate a=candidate lines with that information) πΈ. Once the addresses are accumulated, they are all included in the SDP exchange in a new media attribute called 'candidate'. Each candidate SDP attribute entry has detailed connection information, including a media address, priority, and transport protocol. The appropriate IP address/port combinations are used in the order specified by the priority π. A client compliant to the ICE specification will then locally run STUN servers on all addresses being advertised using ICE. Each instance undertakes connectivity checks to make sure a client can successfully receive media on the advertised address. Only connections that pass the relevant connectivity checks are used for media exchange π₯. The full details of the ICE methodology are in [RFC5245].
5. NAT Traversal Scenarios π
This section of the document includes detailed NAT traversal scenarios for both SIP signaling and the associated media. Signaling NAT traversal is achieved using [RFC5626] π .
5.1. Basic NAT SIP Signaling Traversal π¦
The following sub-sections concentrate on SIP signaling traversal of NATs. The scenarios include traversal for both reliable and unreliable transport protocols β¨.
5.1.1. Registration (Registrar/Edge Proxy Co-Located) π§
The set of scenarios in this section documents basic signaling traversal of a SIP REGISTER method through NATs π«Ά.
5.1.1.1. UDP β¨
Okay so Bob is sending a SIP REGISTER through a NAT, and it's giving main character energy π . He includes an rport parameter, which is described in Section 4.1.1 of this document, so the UDP responses can get through the NAT π¦. The original request, shown as (1) in Figure 5, is a totally standard SIP REGISTER message:
Registrar/
Bob NAT Edge Proxy
| | |
|(1) REGISTER | |
|----------------->| |
| | |
| |(1) REGISTER |
| |----------------->|
| | |
|*************************************|
| Create Outbound Connection Tuple |
|*************************************|
| | |
| |(2) 200 OK |
| |<-----------------|
| | |
|(2) 200 OK | |
|<-----------------| |
| | |
Figure 5: UDP Registration
Message 1:
REGISTER sip:example.com SIP/2.0
Via: SIP/2.0/UDP 192.168.1.2;rport;branch=z9hG4bKnashds7
Max-Forwards: 70
From: Bob <sip:bob@example.com>;tag=7F94778B653B
To: Bob <sip:bob@example.com>
Call-ID: 16CB75F21C70
CSeq: 1 REGISTER
Supported: path, outbound
Contact: <sip:bob@192.168.1.2 >;reg-id=1
;+sip.instance="<urn:uuid:00000000-0000-1000-8000-AABBCCDDEEFF>"
Content-Length: 0
Then this SIP transaction generates a SIP 200 OK response, which is (2) in Figure 5 π:
Message 2:
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.1.2;rport=8050;branch=z9hG4bKnashds7;
received=172.16.3.4
From: Bob <sip:bob@example.com>;tag=7F94778B653B
To: Bob <sip:bob@example.com>;tag=6AF99445E44A
Call-ID: 16CB75F21C70
CSeq: 1 REGISTER
Supported: path, outbound
Require: outbound
Contact: <sip:bob@192.168.1.2 >;reg-id=1;expires=3600
;+sip.instance="<urn:uuid:00000000-0000-1000-8000-AABBCCDDEEFF>"
Content-Length: 0
Okay, the plot twist π. The response goes to the address in the received parameter of the SIP Via header, which is 172.16.3.4. It does not go to the port you'd work out from the Via header like normal SIP does. Instead it goes to whatever got stamped into the rport parameter of the Via header, which is port 8050. For the response to actually make it through the NAT, every convention in RFC 3581 [RFC3581] has to be followed π
.
Also, look at the reg-id and sip.instance Contact header parameters. Those are what get used to set up an outbound connection tuple, as defined in [RFC5626] β¨. You can see the connection tuple creation in Figure 5. The payoff is that any inbound request that triggers a registration lookup gets sent back down the connection path the registration already set up. No more messing with Contact header URIs to make them look globally routable from the public side of the NAT ππ«Ά.
5.1.1.2. Connection-Oriented Transport
Registrar/
Bob NAT Edge Proxy
| | |
|(1) REGISTER | |
|----------------->| |
| | |
| |(1) REGISTER |
| |----------------->|
| | |
|*************************************|
| Create Outbound Connection Tuple |
|*************************************|
| | |
| |(2) 200 OK |
| |<-----------------|
| | |
|(2) 200 OK | |
|<-----------------| |
| | |
Figure 6
Using a reliable, connection-oriented protocol like TCP to traverse SIP REGISTER requests and responses doesn't need any extra core SIP signaling extensions, beyond what's already defined in [RFC5626] πΈ. SIP responses reuse the connection that was created for the first REGISTER request, which is (1) in Figure 6:
Message 1:
REGISTER sip:example.com SIP/2.0
Via: SIP/2.0/TCP 192.168.1.2;branch=z9hG4bKnashds7
Max-Forwards: 70
From: Bob <sip:bob@example.com>;tag=7F94778B653B
To: Bob <sip:bob@example.com>
Call-ID: 16CB75F21C70
CSeq: 1 REGISTER
Supported: path, outbound
Contact: <sip:bob@192.168.1.2;transport=tcp>;reg-id=1
;+sip.instance="<urn:uuid:00000000-0000-1000-8000-AABBCCDDEEFF>"
Content-Length: 0
Message 2:
SIP/2.0 200 OK
Via: SIP/2.0/TCP 192.168.1.2;branch=z9hG4bKnashds7
From: Bob <sip:bob@example.com>;tag=7F94778B653B
To: Bob <sip:bob@example.com>;tag=6AF99445E44A
Call-ID: 16CB75F21C70
CSeq: 1 REGISTER
Supported: path, outbound
Require: outbound
Contact: <sip:bob@192.168.1.2;transport=tcp>;reg-id=1;expires=3600
;+sip.instance="<urn:uuid:00000000-0000-1000-8000-AABBCCDDEEFF>"
Content-Length: 0
This example shows the sip.instance Contact header parameter in action, as defined in the SIP Outbound specification [RFC5626] π§. It creates an association tuple, same as in the previous example, so future inbound requests aimed at the new registration binding can find their way back. The only real difference is that the association is with a TCP connection instead of a UDP pinhole binding π.
5.1.2. Registration(Registrar/Edge Proxy Not Co-Located) β¨
This section shows how traversal works when the Registrar isn't living in the same place as the edge proxy π. The steps are the same no matter which transport protocol you use, so the only example here uses TCP.
Bob NAT Edge Proxy Registrar
| | | |
|(1) REGISTER | | |
|----------------->| | |
| | | |
| |(1) REGISTER | |
| |----------------->| |
| | | |
| | |(2) REGISTER |
| | |----------------->|
| | | |
|*************************************| |
| Create Outbound Connection Tuple | |
|*************************************| |
| | | |
| | |(3) 200 OK |
| | |<-----------------|
| |(4)200 OK | |
| |<-----------------| |
| | | |
|(4)200 OK | | |
|<-----------------| | |
| | | |
Figure 7: Registration (Registrar/Proxy Not Co-Located)
This one builds on the co-located example from Section 5.1.1.2 π«Ά. The main difference is that the REGISTER request gets routed onward from a proxy server to a separate Registrar. The key message to look at is (1) in Figure 7. When the edge proxy gets a REGISTER request containing a sip.instance media feature tag, it forms a unique flow identifier token as discussed in [RFC5626] π₯. Then the proxy server routes the SIP REGISTER message on to the Registrar. The proxy creates the connection tuple, as described in SIP Outbound, at the same moment as in the co-located example. But for later messages to reach the proxy, the proxy has to say that it needs to stay in the SIP signaling path. To do that, it inserts a SIP Path extension header into REGISTER message (2), as defined in RFC 3327 [RFC3327] π. The flow association token goes somewhere inside the Path header where it can be pulled back out easily later, when messages that need routing to the registration binding come in. In this case that's the user part of the SIP URI. The REGISTER message in (1) includes a SIP Route header for the edge proxy.
Message 1:
REGISTER sip:example.com SIP/2.0
Via: SIP/2.0/TCP 192.168.1.2;branch=z9hG4bKnashds7
Max-Forwards: 70
From: Bob <sip:bob@example.com>;tag=7F94778B653B
To: Bob <sip:bob@example.com>
Call-ID: 16CB75F21C70
CSeq: 1 REGISTER
Supported: path, outbound
Route: <sip:ep1.example.com;lr>
Contact: <sip:bob@192.168.1.2;transport=tcp>;reg-id=1
;+sip.instance="<urn:uuid:00000000-0000-1000-8000-AABBCCDDEEFF>"
Content-Length: 0
Here's what it looks like once it's proxied in (2):
Message 2:
REGISTER sip:example.com SIP/2.0
Via: SIP/2.0/TCP ep1.example.com;branch=z9hG4bKnuiqisi
Via: SIP/2.0/TCP 192.168.1.2;branch=z9hG4bKnashds7
Max-Forwards: 69
From: Bob <sip:bob@example.com>;tag=7F94778B653B
To: Bob <sip:bob@example.com>
Call-ID: 16CB75F21C70
CSeq: 1 REGISTER
Supported: path, outbound
Contact: <sip:bob@192.168.1.2;transport=tcp>;reg-id=1
;+sip.instance="<urn:uuid:00000000-0000-1000-8000-AABBCCDDEEFF>"
Path: <sip:VskztcQ/S8p4WPbOnHbuyh5iJvJIW3ib@ep1.example.com;lr;ob>
Content-Length: 0
When this REGISTER request lands, the Path header gets stored at the Registrar along with the AOR and its binding π§. The URI in the Path header gets slotted in as a pre-loaded SIP Route header on any request that reaches the Registrar and is aimed at that AOR binding. Basically this almost guarantees that every request for the new registration gets forwarded to the edge proxy π. In our example, the user part of the SIP Path header URI, which the edge proxy inserted, holds the unique token that identifies the client's flow. When later requests come in, the edge proxy checks the user part of the pre-loaded SIP Route header, pulls out that flow token, and uses it for its connection tuple comparison, as defined in the SIP Outbound specification [RFC5626] π¦. There's an example building on this scenario, showing an inbound request to the AOR, in Section 5.1.4.2 of this document β¨.
5.1.3. Initiating a Session π
This section covers the basic SIP signaling when you start a call from behind a NAT π.
5.1.3.1. UDP β¨
Okay bestie, this is the call setup over UDP, where the edge proxy and the authoritative proxy are living in the same box π¦π«Ά Bob's on the inside of a NAT, Alice is out in the wild, and we're watching the INVITE go out and the answer come all the way back π
Edge Proxy/
Bob NAT Auth. Proxy Alice
| | | |
|(1) INVITE | | |
|----------------->| | |
| | | |
| |(1) INVITE | |
| |----------------->| |
| | | |
| | |(2) INVITE |
| | |---------------->|
| | | |
| | |(3)180 RINGING |
| | |<----------------|
| | | |
| |(4)180 RINGING | |
| |<-----------------| |
| | | |
|(4)180 RINGING | | |
|<-----------------| | |
| | | |
| | |(5)200 OK |
| | |<----------------|
| | | |
| |(6)200 OK | |
| |<-----------------| |
| | | |
|(6)200 OK | | |
|<-----------------| | |
| | | |
|(7)ACK | | |
|----------------->| | |
| | | |
| |(7)ACK | |
| |----------------->| |
| | | |
| | |(8) ACK |
| | |---------------->|
| | | |
Figure 8: Initiating a Session - UDP π¦
The initiating client makes an INVITE request that gets sent through the NAT to a proxy server. That INVITE is step (1) in Figure 8, and it looks like this π
Message 1:
INVITE sip:alice@a.example SIP/2.0
Via: SIP/2.0/UDP 192.168.1.2;rport;branch=z9hG4bKnashds7
Max-Forwards: 70
From: Bob <sip:bob@example.com>;tag=ldw22z
To: Alice <sip:alice@a.example>
Call-ID: 95KGsk2V/Eis9LcpBYy3
CSeq: 1 INVITE
Supported: outbound
Route: <sip:ep1.example.com;lr>
Contact: <sip:bob@192.168.1.2;ob>
Content-Type: application/sdp
Content-Length: ...
[SDP not shown]
There are a couple of things to notice in this message π§
- First up, just like the registration example in Section 5.1.1.1, responses to this request won't automatically make their way back through a NAT. So the
rportflag gets added to the SIPViaheader, which is the Section 4.1.1 ("Symmetric Response") trick defined in RFC 3581 [RFC3581] πͺ - Second, the
obparameter goes onto theContactheader so that every later request gets sent down the same flow π The other option would have been a Globally Routable User Agent URI (GRUU), and you can read about that in Section 4.3 of [RFC5626] π
When the proxy handles (2), it adds itself to the Via header, fills in the rport port number and the received parameter on the earlier Via header, takes out the Route header, and slips in a Record-Route with a token π
Message 2:
INVITE sip:alice@172.16.1.4 SIP/2.0
Via: SIP/2.0/UDP ep1.example.com;branch=z9hG4bKnuiqisi
Via: SIP/2.0/UDP 192.168.1.2;rport=8050;branch=z9hG4bKnashds7;
received=172.16.3.4
Max-Forwards: 69
From: Bob <sip:bob@example.com>;tag=ldw22z
To: Alice <sip:alice@a.example>
Call-ID: 95KGsk2V/Eis9LcpBYy3
CSeq: 1 INVITE
Supported: outbound
Record-Route: <sip:3yJEbr1GYZK9cPYk5Snocez6DzO7w+AX@ep1.example.com;lr>
Contact: <sip:bob@192.168.1.2;ob>
Content-Type: application/sdp
Content-Length: ...
[SDP not shown]
5.1.3.2. Connection-Oriented Transport π
When you're on a reliable transport like TCP, the call flow and the NAT traversal steps are basically the same as in Section 5.1.3.1, ngl π The big difference is that symmetric response [RFC3581] isn't required for SIP responses to get through a NAT. RFC 3261 [RFC3261] already says SIP responses go back out over the same connection the request came in on 𧦠For an example flow of an outgoing call, check out Section 9.5 of [RFC5626] β¨
5.1.4. Receiving an Invitation to a Session π©
This section is all about a client sitting behind a NAT getting an inbound request through that NAT π These scenarios build on the registration scenarios from Sections 5.1.1 and 5.1.2 in this document, so you'll want to have those fresh in your head π§
5.1.4.1. Registrar/Proxy Co-Located π
The SIP signaling on the inside of the network (behind the user's proxy) isn't really affected by which transport protocol is used, so one example is enough π This one uses UDP and picks up right where the registration from Section 5.1.1.1 left off π
Edge Proxy
Bob NAT Auth. Proxy Alice
| | | |
|*******************************************************|
| Registration Binding Installed in |
| Section 5.1.1.1 |
|*******************************************************|
| | | |
| | |(1)INVITE |
| | |<----------------|
| | | |
| |(2)INVITE | |
| |<-----------------| |
| | | |
|(2)INVITE | | |
|<-----------------| | |
| | | |
| | | |
Figure 9: Receiving an Invitation to a Session π
An INVITE shows up at the authoritative proxy, pointed at the AOR that was set up in Section 5.1.1.1. That's step (1) in Figure 9, and it looks like this π
INVITE sip:bob@example.com SIP/2.0
Via: SIP/2.0/UDP 172.16.1.4;branch=z9hG4bK74huHJ37d
Max-Forwards: 70
From: External Alice <sip:alice@example.com>;tag=02935
To: Bob <sip:bob@example.com>
Call-ID: klmvCxVWGp6MxJp2T2mb
CSeq: 1 INVITE
Contact: <sip:alice@172.16.1.4>
Content-Type: application/sdp
Content-Length: ..
[SDP not shown]
The INVITE matches the registration binding that got saved at the Registrar, and the Request-URI of the INVITE gets rewritten to the chosen onward address πͺ The proxy then looks at the Request-URI and checks it against its list of connection tuples. It starts with the incoming AOR and looks for any open connections or mappings tied to it π Once there's a match, the proxy checks whether the unique instance identifier (+sip.instance) on the binding equals the instance identifier on that connection tuple. If it does, the request goes out on the right binding π― That forwarded copy is step (2) in Figure 9, and it looks like this π
INVITE sip:bob@192.168.1.2 SIP/2.0
Via: SIP/2.0/UDP ep1.example.com;branch=z9hG4kmlds893jhsd
Via: SIP/2.0/UDP 172.16.1.4;branch=z9hG4bK74huHJ37d
Max-Forwards: 69
From: Alice <sip:alice@example.com>;tag=02935
To: client bob <sip:bob@example.com>
Call-ID: klmvCxVWGp6MxJp2T2mb
CSeq: 1 INVITE
Contact: <sip:alice@172.16.1.4>
Content-Type: application/sdp
Content-Length: ..
[SDP not shown]
Honestly, it's just a standard SIP INVITE with nothing extra going on π The big twist is that this request doesn't get sent to the address in the Request-URI the way normal SIP rules would have it. Instead, it goes out on the flow tied to the registration binding. (The lookup procedures in RFC 3263 [RFC3263] get overridden by RFC 5626 [RFC5626] here π ) That means the original connection or mapping from the first registration gets reused, and that's the whole trick π¦β¨
5.1.4.2. Edge Proxy/Authoritative Proxy Not Co-Located π¦
okay so the core SIP signaling here doesn't care what transport you're using at all π , so we only need ONE example scenario. bestie, it's giving efficiency. π§ It uses UDP and picks up right where the registration from Section 5.1.2 left off π«Ά
Bob NAT Edge Proxy Auth. Proxy Alice
| | | | |
|***********************************************************|
| Registration Binding Installed in |
| Section 5.1.2 |
|***********************************************************|
| | | | |
| | | |(1)INVITE |
| | | |<-------------|
| | | | |
| | |(2)INVITE | |
| | |<-------------| |
| | | | |
| |(3)INVITE | | |
| |<-------------| | |
| | | | |
|(3)INVITE | | | |
|<-------------| | | |
| | | | |
| | | | |
Figure 10: Registrar/Proxy Not Co-located
okay so an INVITE shows up at the authoritative proxy aimed at the AOR we stuck in Section 5.1.2 πΈ That's step (1) in Figure 10, and it looks like this:
INVITE sip:bob@example.com SIP/2.0
Via: SIP/2.0/UDP 172.16.1.4;branch=z9hG4bK74huHJ37d
Max-Forwards: 70
From: Alice <sip:alice@example.com>;tag=02935
To: Bob <sip:bob@example.com>
Call-ID: klmvCxVWGp6MxJp2T2mb
CSeq: 1 INVITE
Contact: <sip:external@172.16.1.4>
Content-Type: application/sdp
Content-Length: ..
[SDP not shown]
the INVITE matches the registration binding that got saved at the Registrar π and the Request-URI gets rewritten to the picked onward address. The Registrar also notices that a SIP 'Path' header was tied to the registration, and it shoves that into the INVITE as a pre-loaded SIP Route header π Then it forwards the request to whatever proxy is in that Route header, which is step (2) from Figure 10:
INVITE sip:bob@client.example.com SIP/2.0
Via: SIP/2.0/UDP proxy.example.com;branch=z9hG4bK74fmljnc
Via: SIP/2.0/UDP 172.16.1.4;branch=z9hG4bK74huHJ37d
Route: <sip:VskztcQ/S8p4WPbOnHbuyh5iJvJIW3ib@ep1.example.com;lr;ob>
Max-Forwards: 69
From: Alice <sip:alice@example.net>;tag=02935
To: Bob <sip:Bob@example.com>
Call-ID: klmvCxVWGp6MxJp2T2mb
CSeq: 1 INVITE
Contact: <sip:alice@172.16.1.4>
Content-Type: application/sdp
Content-Length: ..
[SDP not shown]
the request then lands at the client's outbound proxy β¨ The proxy looks at the Request-URI of the INVITE together with the flow token it put into the user part of the 'Path' header SIP URI earlier (which now sits in the user part of the Route header on the incoming INVITE). It finds the right flow and sends the message to the client, which is step (3) from Figure 10 π
INVITE sip:bob@192.168.1.2 SIP/2.0
Via: SIP/2.0/UDP ep1.example.com;branch=z9hG4nsi30dncmnl
Via: SIP/2.0/UDP proxy.example.com;branch=z9hG4bK74fmljnc
Via: SIP/2.0/UDP 172.16.1.4;branch=z9hG4bK74huHJ37d
Record-Route: <sip:VskztcQ/S8p4WPbOnHbuyh5iJvJIW3ib@ep1.example.com;lr>
Max-Forwards: 68
From: Alice <sip:Alice@example.net>;tag=02935
To: bob <sip:bob@example.com>
Call-ID: klmvCxVWGp6MxJp2T2mb
CSeq: 1 INVITE
Contact: <sip:alice@172.16.1.4>
Content-Type: application/sdp
Content-Length: ..
[SDP not shown]
this is a totally standard SIP INVITE with zero extra magic happening at the originator π The big difference is that the request does NOT follow the address in the Request-URI once it hits the outbound proxy, the way normal SIP rules would make it. Instead it gets sent down the flow tied to the registration binding, as the Route header says (the lookup procedures in RFC 3263 [RFC3263] get overridden π). That lets the original connection/ mapping from the initial registration to the outbound proxy get reused, and honestly that's iconic behavior π
5.2. Basic NAT Media Traversal π
this section gives example scenarios that show basic media traversal using the techniques we went over earlier in this document π
in the flow diagrams, STUN messages get annotated (for simplicity, obviously π) like this:
- The "Src" attribute represents the source transport address of the message.
- The "Dest" attribute represents the destination transport address of the message.
- The "Map" attribute represents the server reflexive (XOR-MAPPED-ADDRESS STUN attribute) transport address.
- The "Rel" attribute represents the relayed (RELAY-ADDRESS STUN attribute) transport address.
the meaning of each STUN attribute is explained in full detail in the core STUN [RFC5389] and TURN [RFC5766] specifications π
a bunch of ICE SDP attributes show up in some of the examples too π«§ If you want the details on any individual attribute, check the core ICE specification [RFC5245] π
the examples also use a way to represent transport addresses, because putting real network addresses in the call flows would be super confusing and hard to follow π So network addresses get written with a little annotation. The first part names the client responsible for the address. Most of the examples use "L" (left client), "R" (right client), "NAT-PUB" (NAT public), "PRIV" (Private), and "STUN-PUB" (STUN public) (this is the vibe). To handle multiple addresses from the same network element, you can add a number after the representation, and you can mix these together too β¨ For example, "L-NAT-PUB-1" is a public network address of the left-hand side NAT, while "R-NAT-PUB-1" is a public network address of the right-hand side of the NAT. "L-PRIV-1" is a private network address of the left-hand side of the NAT, and "R-PRIV-1" is a private address of the right-hand side of the NAT π
it might also be useful during the examples to point at an explicit part of a transport address π¦ You do that by adding either the '.address' or '.port' tag to the end of the representation, like 'L-PRIV-1.address' and 'L-PRIV-1.port' π
and the '$' sign marks variable parts in example SIP messages πΈ
5.2.1. Endpoint-Independent NAT π
this section shows an example of a client both starting and receiving calls behind an Endpoint-Independent NAT π There's an example for both STUN and ICE, and ICE is the RECOMMENDED mechanism for media traversal, periodt π
right now there's no reliable test to tell whether a host is behind an Endpoint-Independent Filtering NAT or an Endpoint-Independent Mapping NAT [RFC5780] π The kind of failure that happens in this situation is described in Section 5.2.2.1. Because of that, ICE is RECOMMENDED over the mechanism in this section, no cap π«Ά
5.2.1.1. STUN Solution β¨
it IS possible to traverse media through an Endpoint-Independent NAT using STUN π The rest of this section has simplified examples of the 'Binding Discovery' STUN as defined in [RFC5389]. The STUN messages have been simplified, so they leave out the 'Shared Secret' requests that get the temporary username and password π§
5.2.1.1.1. Initiating Session π¦
okay so this example shows media getting through a NAT with Endpoint-Independent Mapping properties, using the STUN 'Binding Discovery' usage π we're assuming the STUN client and SIP Client are co-located on the same physical machine, bestie π₯οΈ also some SIP signaling messages got left out to keep it simple, so don't panic if things look a little suspiciously tidy π«Ά
Client NAT STUN [..]
Server
| | | |
|(1) BIND Req | | |
|Src=L-PRIV-1 | | |
|Dest=STUN-PUB | | |
|----------------->| | |
| | | |
| |(2) BIND Req | |
| |Src=NAT-PUB-1 | |
| |Dest=STUN-PUB | |
| |----------------->| |
| | | |
| |(3) BIND Resp | |
| |<-----------------| |
| |Src=STUN-PUB | |
| |Dest=NAT-PUB-1 | |
| |Map=NAT-PUB-1 | |
| | | |
|(4) BIND Resp | | |
|<-----------------| | |
|Src=STUN-PUB | | |
|Dest=L-PRIV-1 | | |
|Map=NAT-PUB-1 | | |
| | | |
|(5) BIND Req | | |
|Src=L-PRIV-2 | | |
|Dest=STUN-PUB | | |
|----------------->| | |
| | | |
| |(6) BIND Req | |
| |Src=NAT-PUB-2 | |
| |Dest=STUN-PUB | |
| |----------------->| |
| | | |
| |(7) BIND Resp | |
| |<-----------------| |
| |Src=STUN-PUB | |
| |Dest=NAT-PUB-2 | |
| |Map=NAT-PUB-2 | |
| | | |
|(8) BIND Resp | | |
|<-----------------| | |
|Src=STUN-PUB | | |
|Dest=L-PRIV-2 | | |
|Map=NAT-PUB-2 | | |
| | | |
|(9)SIP INVITE | | |
|----------------->| | |
| | | |
| |(10)SIP INVITE | |
| |------------------------------------>|
| | | |
| | |(11)SIP 200 OK |
| |<------------------------------------|
| | | |
|(12)SIP 200 OK | | |
|<-----------------| | |
| | | |
|========================================================|
|>>>>>>>>>>>>Outgoing Media sent from L-PRIV-1>>>>>>>>>>>|
|========================================================|
| |
|========================================================|
|<<<<<<<<<<<<Incoming Media sent to NAT-PUB-1<<<<<<<<<<<<|
|========================================================|
| |
|========================================================|
|>>>>>>>>>>>>Outgoing RTCP sent from L-PRIV-2>>>>>>>>>>>>|
|========================================================|
| |
|========================================================|
|<<<<<<<<<<<<Incoming RTCP sent to NAT-PUB-2<<<<<<<<<<<<<|
|========================================================|
| | | |
|(13)SIP ACK | | |
|----------------->| | |
| | | |
| |(14) SIP ACK | |
| |------------------------------------>|
| | | |
Figure 11: Endpoint-Independent NAT - Initiating πΈ
- okay so the first step is the client spinning up a local STUN client on the interface and port that's gonna be used for media (send/receive) β¨ that STUN client makes a standard 'Binding Discovery' request, which is message (1) in Figure 11. It also shows the source address and port the client wants a mapping for π the request then goes through the NAT and out toward the public Internet and the STUN server π
- message (2) goes through the NAT and breaks out onto the public Internet, heading to the public STUN server π and this is the part where it gets iconic: the source address of the 'Binding Discovery' request is now the public address and port from the public side of the NAT π
- the STUN server gets the request and handles it properly π§ then it sends back a successful 'Binding Discovery' response (3) π that response has the XOR-mapped public address (inside the STUN XOR-MAPPED-ADDRESS attribute), which is the address the originating client will use to receive media (see 'Map=NAT-PUB-1' in (3)) π
- the 'Binding Discovery' response travels back through the NAT along the path the request already made, and hands the new XOR-mapped address to the client (4) π¦ then the whole thing gets repeated so we can grab a second XOR-mapped address (that's (5)-(8)) for a second local address, where the address changed from "L-PRIV-1" to "L-PRIV-2", and this one's for an RTCP port π«Ά
- now the client builds the SIP INVITE message (9) π traversal of SIP isn't covered in this example, bestie, so go check Section 5.1 for that π the INVITE request uses the addresses it got from the earlier STUN transactions to fill in the SDP, like this:
v=0
o=test 2890844526 2890842807 IN IP4 $L-PRIV-1.address
c=IN IP4 $NAT-PUB-1.address
t=0 0
m=audio $NAT-PUB-1.port RTP/AVP 0
a=rtcp:$NAT-PUB-2.port
- the XOR-mapped address from the 'Binding Discovery' transactions goes in as the connection address for the SDP (c=$NAT-PUB-1.address) π the primary RTP port also goes in the SDP (m=audio $NAT-PUB-1.port RTP/AVP 0) β¨ and the port from the extra 'Binding Discovery' gets put in the RTCP attribute (as covered in Section 4.2.2) so RTCP can traverse too (a=rtcp:$NAT-PUB-2.port) π§
- the SIP signaling goes through the NAT and sets up the SIP session (9-12) π₯ the left-hand client starts sending media the moment the 200 OK to the INVITE arrives (12) π until that point, incoming media and RTCP to the left-hand client won't pass through the NAT, because no outbound association has been created with the far-end client yet π and once that's all happened? two-way media communication is officially established ππ
5.2.1.1.2. Receiving Session Invitation
okay so receiving a session through an Endpoint-Independent NAT with the STUN 'Binding Discovery' usage is basically the same energy as the initiating example in Section 5.2.1.1.1 π¦β¨ Figure 12 maps out the whole message flow, so let's see it π
Client NAT STUN [..]
Server
| | | (1)SIP INVITE |
| |<------------------------------------|
| | | |
|(2) SIP INVITE | | |
|<-----------------| | |
| | | |
|(3) BIND Req | | |
|Src=L-PRIV-1 | | |
|Dest=STUN-PUB | | |
|----------------->| | |
| | | |
| |(4) BIND Req | |
| |Src=NAT-PUB-1 | |
| |Dest=STUN-PUB | |
| |----------------->| |
| | | |
| |(5) BIND Resp | |
| |<-----------------| |
| |Src=STUN-PUB | |
| |Dest=NAT-PUB-1 | |
| |Map=NAT-PUB-1 | |
| | | |
|(6) BIND Resp | | |
|<-----------------| | |
|Src=STUN-PUB | | |
|Dest=L-PRIV-1 | | |
|Map=NAT-PUB-1 | | |
| | | |
|(7) BIND Req | | |
|Src=L-PRIV-2 | | |
|Dest=STUN-PUB | | |
|----------------->| | |
| | | |
| |(8) BIND Req | |
| |Src=NAT-PUB-2 | |
| |Dest=STUN-PUB | |
| |----------------->| |
| | | |
| |(9) BIND Resp | |
| |<-----------------| |
| |Src=STUN-PUB | |
| |Dest=NAT-PUB-2 | |
| |Map=NAT-PUB-2 | |
| | | |
|(10) BIND Resp | | |
|<-----------------| | |
|Src=STUN-PUB | | |
|Dest=L-PRIV-2 | | |
|Map=NAT-PUB-2 | | |
| | | |
|(11)SIP 200 OK | | |
|----------------->| | |
| |(12)SIP 200 OK | |
| |------------------------------------>|
| | | |
|========================================================|
|>>>>>>>>>>>>Outgoing Media sent from L-PRIV-1>>>>>>>>>>>|
|========================================================|
| | | |
|========================================================|
|<<<<<<<<<<<<<Incoming Media sent to L-PRIV-1<<<<<<<<<<<<|
|========================================================|
| | | |
|========================================================|
|>>>>>>>>>>>>Outgoing RTCP sent from L-PRIV-2>>>>>>>>>>>>|
|========================================================|
| | | |
|========================================================|
|<<<<<<<<<<<<<Incoming RTCP sent to L-PRIV-2<<<<<<<<<<<<<|
|========================================================|
| | | |
| | |(13)SIP ACK |
| |<------------------------------------|
| | | |
|(14)SIP ACK | | |
|<-----------------| | |
| | | |
Figure 12: Endpoint-Independent NAT - Receiving
- okay so when the User Agent gets a SIP voice session invite (SIP INVITE request) π, it starts a local STUN client on the right port where it's going to receive media π. That client makes a standard 'Binding Discovery' request, step (3) from Figure 12, which also highlights the source address and port the client wants a mapping for π§. The request goes through the NAT towards the public Internet and STUN server πΈ.
- the 'Binding Discovery' message (4) goes through the NAT and breaks out onto the public Internet towards the public STUN server π¦. Note that the source address of the STUN requests now represents the public address and port from the public side of the NAT π.
- the STUN server gets the request and processes it appropriately π. This results in a successful 'Binding Discovery' response being generated and returned (5). The message contains details of the mapped public address (contained in the STUN XOR-MAPPED-ADDRESS attribute) that the originating client is going to use to receive media (see 'Map=NAT-PUB-1' from (5)) π«Ά.
- the 'Binding Discovery' response goes back through the NAT using the path that was created by the outgoing 'Binding Discovery' request, and presents the new XOR-mapped address to the client (6) β¨. At this point, the process is repeated to get a second XOR-mapped address (as shown in (7)-(10)) for a second local address (the local port has changed and is represented by L-PRIV-2 in (7)) for an RTCP port π.
- the client now builds a SIP 200 OK message (11) in response to the original SIP INVITE request π . Note that traversal of SIP is not covered in this example and is discussed in Section 5.1. SIP Provisional responses are also left out for simplicity π. The 200 OK response uses the addresses it got in the previous STUN transactions to fill in the SDP of the SIP 200 OK, as shown below:
v=0
o=test 2890844526 2890842807 IN IP4 $L-PRIV-1.address
c=IN IP4 $NAT-PUB-1.address
t=0 0
m=audio $NAT-PUB-1.port RTP/AVP 0
a=rtcp:$NAT-PUB-2.port
- okay this part is so satisfying π the XOR-mapped address from the initial 'Binding Discovery' transaction goes in as the connection address for the SDP (c=NAT-PUB-1.address) π. The Primary port for RTP also goes in the SDP (m=audio NAT-PUB-1.port RTP/AVP 0) π. Finally, the port from the second 'Binding Discovery' is placed in the RTCP attribute (as discussed in Section 4.2.2) for traversal of RTCP (a=rtcp:NAT-PUB-2.port) π.
- the SIP signaling then goes through the NAT and sets up the SIP session (11-14) πΈ. Note that the left-hand client transmits media as soon as the 200 OK to the INVITE is sent to the User Agent Client (UAC) (11) π₯. Up until this point, incoming media from the right-hand client won't pass through the NAT, because no outbound association has been created with the far-end client π. Two-way media communication has now been established π₯Ήβ¨
Two-way media is only live once the outbound association exists, so the far-end client's packets don't get through before that point. Iconic timing, honestly π
5.2.1.2. ICE Solution
the preferred solution for media traversal of NAT is ICE, as described in Section 4.2.3.3, regardless of the NAT type π. The examples below show traversal of an Endpoint-Independent NAT when initiating the session π¦. The example only covers ICE in association with the 'Binding Discovery' and TURN π§. It's worth noting that the TURN server provides both STUN functions (to learn your public mapping) and TURN functions (media relaying) π . It's also worth noting that in the example described in Section 5.2.1.2.1, both SIP clients L and R are contacting the same TURN server π. This is not necessary for ICE, STUN, TURN to function; all that is necessary is that the STUN and TURN server(s) be in the same addressing domain that is accessible on the Internet π.
5.2.1.2.1. Initiating Session
the following example demonstrates an initiating traversal through an Endpoint-Independent NAT using ICE π¦β¨
okay bestie, here's the full message ladder π every hop lined up so you can follow the whole dance π
L NAT STUN NAT R
Server
| | | | |
|(1) Alloc Req | | | |
|Src=L-PRIV-1 | | | |
|Dest=TURN-PUB-1 | | | |
|--------------->| | | |
| | | | |
| |(2) Alloc Req | | |
| |Src=L-NAT-PUB-1 | | |
| |Dest=TURN-PUB-1 | | |
| |--------------->| | |
| | | | |
| |(3) Alloc Resp | | |
| |<---------------| | |
| |Src=TURN-PUB-1 | | |
| |Dest=L-NAT-PUB-1| | |
| |Map=L-NAT-PUB-1 | | |
| |Rel=TURN-PUB-2 | | |
| | | | |
|(4) Alloc Resp | | | |
|<---------------| | | |
|Src=TURN-PUB-1 | | | |
|Dest=L-PRIV-1 | | | |
|Map=L-NAT-PUB-1 | | | |
|Rel=TURN-PUB-2 | | | |
| | | | |
|(5) Alloc Req | | | |
|Src=L-PRIV-2 | | | |
|Dest=TURN-PUB-1 | | | |
|--------------->| | | |
| | | | |
| |(6) Alloc Req | | |
| |Src=L-NAT-PUB-2 | | |
| |Dest=TURN-PUB-1 | | |
| |--------------->| | |
| | | | |
| |(7) Alloc Resp | | |
| |<---------------| | |
| |Src=TURN-PUB-1 | | |
| |Dest=NAT-PUB-2 | | |
| |Map=NAT-PUB-2 | | |
| |Rel=TURN-PUB-3 | | |
| | | | |
|(8) Alloc Resp | | | |
|<---------------| | | |
|Src=TURN-PUB-1 | | | |
|Dest=L-PRIV-2 | | | |
|Map=L-NAT-PUB-2 | | | |
|Rel=TURN-PUB-3 | | | |
| | | | |
|(9) SIP INVITE | | | |
|------------------------------------------------->| |
| | | | |
| | | |(10) SIP INVITE |
| | | |--------------->|
| | | | |
| | | |(11) Alloc Req |
| | | |<---------------|
| | | |Src=R-PRIV-1 |
| | | |Dest=TURN-PUB-1 |
| | | | |
| | |(12) Alloc Req | |
| | |<---------------| |
| | |Src=R-NAT-PUB-1 | |
| | |Dest=TURN-PUB-1 | |
| | | | |
| | |(13) Alloc Res | |
| | |--------------->| |
| | |Src=TURN-PUB-1 | |
| | |Dest=R-NAT-PUB-1| |
| | |Map=R-NAT-PUB-1 | |
| | |Rel=TURN-PUB-4 | |
| | | | |
| | | |(14) Alloc Res |
| | | |--------------->|
| | | |Src=TURN-PUB-1 |
| | | |Dest=R-PRIV-1 |
| | | |Map=R-NAT-PUB-1 |
| | | |Rel=TURN-PUB-4 |
| | | | |
| | | |(15) Alloc Req |
| | | |<---------------|
| | | |Src=R-PRIV-2 |
| | | |Dest=TURN-PUB-1 |
| | | | |
| | |(16) Alloc Req | |
| | |<---------------| |
| | |Src=R-NAT-PUB-2 | |
| | |Dest=TURN-PUB-1 | |
| | | | |
| | |(17) Alloc Res | |
| | |--------------->| |
| | |Src=TURN-PUB-1 | |
| | |Dest=R-NAT-PUB-2| |
| | |Map=R-NAT-PUB-2 | |
| | |Rel=TURN-PUB-5 | |
| | | | |
| | | |(18) Alloc Res |
| | | |--------------->|
| | | |Src=TURN-PUB-1 |
| | | |Dest=R-PRIV-2 |
| | | |Map=R-NAT-PUB-2 |
| | | |Rel=TURN-PUB-5 |
| | | | |
| | | |(19) SIP 200 OK |
| |<-------------------------------------------------|
| | | | |
|(20) SIP 200 OK | | | |
|<---------------| | | |
| | | | |
|(21) SIP ACK | | | |
|------------------------------------------------->| |
| | | | |
| | | |(22) SIP ACK |
| | | |--------------->|
| | | | |
|(23) Bind Req | | | |
|------------------------>x | | |
|Src=L-PRIV-1 | | | |
|Dest=R-PRIV-1 | | | |
| | | | |
|(24) Bind Req | | | |
|--------------->| | | |
|Src=L-PRIV-1 | | | |
|Dest=R-NAT-PUB-1| | | |
| | | | |
| |(25) Bind Req | | |
| |-------------------------------->| |
| |Src=L-NAT-PUB-1 | | |
| |Dest=R-NAT-PUB-1| | |
| | | | |
| | | |(26) Bind Req |
| | | |--------------->|
| | | |Src=L-NAT-PUB-1 |
| | | |Dest=R-PRIV-1 |
| | | | |
| | | |(27) Bind Res |
| | | |<---------------|
| | | |Src=R-PRIV-1 |
| | | |Dest=L-NAT-PUB-1|
| | | |Map=L-NAT-PUB-1 |
| | | | |
| | |(28) Bind Res | |
| |<--------------------------------| |
| | |Src=R-NAT-PUB-1 | |
| | |Dest=L-NAT-PUB-1| |
| | |Map=L-NAT-PUB-1 | |
| | | | |
|(29) Bind Res | | | |
|<---------------| | | |
|Src=R-NAT-PUB-1 | | | |
|Dest=L-PRIV-1 | | | |
|Map=L-NAT-PUB-1 | | | |
| | | | |
|===================================================================|
|>>>>>>>>>>>>>>>>>>Outgoing RTP sent from L-PRIV-1 >>>>>>>>>>>>>>>>>|
|===================================================================|
| | | | |
| | | |(30) Bind Req |
| | | x<-----------------------|
| | | |Src=R-PRIV-1 |
| | | |Dest=L-PRIV-1 |
| | | | |
okay so picking up right where we left off π¦ this part is all about the binding requests and responses bouncing between both sides and both NATs, with the RTP and RTCP flows marked out in the middle. Watch for the USE-CANDIDATE bits, they're the main event π
| | | | |
| | | |(31) Bind Req |
| | | |<---------------|
| | | |Src=R-PRIV-1 |
| | | |Dest=L-NAT-PUB-1|
| | | | |
| | |(32) Bind Req | |
| |<--------------------------------| |
| | |Src=R-NAT-PUB-1 | |
| | |Dest=L-NAT-PUB-1| |
| | | | |
|(33) Bind Req | | | |
|<---------------| | | |
|Src=R-NAT-PUB-1 | | | |
|Dest=L-PRIV-1 | | | |
| | | | |
|(34) Bind Res | | | |
|--------------->| | | |
|Src=L-PRIV-1 | | | |
|Dest=R-NAT-PUB-1| | | |
|Map=R-NAT-PUB-1 | | | |
| | | | |
| |(35) Bind Res | | |
| |-------------------------------->| |
| |Src=L-NAT-PUB-1 | | |
| |Dest=R-NAT-PUB-1| | |
| |Map=R-NAT-PUB-1 | | |
| | | | |
| | | |(36) Bind Res |
| | | |--------------->|
| | | |Src=L-NAT-PUB-1 |
| | | |Dest=R-PRIV-1 |
| | | |Map=R-NAT-PUB-1 |
| | | | |
|===================================================================|
|<<<<<<<<<<<<<<<<<<Outgoing RTP sent from R-PRIV-1 <<<<<<<<<<<<<<<<<|
|===================================================================|
|(37) Bind Req | | | |
|--------------->| | | |
|Src=L-PRIV-1 | | | |
|Dest=R-NAT-PUB-1| | | |
|USE-CANDIDATE | | | |
| | | | |
| |(38) Bind Req | | |
| |-------------------------------->| |
| |Src=L-NAT-PUB-1 | | |
| |Dest=R-NAT-PUB-1| | |
| |USE-CANDIDATE | | |
| | | | |
| | | |(39) Bind Req |
| | | |--------------->|
| | | |Src=L-NAT-PUB-1 |
| | | |Dest=R-PRIV-1 |
| | | |USE-CANDIDATE |
| | | | |
| | | |(40) Bind Res |
| | | |<---------------|
| | | |Src=R-PRIV-1 |
| | | |Dest=L-NAT-PUB-1|
| | | |Map=L-NAT-PUB-1 |
| | | | |
| | |(41) Bind Res | |
| |<--------------------------------| |
| | |Src=R-NAT-PUB-1 | |
| | |Dest=L-NAT-PUB-1| |
| | |Map=L-NAT-PUB-1 | |
| | | | |
|(42) Bind Res | | | |
|<---------------| | | |
|Src=R-NAT-PUB-1 | | | |
|Dest=L-PRIV-1 | | | |
|Map=L-NAT-PUB-1 | | | |
| | | | |
|(43) Bind Req | | | |
|--------------->| | | |
|Src=L-PRIV-2 | | | |
|Dest=R-NAT-PUB-2| | | |
| | | | |
| |(44) Bind Req | | |
| |-------------------------------->| |
| |Src=L-NAT-PUB-2 | | |
| |Dest=R-NAT-PUB-2| | |
| | | | |
| | | |(45) Bind Req |
| | | |--------------->|
| | | |Src=L-NAT-PUB-2 |
| | | |Dest=R-PRIV-2 |
| | | | |
| | | |(46) Bind Res |
| | | |<---------------|
| | | |Src=R-PRIV-2 |
| | | |Dest=L-NAT-PUB-2|
| | | |Map=L-NAT-PUB-2 |
| | | | |
| | |(47) Bind Res | |
| |<--------------------------------| |
| | |Src=R-NAT-PUB-2 | |
| | |Dest=L-NAT-PUB-2| |
| | |Map=L-NAT-PUB-2 | |
| | | | |
|(48) Bind Res | | | |
|<---------------| | | |
|Src=R-NAT-PUB-2 | | | |
|Dest=L-PRIV-2 | | | |
|Map=L-NAT-PUB-2 | | | |
| | | | |
|===================================================================|
|>>>>>>>>>>>>>>>>>>Outgoing RTCP sent from L-PRIV-2 >>>>>>>>>>>>>>>>|
|===================================================================|
| | | | |
| | | |(49) Bind Req |
| | | |<---------------|
| | | |Src=R-PRIV-2 |
| | | |Dest=L-NAT-PUB-2|
| | | | |
| | |(50) Bind Req | |
| |<--------------------------------| |
| | |Src=R-NAT-PUB-2 | |
| | |Dest=L-NAT-PUB-2| |
| | | | |
|(51) Bind Req | | | |
|<---------------| | | |
|Src=R-NAT-PUB-2 | | | |
|Dest=L-PRIV-2 | | | |
| | | | |
|(52) Bind Res | | | |
|--------------->| | | |
|Src=L-PRIV-2 | | | |
|Dest=R-NAT-PUB-2| | | |
|Map=R-NAT-PUB-2 | | | |
| | | | |
| |(53) Bind Res | | |
| |-------------------------------->| |
| |Src=L-NAT-PUB-2 | | |
| |Dest=R-NAT-PUB-2| | |
| |Map=R-NAT-PUB-2 | | |
| | | | |
| | | |(54) Bind Res |
| | | |--------------->|
| | | |Src=L-NAT-PUB-2 |
| | | |Dest=R-PRIV-2 |
| | | |Map=R-NAT-PUB-2 |
| | | | |
|===================================================================|
|<<<<<<<<<<<<<<<<<<Outgoing RTCP sent from R-PRIV-2<<<<<<<<<<<<<<<<<|
|===================================================================|
|(55) Bind Req | | | |
|--------------->| | | |
|Src=L-PRIV-2 | | | |
|Dest=R-NAT-PUB-2| | | |
|USE-CANDIDATE | | | |
| | | | |
| |(56) Bind Req | | |
| |-------------------------------->| |
| |Src=L-NAT-PUB-2 | | |
| |Dest=R-NAT-PUB-2| | |
| |USE-CANDIDATE | | |
| | | | |
| | | |(57) Bind Req |
| | | |--------------->|
| | | |Src=L-NAT-PUB-2 |
| | | |Dest=R-PRIV-2 |
| | | |USE-CANDIDATE |
| | | | |
| | | |(58) Bind Res |
the diagram gets cut off right at message (58), so the next part picks up from there π§π
| | | |<---------------|
| | | |Src=R-PRIV-2 |
| | | |Dest=L-NAT-PUB-2|
| | | |Map=L-NAT-PUB-2 |
| | | | |
| | |(59) Bind Res | |
| |<--------------------------------| |
| | |Src=R-NAT-PUB-2 | |
| | |Dest=L-NAT-PUB-2| |
| | |Map=L-NAT-PUB-2 | |
| | | | |
|(60) Bind Res | | | |
|<---------------| | | |
|Src=R-NAT-PUB-2 | | | |
|Dest=L-PRIV-2 | | | |
|Map=L-NAT-PUB-2 | | | |
| | | | |
| | | | |
|(61) SIP INVITE | | | |
|------------------------------------------------->| |
| | | | |
| | | |(62) SIP INVITE |
| | | |--------------->|
| | | | |
| | | |(63) SIP 200 OK |
| |<-------------------------------------------------|
| | | | |
|(64) SIP 200 OK | | | |
|<---------------| | | |
| | | | |
|(65) SIP ACK | | | |
|------------------------------------------------->| |
| | | | |
| | | |(66) SIP ACK |
| | | |--------------->|
| | | | |
Figure 13: Endpoint-Independent NAT with ICE
- okay so π when SIP client L decides it wants to start a SIP voice session, it spins up a local STUN client πβ¨. That STUN client builds a TURN Allocate request, which you can see as (1) in Figure 13. The Allocate request is the one that says "hey, this is the source address and port combo I want a mapping for" π. Then it gets sent through the NAT toward the public Internet π¦.
- the Allocate message (2) makes its way across the NAT to the public Internet and lands on the public TURN server πΈ. Super important detail: the source address on that request is now the public address and port from the public side of the NAT, which is L-NAT-PUB-1 π.
- the TURN server gets the Allocate request and handles it properly π . It sends back a successful Allocate response (3) π. That response holds the server reflexive address the originating client should use to receive media (see 'Map=L-NAT-PUB-1' from (3)) π«Ά. It also holds a suitable TURN-relayed address that can be used at the STUN server (see 'Rel=TURN-PUB-2') π§.
- the Allocate response travels back through the NAT using the binding that the first Allocate request created, and it hands the new mapped address over to the client (4) β¨. Then the whole thing gets repeated, so a second STUN-derived set of addresses shows up, as illustrated in (5)-(8) in Figure 13 π. At this point, the User Agent behind the NAT is holding pairs of derived external server reflexive and relayed representations π₯Ή. The client can also gather IP addresses and ports through other mechanisms (e.g., NAT-PMP [NAT-PMP], UPnP IGD [UPnP-IGD]) or similar π.
- now the client builds a SIP INVITE message (9) π. The INVITE request uses the addresses it grabbed during those earlier STUN/TURN exchanges to fill in the SDP of the SIP INVITE π. This should be carried out in accordance with the semantics defined in the ICE specification [RFC5245], as shown below in Figure 14 π₯:
v=0
o=test 2890844526 2890842807 IN IP4 $L-PRIV-1
c=IN IP4 $L-PRIV-1.address
t=0 0
a=ice-pwd:$LPASS
a=ice-ufrag:$LUNAME
m=audio $L-PRIV-1.port RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=rtcp:$L-PRIV-2.port
a=candidate:$L1 1 UDP 2130706431 $L-PRIV-1.address $L-PRIV-1.port
typ host
a=candidate:$L1 2 UDP 2130706430 $L-PRIV-2.address $L-PRIV-2.port
typ host
a=candidate:$L2 1 UDP 1694498815 $L-NAT-PUB-1.address $L-NAT-PUB-1.port
typ srflx raddr $L-PRIV-1.address rport $L-PRIV-1.port
a=candidate:$L2 2 UDP 1694498814 $L-NAT-PUB-2.address $L-NAT-PUB-2.port
typ srflx raddr $L-PRIV-1.address rport $L-PRIV-2.port
a=candidate:$L3 1 UDP 16777215 $STUN-PUB-2.address $STUN-PUB-2.port
typ relay raddr $L-PRIV-1.address rport $L-PRIV-1.port
a=candidate:$L3 2 UDP 16777214 $STUN-PUB-3.address $STUN-PUB-3.port
typ relay raddr $L-PRIV-1.address rport $L-PRIV-2.port
Figure 14: ICE SDP Offer
- the SDP is stuffed with every available candidate that got assembled π§. The first set of candidates (Foundation $L1) has two local addresses with the highest priority π. Those same addresses also get encoded into the connection (c=) and media (m=) lines of the SDP π. The second set, Foundation $L2, has the two server reflexive addresses from the STUN server, one for RTP and one for RTCP traffic (candidate-id $L2) π¦. The client gave this entry a lower priority than the $L1 pair π₯. The third and final set is the relayed addresses (Foundation $L3) from the STUN server π§. This pair has the lowest priority of all, and it only gets used as a last resort if both $L1 and $L2 fail π.
- the SIP signaling then goes through the NAT and sets up the SIP session (9)-(10) π¨. When a client advertises a candidate address, it should have a local STUN server running on each advertised candidate address β¨. That's so it can respond to incoming STUN connectivity checks π .
- when client R gets the SIP INVITE request (10), it also starts local STUN servers on the right address/port combos π. It gathers potential candidate addresses to encode into the SDP, just like the originating client did π«Ά. Steps (11-18) have client R doing the same things client L did π. That means it collects local, server reflexive, and relayed addresses π. Client R is now ready to build an appropriate answer in the SIP 200 OK message (19) π. The example answer shows up in Figure 15 π:
v=0
o=test 3890844516 3890842803 IN IP4 $R-PRIV-1
c=IN IP4 $R-PRIV-1.address
t=0 0
a=ice-pwd:$RPASS
m=audio $R-PRIV-1.port RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=rtcp:$R-PRIV-2.port
a=candidate:$L1 1 UDP 2130706431 $R-PRIV-1.address $R-PRIV-1.port
typ host
a=candidate:$L1 2 UDP 2130706430 $R-PRIV-2.address $R-PRIV-2.port
typ host
a=candidate:$L2 1 UDP 1694498815 $R-NAT-PUB-1.address $R-NAT-PUB-1.port
typ srflx raddr $R-PRIV-1.address rport $R-PRIV-1.port
a=candidate:$L2 2 UDP 1694498814 $R-NAT-PUB-2.address $R-NAT-PUB-2.port
typ srflx raddr $R-PRIV-1.address rport $R-PRIV-1.port
a=candidate:$L3 1 UDP 16777215 $STUN-PUB-2.address $STUN-PUB-4.port
typ relay raddr $R-PRIV-1.address rport $R-PRIV-1.port
a=candidate:$L3 2 UDP 16777214 $STUN-PUB-3.address $STUN-PUB-5.port
typ relay raddr $R-PRIV-1.address rport $R-PRIV-1.port
Figure 15: ICE SDP Answer
- both clients have now swapped SDP using offer/answer π€ and can carry on with the ICE processing π. User Agent L takes on the controlling agent role, as ICE specifies π. The clients are now required to form their Candidate check lists so they can figure out which candidates will carry the media streams π. In this example, User Agent L's Foundation 1 is paired with User Agent R's Foundation 1 π, User Agent L's Foundation 2 is paired with User Agent R's Foundation 2 π«Ά, and User Agent L's Foundation 3 is paired with User Agent R's Foundation 3 π§. At this point User Agents L and R both have a complete candidate checklist β . Both clients use the algorithm from ICE to work out candidate pair priorities and sort everything into a list of decreasing priorities π. In this example, both lists start with the host address (Foundation $L1), then the server reflexive address (Foundation $L2), and finally the relayed address (Foundation $L3) πΈ.
- every candidate pair has a state, as ICE specifies π¦. At the start, all the candidate pairs for User Agents L and R get set to the 'Frozen' state π§. The User Agents then scan the list and move the candidates to the 'Waiting' state β³. From here, both clients work their way down the list, starting with the highest candidate pair priority, and keep issuing STUN checks from the local candidate to the remote candidate of the pair π. Each time a STUN check is attempted from a local candidate, its candidate pair moves to 'In-Progress' πββοΈ.
- as shown in (23), client L builds a STUN connectivity check to validate the remote candidate address it got in the SDP of the 200 OK (20), starting with the highest priority in the checklist π΅οΈββοΈ. The active address in the SDP was a private address, so the STUN connectivity check can't reach its destination and fails π. Client L moves that candidate pair to 'Failed' π. Meanwhile, client L is also trying a STUN connectivity check for the second candidate pair in the returned SDP, the one with the second highest priority (24) π. Messages (24) to (29) show that this STUN Bind request succeeds and gives a positive result for the connectivity check π. Client L is now free to send media to the peer using that candidate pair π₯³.
- right after sending its 200 OK, client R runs the same set of binding requests too π«. First, and in parallel, it tries to contact the active address in the SDP (30), which results in failure π.
- In the meantime π a successful response to a STUN connectivity check by User Agent R (27) results in a tentative check in the reverse direction. This is illustrated by messages (31) to (36). Once this check has succeeded, User Agent R can transition the state of the appropriate candidate to 'Succeeded', and media can be sent (RTP). The earlier check in (31-36) confirms on both sides (User Agents L and R) that connectivity can be achieved using the appropriate candidate pair. User Agent L, as the controlling client, now sends another connectivity check for the candidate pair, this time including the 'USE-CANDIDATE' attribute as specified in ICE to signal the chosen candidate. This exchange is illustrated in messages (37) to (42) β¨
- As part of the process in this example, both L and R will now complete the same connectivity checks for part 2 of the component named for the favored 'Foundation' selected for use with RTCP π The connectivity checks for part 2 of the candidate component are shown in L (43-48) and R (49-54). Once this has succeeded, User Agent L as the controlling client sends another connectivity check for the candidate pair. This time the 'USE-CANDIDATE' attribute is again specified to signal the chosen candidate for component 2 π¦
- The candidates have now been fully verified (and selected), and since they are the highest priority, an updated offer (61-62) is now sent from the offerer (client L) to the answerer (client R) representing the new active candidates π The new offer would look as follows:
v=0
o=test 2890844526 2890842808 IN IP4 $L-PRIV-1
c=IN IP4 $L-NAT-PUB-1.address
t=0 0
a=ice-pwd:$LPASS
a=ice-ufrag:$LUNAME
m=audio $L-NAT-PUB-1.port RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=rtcp:$L-NAT-PUB-2.port
a=candidate:$L2 1 UDP 2203948363 $L-NAT-PUB-1.address $L-NAT-PUB-1.port
typ srflx raddr $L-PRIV-1.address rport $L-PRIV-1.port
a=candidate:$L2 2 UDP 2172635342 $L-NAT-PUB-2.address $L-NAT-PUB-2.port
typ srflx raddr $L-PRIV-1.address rport $L-PRIV-2.port
Figure 16: ICE SDP Updated Offer
- The resulting answer (63-64) for R would look as follows πΈ
v=0
o=test 3890844516 3890842804 IN IP4 $R-PRIV-1
c=IN IP4 $R-PRIV-1.address
t=0 0
a=ice-pwd:$RPASS
a=ice-ufrag:$RUNAME
m=audio $R-PRIV-1.port RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=rtcp:$R-PRIV-2.port
a=candidate:$L2 1 UDP 2984756463 $R-NAT-PUB-1.address $R-NAT-PUB-1.port
typ srflx raddr $R-PRIV-1.address rport $R-PRIV-1.port
a=candidate:$L2 2 UDP 2605968473 $R-NAT-PUB-2.address $R-NAT-PUB-2.port
typ srflx raddr $R-PRIV-1.address rport $R-PRIV-2.port
Figure 17: ICE SDP Updated Answer
5.2.2. Address/Port-Dependent NAT
5.2.2.1. STUN Failure
Okay, this part is the plot twist π It's about how STUN techniques are the preferred way to traverse a NAT, but they don't fix every case. Basic STUN on its own will not guarantee traversal through every NAT type, which is exactly why ICE is the recommended option π
Client ADDRESS/PORT-Dependent STUN [..]
NAT Server
| | | |
|(1) BIND Req | | |
|Src=L-PRIV-1 | | |
|Dest=STUN-PUB | | |
|----------------->| | |
| |(2) BIND Req | |
| |Src=NAT-PUB-1 | |
| |Dest=STUN-PUB | |
| |----------------->| |
| | | |
| |(3) BIND Resp | |
| |<-----------------| |
| |Src=STUN-PUB | |
| |Dest=NAT-PUB-1 | |
| |Map=NAT-PUB-1 | |
| | | |
|(4) BIND Resp | | |
|<-----------------| | |
|Src=STUN-PUB | | |
|Dest=L-PRIV-1 | | |
|Map=NAT-PUB-1 | | |
| | | |
|(5)SIP INVITE | | |
|------------------------------------------------------->|
| | | |
| | |(6)SIP 200 OK |
| |<------------------------------------|
| | | |
|(7)SIP 200 OK | | |
|<-----------------| | |
| | | |
|========================================================|
|>>>>>>>>>>>>>>Outgoing Media sent from L-PRIV-1>>>>>>>>>|
|========================================================|
| | | |
| x=====================================|
| xIncoming Media sent to L-PRIV-1<<<<<<|
| x=====================================|
| | | |
|(8)SIP ACK | | |
|----------------->| | |
| |(9) SIP ACK | |
| |------------------------------------>|
| | | |
Figure 18: Address/Port-Dependent NAT with STUN - Failure
The example in Figure 18 is set up for a client behind the Address/Port-Dependent NAT that is initiating a call. It should be noted that the same problem applies when a client receives a SIP invitation and is behind an Address/Port-Dependent NAT π«Ά
- In Figure 18, the client behind the NAT obtains a server reflexive representation using standard STUN mechanisms (1)-(4) that have been used in previous examples in this document (e.g., Section 5.2.1.1.1) β¨
- The external mapped address (server reflexive) obtained is also used in the outgoing SDP contained in the SIP INVITE request (5) π¦
- In this example, the client is still able to send media to the external client. The problem occurs when the client outside the NAT tries to use the reflexive address supplied in the outgoing INVITE request to traverse media back through the Address/Port-Dependent NAT π
- An Address/Port-Dependent NAT has differing rules from the Endpoint-Independent type of NAT (as defined in RFC 4787 [RFC4787]). For any internal IP address and port combination, data sent to a different external destination does not provide the same public mapping at the NAT. In Figure 18, the STUN query produced a valid external mapping for receiving media. This mapping, however, can only be used in the context of the original STUN request that was sent to the STUN server. Any packets that attempt to use the mapped address and that do not originate from the STUN server IP address and optionally port will be dropped at the NAT. Figure 18 shows the media being dropped at the NAT after (7) and before (8). This then leads to one-way audio. π
5.2.2.2. TURN Solution π¦
Remember how STUN is amazing for most NATs but totally falls apart with Address/Port-Dependent NAT (see Section 5.2.2.1)? π That's where TURN comes in, from [RFC5766]. TURN extends STUN so a client can ask for a relayed address on the TURN server instead of just a reflexive one. The catch is that this puts a media relay in the path for NAT traversal (as described in Section 4.2.3.2). Here's how TURN fixes the STUN failure with an Address/Port-Dependent NAT. Heads up, bestie: TURN works most effectively when paired with ICE. Using TURN on its own sends all media through a TURN server, and that's not efficient π
L Address/Port-Dependent TURN [..]
NAT Server
| | | |
|(1) Alloc Req | | |
|Src=L-PRIV-1 | | |
|Dest=STUN-PUB-1 | | |
|----------------->| | |
| | | |
| |(2) Alloc Req | |
| |Src=NAT-PUB-1 | |
| |Dest=STUN-PUB-1 | |
| |----------------->| |
| | | |
| |(3) Alloc Resp | |
| |<-----------------| |
| |Src=STUN-PUB-1 | |
| |Dest=NAT-PUB-1 | |
| |Map=NAT-PUB-1 | |
| |Rel=STUN-PUB-2 | |
| | | |
|(4) Alloc Resp | | |
|<-----------------| | |
|Src=STUN-PUB-1 | | |
|Dest=L-PRIV-1 | | |
|Map=NAT-PUB-1 | | |
|Rel=STUN-PUB-2 | | |
| | | |
|(5) Alloc Req | | |
|Src=L-PRIV-2 | | |
|Dest=STUN-PUB-1 | | |
|----------------->| | |
| | | |
| |(6) Alloc Req | |
| |Src=NAT-PUB-2 | |
| |Dest=STUN-PUB-1 | |
| |----------------->| |
| | | |
| |(7) Alloc Resp | |
| |<-----------------| |
| |Src=STUN-PUB-1 | |
| |Dest=NAT-PUB-2 | |
| |Map=NAT-PUB-2 | |
| |Rel=STUN-PUB-3 | |
| | | |
|(8) Alloc Resp | | |
|<-----------------| | |
|Src=STUN-PUB-1 | | |
|Dest=L-PRIV-2 | | |
|Map=NAT-PUB-2 | | |
|Rel=STUN-PUB-3 | | |
| | | |
|(9)SIP INVITE | | |
|----------------->| | |
| | | |
| |(10)SIP INVITE | |
| |------------------------------------>|
| | | |
| | |(11)SIP 200 OK |
| |<------------------------------------|
| | | |
|(12)SIP 200 OK | | |
|<-----------------| | |
| | | |
|========================================================|
|>>>>>>>>>>>>>Outgoing Media sent from L-PRIV-1>>>>>>>>>>|
|========================================================|
| | | |
| | |==================|
| | |<<<Media Sent to<<|
| | |<<<<STUN-PUB-2<<<<|
| | |==================|
| | | |
|=====================================| |
|<Incoming Media Relayed to L-PRIV-1<<| |
|=====================================| |
| | | |
| | |==================|
| | |<<<RTCP Sent to<<>|
| | |<<<<STUN-PUB-3<<<<|
| | |==================|
| | | |
|=====================================| |
|<<Incoming RTCP Relayed to L-PRIV-2<<| |
|=====================================| |
| | | |
|(13)SIP ACK | | |
|----------------->| | |
| | | |
| |(14) SIP ACK | |
| |------------------------------------>|
| | | |
Figure 19: Address/Port-Dependent NAT with TURN - Success
- In this example, client L sends a TURN allocate request (1) to get a relay address from the STUN server. The request goes through the Address/Port-Dependent NAT and reaches the STUN server (2). The STUN server sends back an Allocate response (3) containing both a server reflexive address (Map=NAT-PUB-1) for the client and a relayed address (Rel=STUN-PUB-2). The relayed address maps to a mapping on the STUN server that's tied to the public pinhole opened on the NAT by the Allocate request. So any traffic sent to the TURN relayed address (Rel=STUN-PUB-2) gets forwarded to the external representation of that pinhole (NAT-PUB-1). β¨
- The TURN-derived address (STUN-PUB-2) gets back to the originating client (4) in an Allocate response. That address can then go into the SDP for the outgoing SIP INVITE request, like this (ngl, the example also has client L grabbing a second relay address for the RTCP attribute (5-8)) π
v=0
o=test 2890844342 2890842164 IN IP4 $L-PRIV-1
c=IN IP4 $STUN-PUB-2.address
t=0 0
m=audio $STUN-PUB-2.port RTP/AVP 0
a=rtcp:$STUN-PUB-3.port
- When the INVITE request arrives, the User Agent Server (UAS) can stream media and RTCP to the relay addresses (STUN-PUB-2 and STUN-PUB-3) on the STUN server. As Figure 19 shows (between messages (12) and (13)), the media from the UAS goes to the relayed address at the STUN server. The STUN server then forwards the traffic to the open pinholes in the Address/Port-Dependent NAT (NAT-PUB-1 and NAT-PUB-2). The media can then traverse the Address/Port-Dependent NAT and arrive back at client L. π¦
- TURN on its own will work for Address/Port-Dependent and other types of NAT mentioned in this specification, but it should only be used as a last resort π Relaying media through an external entity isn't an efficient way to traverse NAT, and it comes at a high processing cost. π
5.2.2.3. ICE Solution π¦
The last two examples showed why plain core STUN falls short for every kind of NAT traversal π, and why TURN is the move for the Address/Port-Dependent NAT case π«Ά. The RECOMMENDED mechanism for traversing all varieties of NAT is ICE, detailed in Section 4.2.3.3 π. ICE uses core STUN, TURN, and any other mechanism (e.g., NAT-PMP[NAT-PMP], UPnP IGD[UPnP-IGD]) to build a list of prioritized addresses that can carry media traffic π. Detailed ICE examples are in Section 5.2.1.2.1 β¨. Those examples involve an Endpoint-Independent type NAT, but they work for any NAT type, Address/Port-Dependent included, because the ICE procedures are exactly the same πΈ.
For a list of candidate addresses, a client picks where to send media based on the results of the STUN connectivity checks and their associated priority, and the highest priority wins π. Lowkey, the fact that a NAT has Address/Port-Dependent behavior does not automatically mean the media gets relayed π. ICE actually avoids media relay, with one exception: two clients that both happen to be behind an Address/Port-Dependent NAT. The connectivity checks and the selection algorithm make traversal work in that case too π₯. Figure 20 and the description after it show how the ICE connectivity checks pull this off. This is an abbreviated example that assumes a successful SIP offer/answer exchange, and it just illustrates the connectivity check flow π§.
L Address/Port-Dependent Endpoint-Independent R
L-NAT R-NAT
|========================================================|
| SIP OFFER/ANSWER EXCHANGE |
|========================================================|
| | | |
| | |(1)Bind Req |
| | |<-----------------|
| | |Src=R=PRIV-1 |
| | |Dest=L-NAT-PUB-1 |
| | | |
| |(2)Bind Req | |
| x<-----------------| |
| |Src=R-NAT-PUB-1 | |
| |Dest=L-NAT-PUB-1 | |
| | | |
|(3)Bind Req | | |
|----------------->| | |
|Src=L-PRIV-1 | | |
|Dest=R-NAT-PUB-1 | | |
| | | |
| |(4)Bind Req | |
| |----------------->| |
| |Src=L-NAT-PUB-1 | |
| |Dest=R-NAT-PUB-1 | |
| | | |
| | |(5)Bind Req |
| | |----------------->|
| | |Src=L-NAT-PUB-1 |
| | |Dest=R-PRIV-1 |
| | | |
| | |(6)Bind Resp |
| | |<-----------------|
| | |Src=R-PRIV-1 |
| | |Dest=L-NAT-PUB-1 |
| | | |
| |(7)Bind Resp | |
| |<-----------------| |
| |Src=R-NAT-PUB-1 | |
| |Dest=L-NAT-PUB-1 | |
| | | |
|(8)Bind Resp | | |
|<-----------------| | |
|Src=R-NAT-PUB-1 | | |
|Dest=L-PRIV-1 | | |
| | | |
| | |(9)Bind Req |
| | |<-----------------|
| | |Src=R-Priv-1 |
| | |Dest=L-NAT-PUB-1 |
| |(10)Bind Req | |
| |<-----------------| |
| |Src=R-NAT-PUB-1 | |
| |Dest=L-NAT-PUB-1 | |
| | | |
|(11)Bind Req | | |
|<-----------------| | |
|Src=R-NAT-PUB-1 | | |
|Dest=L-PRIV-1 | | |
| | | |
|(12)Bind Resp | | |
|----------------->| | |
|Src=L-PRIV-1 | | |
|Dest=L-NAT-PUB-1 | | |
| | | |
| |(13)Bind Resp | |
| |----------------->| |
| |Src=L-NAT-PUB-1 | |
| |Dest=R-NAT-PUB-1 | |
| | | |
| | |(14)Bind Resp |
| | |----------------->|
| | |Src=L-NAT-PUB-1 |
| | |Dest=R-PRIV-1 |
| | | |
Figure 20: Single Address/Port-Dependent NAT - Success
Okay, the story here π: client R has already gotten a SIP INVITE and is starting its connectivity checks with client L π . Client R fires off a connectivity check (1) to the information client L gave in the SDP offer π¨. That request hits client L's Address/Port-Dependent NAT and fails to get through, because there's no NAT binding yet π. That check moves to a failed state. Meanwhile, client L has the SDP answer from the SIP request and starts its own connectivity checks too β¨. Check (3) goes out to client R, and it can traverse the NAT because of the association set up by the earlier failed check (1) π¦. The full Bind request/response is shown in steps (3)-(8). As part of a candidate pair, client R can now complete its checks, as shown in steps (9)-(14) π. The end result is a successful pair of candidates that can be used without relaying any media π.
In conclusion, media only needs to be relayed when clients are both behind Address/Port-Dependent NATs π. As the example in this section shows, neither side could complete the connectivity checks except through the Relayed candidates π.
6. IPv4-IPv6 Transition π
This section describes how IPv6-only SIP User Agents can talk to IPv4-only SIP User Agents π§. The techniques in this document mostly show examples of traversing NATs so hosts in private and public networks can communicate, but they are by no means limited to those scenarios π. The same NAT traversal techniques can also set up communication in a heterogeneous network environment, e.g., communication between an IPv4 host and an IPv6 host π«Ά.
6.1. IPv4-IPv6 Transition for SIP Signaling π
IPv4-IPv6 translation at the SIP level usually happens at dual-stack proxies that have both IPv4 and IPv6 DNS entries πΈ. These translations don't involve NATs placed in the middle of two SIP entities, so they fall outside the scope of this document π. A detailed description of this type of translation can be found in [RFC6157] β¨.
7. Security Considerations π
There are no security considerations beyond the ones inherited by reference. π
8. Acknowledgments π«Ά
The authors would like to thank the members of the IETF SIPPING WG for their comments and suggestions π. Expert review and detailed contribution, including text, was provided by Dan Wing, who was supportive throughout π.
Detailed comments were provided by Vijay Gurbani, Kaiduan Xie, Remi Denis-Courmont, Hadriel Kaplan, Phillip Matthews, Spencer Dawkins, and Hans Persson π.
9. References π
9.1. Normative References π§Ύ
okay so these are the must-read receipts that the spec leans on π
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC3261] Rosenberg, J., Schulzrinne, H., Camarillo, G.,
Johnston, A., Peterson, J., Sparks, R., Handley, M.,
and E. Schooler, "SIP: Session Initiation Protocol",
RFC 3261, June 2002.
[RFC3263] Rosenberg, J. and H. Schulzrinne, "Session Initiation
Protocol (SIP): Locating SIP Servers", RFC 3263,
June 2002.
[RFC3264] Rosenberg, J. and H. Schulzrinne, "An Offer/Answer
Model with Session Description Protocol (SDP)",
RFC 3264, June 2002.
[RFC3327] Willis, D. and B. Hoeneisen, "Session Initiation
Protocol (SIP) Extension Header Field for Registering
Non-Adjacent Contacts", RFC 3327, December 2002.
[RFC3550] Schulzrinne, H., Casner, S., Frederick, R., and V.
Jacobson, "RTP: A Transport Protocol for Real-Time
Applications", STD 64, RFC 3550, July 2003.
[RFC3581] Rosenberg, J. and H. Schulzrinne, "An Extension to the
Session Initiation Protocol (SIP) for Symmetric
Response Routing", RFC 3581, August 2003.
[RFC3605] Huitema, C., "Real Time Control Protocol (RTCP)
attribute in Session Description Protocol (SDP)",
RFC 3605, October 2003.
[RFC4566] Handley, M., Jacobson, V., and C. Perkins, "SDP:
Session Description Protocol", RFC 4566, July 2006.
[RFC4787] Audet, F. and C. Jennings, "Network Address
Translation (NAT) Behavioral Requirements for Unicast
UDP", BCP 127, RFC 4787, January 2007.
[RFC4961] Wing, D., "Symmetric RTP / RTP Control Protocol
(RTCP)", BCP 131, RFC 4961, July 2007.
[RFC5245] Rosenberg, J., "Interactive Connectivity Establishment
(ICE): A Protocol for Network Address Translator (NAT)
Traversal for Offer/Answer Protocols", RFC 5245,
April 2010.
[RFC5389] Rosenberg, J., Mahy, R., Matthews, P., and D. Wing,
"Session Traversal Utilities for NAT (STUN)",
RFC 5389, October 2008.
[RFC5626] Jennings, C., Mahy, R., and F. Audet, "Managing
Client-Initiated Connections in the Session Initiation
Protocol (SIP)", RFC 5626, October 2009.
[RFC5761] Perkins, C. and M. Westerlund, "Multiplexing RTP Data
and Control Packets on a Single Port", RFC 5761,
April 2010.
[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,
April 2010.
[RFC5923] Gurbani, V., Mahy, R., and B. Tate, "Connection Reuse
in the Session Initiation Protocol (SIP)", RFC 5923,
June 2010.
9.2. Informative References πΈ
these ones are the extra reading for when you want the full picture π¦
[MIDDLEBOXES] Stucker, B. and H. Tschofenig, "Analysis of Middlebox
Interactions for Signaling Protocol Communication
along the Media Path", Work in Progress, July 2010.
[NAT-PMP] Cheshire, S., "NAT Port Mapping Protocol (NAT-PMP)",
Work in Progress, April 2008.
[RFC2026] Bradner, S., "The Internet Standards Process --
Revision 3", BCP 9, RFC 2026, October 1996.
[RFC3424] Daigle, L. and IAB, "IAB Considerations for UNilateral
Self-Address Fixing (UNSAF) Across Network Address
Translation", RFC 3424, November 2002.
[RFC5780] MacDonald, D. and B. Lowekamp, "NAT Behavior Discovery
Using Session Traversal Utilities for NAT (STUN)",
RFC 5780, May 2010.
[RFC5853] Hautakorpi, J., Camarillo, G., Penfield, R.,
Hawrylyshen, A., and M. Bhatia, "Requirements from
Session Initiation Protocol (SIP) Session Border
Control (SBC) Deployments", RFC 5853, April 2010.
[RFC6157] Camarillo, G., El Malki, K., and V. Gurbani, "IPv6
Transition in the Session Initiation Protocol (SIP)",
RFC 6157, April 2011.
[UPnP-IGD] UPnP Forum, "Universal Plug and Play Internet Gateway
Device v1.0", 2000,
<http://www.upnp.org/specs/gw/igd1/>.
Authors' Addresses π
meet the squad who wrote this thing π«Ά
Chris Boulton
NS-Technologies
EMail: chris@ns-technologies.com
Jonathan Rosenberg
Skype
EMail: jdrosen@jdrosen.net
Gonzalo Camarillo
Ericsson
Hirsalantie 11
Jorvas 02420
Finland
EMail: Gonzalo.Camarillo@ericsson.com
Francois Audet
Skype
EMail: francois.audet@skype.net
π¦ where this page comes from
- ietf: rfc6314 2011-07
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms