RFC 8839

Session Description Protocol (SDP) Offer/Answer Procedures for Interactive Connectivity Establishment (ICE)

๐Ÿ“… published January 2021, from ietf

RFC 8839: SDP Offer/Answer Procedures for ICE ๐ŸŽ€

Okay bestie, let's talk about this one ๐Ÿ’– It's the Internet Engineering Task Force (IETF) doc that explains how Interactive Connectivity Establishment (ICE) gets handled inside Session Description Protocol (SDP) offer/answer ๐ŸŒธ Think of it as the rulebook for how two devices swap their connection options so they can finally talk to each other, no drama โœจ

Here's the title block tea โ˜•:

  • Number and title: RFC 8839, "Session Description Protocol (SDP) Offer/Answer Procedures for Interactive Connectivity Establishment (ICE)" ๐Ÿฆ‹
  • Authors: M. Petit-Huguenin (Impedance Mismatch), S. Nandakumar (Cisco Systems), C. Holmberg (Ericsson), A. Kerรคnen (Ericsson), and R. Shpount (TurboBridge) ๐Ÿ‘‘
  • Category: Standards Track, so this is the real deal, not a suggestion ๐Ÿ’…
  • Date: January 2021 ๐ŸŒˆ
  • Obsoletes: RFC 5245 and RFC 6336, so they're officially retired ๐Ÿ’€
  • Updates: nothing listed here, but the Introduction explains what's changed from RFC 5245 ๐Ÿงš

The Abstract is the elevator pitch: this doc describes SDP offer/answer procedures for carrying out ICE between the agents ๐Ÿ’œ


Status of This Memo

This is an Internet Standards Track document ๐Ÿ’– It's a product of the IETF and it represents the consensus of the IETF community. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG). For more on Internet Standards, check Section 2 of RFC 7841 ๐Ÿซถ Info about this doc's status, any errata, and how to send feedback lives at https://www.rfc-editor.org/info/rfc8839 โœจ

Copyright Notice

Copyright (c) 2021 IETF Trust and the persons identified as the document authors. All rights reserved ๐Ÿ”’

This doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as in effect on the publication date. Read those carefully, bestie, because they spell out your rights and restrictions ๐Ÿ“œ Code Components pulled from this doc must include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and come without warranty as described in that license ๐Ÿ’…

This doc may contain material from IETF Documents or IETF Contributions published or made publicly available before November 10, 2008. The people controlling copyright in some of that material may not have granted the IETF Trust permission to allow modifications outside the IETF Standards Process. Without an adequate license from them, this doc may not be modified outside the IETF Standards Process, and derivative works may not be created outside it, except to format it for publication as an RFC or to translate it into languages other than English ๐Ÿ™ˆ

Table of Contents

   1.  Introduction
   2.  Conventions
   3.  Terminology
   4.  SDP Offer/Answer Procedures
     4.1.  Introduction
     4.2.  Generic Procedures
       4.2.1.  Encoding
       4.2.2.  RTP/RTCP Considerations
       4.2.3.  Determining Role
       4.2.4.  STUN Considerations
       4.2.5.  Verifying ICE Support Procedures
       4.2.6.  SDP Example
     4.3.  Initial Offer/Answer Exchange
       4.3.1.  Sending the Initial Offer
       4.3.2.  Sending the Initial Answer
       4.3.3.  Receiving the Initial Answer
       4.3.4.  Concluding ICE
     4.4.  Subsequent Offer/Answer Exchanges
       4.4.1.  Sending Subsequent Offer
       4.4.2.  Sending Subsequent Answer
       4.4.3.  Receiving Answer for a Subsequent Offer
   5.  Grammar
     5.1.  "candidate" Attribute
     5.2.  "remote-candidates" Attribute
     5.3.  "ice-lite" and "ice-mismatch" Attributes
     5.4.  "ice-ufrag" and "ice-pwd" Attributes
     5.5.  "ice-pacing" Attribute
     5.6.  "ice-options" Attribute
   6.  Keepalives
   7.  SIP Considerations
     7.1.  Latency Guidelines
       7.1.1.  Offer in INVITE
       7.1.2.  Offer in Response
     7.2.  SIP Option Tags and Media Feature Tags
     7.3.  Interactions with Forking
     7.4.  Interactions with Preconditions
     7.5.  Interactions with Third Party Call Control
   8.  Interactions with Application Layer Gateways and SIP
   9.  Security Considerations
     9.1.  IP Address Privacy
     9.2.  Attacks on the Offer/Answer Exchanges
     9.3.  The Voice Hammer Attack
   10. IANA Considerations
     10.1.  SDP Attributes
       10.1.1.  "candidate" Attribute
       10.1.2.  "remote-candidates" Attribute
       10.1.3.  "ice-lite" Attribute
       10.1.4.  "ice-mismatch" Attribute
       10.1.5.  "ice-pwd" Attribute
       10.1.6.  "ice-ufrag" Attribute
       10.1.7.  "ice-options" Attribute
       10.1.8.  "ice-pacing" Attribute
     10.2.  Interactive Connectivity Establishment (ICE) Options
            Registry
     10.3.  Candidate Attribute Extension Subregistry Establishment
   11. Changes from RFC 5245
   12. References
     12.1.  Normative References
     12.2.  Informative References
   Appendix A.  Examples
   Appendix B.  The "remote-candidates" Attribute
   Appendix C.  Why Is the Conflict Resolution Mechanism Needed?
   Appendix D.  Why Send an Updated Offer?
   Acknowledgements
   Contributors
   Authors' Addresses

1. Introduction ๐ŸŒธ

1.1. Overview

Okay so this doc explains how ICE gets used with SDP offer/answer, which is defined in [RFC3264] ๐Ÿ’… The general ICE spec, [RFC8445], covers the procedures that every ICE usage shares, and this doc adds the extra details you need for SDP offer/answer ๐Ÿซถ

This doc obsoletes RFCs 5245 and 6336 ๐Ÿ’€

NOTE: Back in the day, both the common ICE stuff and the SDP offer/answer specifics lived in [RFC5245]. Then [RFC8445] obsoleted [RFC5245], and the SDP offer/answer details were pulled out of it. Section 11 covers what's changed in the SDP offer/answer details this doc specifies ๐Ÿงš

2. Conventions โœจ

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this doc are to be read as described in BCP 14 [RFC2119] [RFC8174], but only when they show up in ALL CAPS like this ๐Ÿ’–

3. Terminology ๐Ÿฆ‹

You should already know the terms defined in [RFC3264] and [RFC8445], plus these:

Default Destination/Candidate: The default destination for a component of a data stream is the transport address an agent that isn't ICE aware would use ๐Ÿงš A default candidate for a component is one whose transport address matches that default destination. For the RTP component, the default connection address is in the "c=" line of the SDP, and the port and transport protocol are in the "m=" line. For the RTP Control Protocol (RTCP) component, the address and port are indicated with the "rtcp" attribute defined in [RFC3605] if it's present. Otherwise, the RTCP component address is the same as the RTP component's address, and its port is one greater than the RTP component's port ๐Ÿ’œ

4. SDP Offer/Answer Procedures ๐Ÿ‘‘

4.1. Introduction ๐Ÿ’…

[RFC8445] defines ICE candidate exchange as the process where ICE agents (initiator and responder) swap the candidate info they need for ICE processing at the agents ๐ŸŒˆ For this spec, the candidate exchange process matches the Offer/Answer protocol in [RFC3264], and the terms "offerer" and "answerer" line up with the initiator and responder roles from [RFC8445] ๐Ÿซถ

Once the initiating agent has gathered, pruned, and prioritized its set of candidates [RFC8445], the candidate exchange with the peer agent kicks off โœจ

4.2. Generic Procedures ๐ŸŽ€

4.2.1. Encoding ๐Ÿ’–

Section 5 has the detailed rules for building the various SDP attributes this spec defines ๐Ÿฆ‹

4.2.1.1. Data Streams ๐ŸŒธ

Each data stream [RFC8445] is represented by an SDP media description ("m=" section) ๐Ÿ’…

4.2.1.2. Candidates ๐Ÿซถ

Inside an "m=" section, each candidate (including the default candidate) for the data stream is represented by an SDP "candidate" attribute โœจ

Before nomination, the "c=" line for an "m=" section holds the connection address of the default candidate, and the "m=" line holds the port and transport protocol of that default candidate ๐Ÿงš

After nomination, the "c=" line for a given "m=" section holds the connection address of the nominated candidate (the local candidate of the nominated candidate pair), and the "m=" line holds the port and transport protocol that match the nominated candidate for that "m=" section ๐Ÿ‘‘

4.2.1.3. Username and Password ๐Ÿ”ฅ

The ICE username is represented by an SDP "ice-ufrag" attribute, and the ICE password is represented by an SDP "ice-pwd" attribute ๐Ÿ’œ

4.2.1.4. Lite Implementations ๐ŸŒˆ

An ICE-lite implementation [RFC8445] MUST include an SDP "ice-lite" attribute. A full implementation MUST NOT include that attribute ๐Ÿ’€

4.2.1.5. ICE Extensions ๐Ÿ’–

An agent uses the SDP "ice-options" attribute to say it supports ICE extensions ๐ŸŽ€

An agent compliant with this spec MUST include an SDP "ice-options" attribute with an "ice2" attribute value [RFC8445] ๐Ÿซถ If an agent gets an SDP offer or answer that indicates ICE support but doesn't have an SDP "ice-options" attribute with an "ice2" value, the agent can assume the peer is compliant with [RFC5245] ๐Ÿ™ˆ

4.2.1.6. Inactive and Disabled Data Streams ๐Ÿฆ‹

If an "m=" section is marked as inactive [RFC4566], or has a bandwidth value of zero [RFC4566], the agent MUST still include ICE-related SDP attributes ๐ŸŒธ

If the port value for an "m=" section is set to zero (implying a disabled stream) as defined in Section 8.2 of [RFC3264], the agent SHOULD NOT include ICE-related SDP "candidate" attributes in that "m=" section, unless an SDP extension says otherwise and is used ๐Ÿงš

4.2.2. RTP/RTCP Considerations ๐ŸŒˆ

If an agent uses both RTP and RTCP, and separate ports are used for RTP and RTCP, the agent MUST include SDP "candidate" attributes for both the RTP and RTCP components ๐Ÿ’…

The agent includes an SDP "rtcp" attribute following the procedures in [RFC3605]. So when the RTCP port is one higher than the RTP port, and the RTCP component address is the same as the RTP component's address, the SDP "rtcp" attribute might get left out ๐Ÿซถ

NOTE: [RFC5245] required that an agent always include the SDP "rtcp" attribute, even when the RTCP port was one higher than the RTP port. This spec lines up the "rtcp" attribute procedures with [RFC3605] โœจ

If the agent doesn't use RTCP, it signals that by including "RS:0" and "RR:0" SDP attributes as described in [RFC3556] ๐Ÿ‘‘

4.2.3. Determining Role ๐Ÿ’–

The offerer acts as the initiating agent, and the answerer acts as the responding agent ๐ŸŽ€ The ICE roles (controlling and controlled) get figured out using the procedures in [RFC8445] ๐Ÿฆ‹

4.2.4. STUN Considerations ๐ŸŒธ

Once an agent has given its local candidates to its peer in an SDP offer or answer, the agent MUST be ready to receive STUN (Session Traversal Utilities for NAT, [RFC5389]) connectivity check Binding requests on those candidates ๐Ÿ”ฅ

Part 1 of 8 is done, bestie! ๐Ÿ’… More parts are coming, so stay tuned ๐Ÿซถ

4.2.5. Verifying ICE Support Procedures โœจ

Okay so first things first ๐Ÿ’… an ICE agent tells the other side it's ICE-pilled by including at least the SDP ice-pwd and ice-ufrag attributes in an offer or answer. And if you're compliant with this spec, you MUST also include an SDP ice-options attribute with an ice2 attribute value. No skipping!! ๐Ÿซถ

The agents will go ahead with the ICE procedures in [RFC8445] and this spec if, for each data stream in the SDP it received, the default destination for each component of that data stream shows up in a candidate attribute. For example, with RTP, the connection address, port, and transport protocol from the c= and m= lines (respectively) show up in a candidate attribute, and the value in the rtcp attribute shows up in a candidate attribute too. It's giving consistency ๐ŸŽ€

This spec doesn't give any guidance on what an agent should do when that condition isn't met, with a few exceptions:

  1. The presence of certain Application Layer Gateways might modify the transport address information, as described in Section 8. The behavior of the responding agent in that situation is implementation dependent. Informally, the responding agent might treat the mismatched transport address information as a plausible new candidate learned from the peer and keep its ICE processing going with that transport address included. Alternatively, the responding agent MAY include an ice-mismatch attribute in its answer for those data streams. If an agent chooses to include an ice-mismatch attribute in its answer for a data stream, then it MUST also omit candidate attributes, MUST terminate the usage of ICE procedures, and [RFC3264] procedures MUST be used instead for that data stream. ๐Ÿฆ‹
  2. The transport address from the peer for the default destination is set to IPv4/IPv6 address values 0.0.0.0/:: and port value of 9. This MUST NOT be considered an ICE failure by the peer agent, and the ICE processing MUST continue as usual. ๐Ÿ’€ not a failure, bestie, it's just vibes
  3. In some cases, the controlling/initiator agent may receive an SDP answer that omits candidate attributes for the data stream and instead includes a media-level ice-mismatch attribute. This tells the offerer that the answerer supports ICE, but that ICE processing wasn't used for this data stream. In this case, ICE processing MUST be terminated for this data stream, and [RFC3264] procedures MUST be followed instead. ๐ŸŒธ
  4. The transport address from the peer for the default destination is an FQDN. Regardless of the procedures used to resolve the FQDN or the resolution result, this MUST NOT be considered an ICE failure by the peer agent, and the ICE processing MUST continue as usual. ๐Ÿงš

4.2.6. SDP Example ๐Ÿ“

Here's an example SDP message that includes ICE attributes (lines folded for readability):

v=0
o=jdoe 2890844526 2890842807 IN IP4 203.0.113.141
s=
c=IN IP4 192.0.2.3
t=0 0
a=ice-options:ice2
a=ice-pacing:50
a=ice-pwd:asd88fgpdd777uzjYhagZg
a=ice-ufrag:8hhY
m=audio 45664 RTP/AVP 0
b=RS:0
b=RR:0
a=rtpmap:0 PCMU/8000
a=candidate:1 1 UDP 2130706431 203.0.113.141 8998 typ host
a=candidate:2 1 UDP 1694498815 192.0.2.3 45664 typ srflx raddr
 203.0.113.141 rport 8998

4.3. Initial Offer/Answer Exchange ๐ŸŒˆ

4.3.1. Sending the Initial Offer ๐Ÿ’Œ

When an offerer generates the initial offer, in each m= section it MUST include SDP candidate attributes for each available candidate associated with that m= section. On top of that, the offerer MUST include an SDP ice-ufrag attribute, an SDP ice-pwd attribute, and an SDP ice-options attribute with an ice2 attribute value in the offer. If the offerer is a full ICE implementation, it SHOULD include an ice-pacing attribute in the offer (if it's not included, the default value applies). A lite ICE implementation MUST NOT include the ice-pacing attribute in the offer, because it won't perform connectivity checks. ๐Ÿ™ˆ

It's valid for an offer m= line to include no SDP candidate attributes and have the default destination set to the IP address values 0.0.0.0/:: and the port value to 9. This implies that the offering agent is only going to use peer-reflexive candidates, or that it will provide additional candidates in subsequent signaling messages. โœจ

Note: Within the scope of this document, "initial offer" refers to the first SDP offer that is sent in order to negotiate usage of ICE. It might, or might not, be the initial SDP offer of the SDP session.

Note: The procedures in this document only consider m= sections associated with data streams where ICE is used.

4.3.2. Sending the Initial Answer ๐ŸŽ€

When an answerer receives an initial offer indicating that the offerer supports ICE, and the answerer accepts both the offer and the usage of ICE, the answerer MUST include in each m= section within the answer the SDP candidate attributes for each available candidate associated with that m= section. The answerer MUST also include an SDP ice-ufrag attribute, an SDP ice-pwd attribute, and an SDP ice-options attribute with an ice2 attribute value in the answer. If the answerer is a full ICE implementation, it SHOULD include an ice-pacing attribute in the answer (if it's not included, the default value applies). A lite ICE implementation MUST NOT include the ice-pacing attribute in the answer, because it won't perform connectivity checks. ๐Ÿซถ

In each m= line, the answerer MUST use the same transport protocol that was used in the offer m= line. If none of the candidates in the m= line in the answer uses the same transport protocol indicated in the offer m= line, then, to avoid ICE mismatch, the default destination MUST be set to IP address values 0.0.0.0/:: and port value of 9. ๐Ÿ‘‘

It's also valid for an answer m= line to include no SDP candidate attributes and have the default destination set to the IP address values 0.0.0.0/:: and the port value to 9. This implies that the answering agent is only going to use peer-reflexive candidates, or that additional candidates will be provided in subsequent signaling messages. ๐Ÿฆ‹

Once the answerer has sent the answer, it can start performing connectivity checks towards the peer candidates that were provided in the offer. ๐Ÿ’…

If the offer does not indicate support of ICE (Section 4.2.5), the answerer MUST NOT accept the usage of ICE. If the answerer still accepts the offer, the answerer MUST NOT include any ICE-related SDP attributes in the answer. Instead, the answerer generates the answer according to normal offer/answer procedures [RFC3264]. ๐Ÿ™…โ€โ™€๏ธ no ICE for you, offer

If the answerer detects a possibility of an ICE mismatch, the procedures described in Section 4.2.5 are followed. ๐Ÿ”

4.3.3. Receiving the Initial Answer ๐Ÿ“ฌ

When an offerer receives an initial answer that indicates the answerer supports ICE, it can start performing connectivity checks towards the peer candidates that were provided in the answer. ๐Ÿš€

If the answer does not indicate that the answerer supports ICE, or if the answerer included ice-mismatch attributes for all the active data streams in the answer, the offerer MUST terminate the usage of ICE for the entire session, and [RFC3264] procedures MUST be followed instead. ๐Ÿ˜ญ

On the other hand, if the answer indicates support for ICE but includes ice-mismatch in certain active data streams, then the offerer MUST terminate the usage of ICE procedures, and [RFC3264] procedures MUST be used instead for only those data streams. Also, ICE procedures MUST be used for data streams where an ice-mismatch attribute was not included. โš–๏ธ

If the offerer detects an ICE mismatch for one or more data streams in the answer, as described in Section 4.2.5, the offerer MUST terminate the usage of ICE for the entire session. The subsequent actions taken by the offerer are implementation dependent and are out of the scope of this specification. ๐ŸŒธ

4.3.4. Concluding ICE ๐Ÿ

Once the agent has successfully nominated a pair [RFC8445], the state of the checklist associated with that pair is set to Completed. Once the state of each checklist is set to either Completed or Failed, for each Completed checklist, the agent checks whether the nominated pair matches the default candidate pair. If there are one or more pairs that do not match, and the peer did not indicate support for the 'ice2' ice-option, the controlling agent MUST generate a subsequent offer in which the connection address, port, and transport protocol in the c= and m= lines associated with each data stream match the corresponding local information of the nominated pair for that data stream (Section 4.4.1.2.2). If the peer did indicate support for the 'ice2' ice-option, the controlling agent does not immediately need to generate an updated offer in order to align a connection address, port, and protocol with a nominated pair. However, later in the session, whenever the controlling agent does send a subsequent offer, it MUST do the alignment as described above. ๐Ÿงฉ

If there are one or more checklists with the state set to Failed, the controlling agent MUST generate a subsequent offer in order to remove the associated data streams by setting the port value of those data streams to zero (Section 4.4.1.1.2), even if the peer did indicate support for the 'ice2' ice-option. If needed, that offer is used to align the connection address, port, and transport protocol, as described above. ๐Ÿฅ€

As described in [RFC8445], once the controlling agent has nominated a candidate pair for a checklist, the agent MUST NOT nominate another pair for that checklist during the lifetime of the ICE session (i.e., until ICE is restarted). ๐Ÿ”’ one pair per checklist, periodt

[RFC8863] provides a mechanism for allowing the ICE process to run long enough to find working candidate pairs, by waiting for potential peer-reflexive candidates, even though no candidate pairs were received from the peer or all current candidate pairs associated with a checklist have either failed or been discarded. โณ

4.4. Subsequent Offer/Answer Exchanges ๐Ÿ”

Either agent MAY generate a subsequent offer at any time allowed by [RFC3264]. This section defines the rules for constructing subsequent offers and answers. ๐Ÿง

Should a subsequent offer fail, ICE processing continues as if the subsequent offer had never been made. ๐Ÿ™ƒ

4.4.1. Sending Subsequent Offer ๐Ÿ’ซ

4.4.1.1. Procedures for All Implementations ๐ŸŒŸ

4.4.1.1.1. ICE Restart ๐Ÿ”„โœจ

An agent MAY restart ICE processing for an existing data stream [RFC8445]. It's totally optional, but when it happens it's a whole glow-up ๐Ÿ’…

Here's the tea: the restart rules mean that setting the connection address in the c= line to 0.0.0.0 (for IPv4) or :: (for IPv6) will also cause an ICE restart ๐Ÿ™ˆ So ICE implementations MUST NOT use that for call hold ๐Ÿšซ. Instead, they MUST use inactive and sendonly as described in [RFC3264] ๐Ÿ’œ

To restart ICE, an agent MUST change both the ice-pwd and the ice-ufrag for the data stream in an offer. It's allowed to use a session-level attribute in one offer and then give the same ice-pwd or ice-ufrag as a media-level attribute in a later offer. This MUST NOT be considered as ICE restart ๐ŸŽ€

The agent sets the rest of the ICE-related fields in the SDP for this data stream the same way it would in an initial offer of this data stream (Section 4.2.1). So the set of candidates MAY include some, none, or all of the previous candidates for that data stream, and MAY include a totally new set of candidates ๐Ÿฆ‹ The agent MAY modify the attribute values of the SDP ice-options and SDP ice-pacing attributes, and it MAY change its role using the SDP ice-lite attribute. But the agent MUST NOT modify the SDP ice-options, ice-pacing, and ice-lite attributes in a subsequent offer unless that offer is sent in order to request an ICE restart ๐Ÿซถ

4.4.1.1.2. Removing a Data Stream ๐Ÿ™…โ€โ™€๏ธ

If an agent removes a data stream by setting its port to zero, it MUST NOT include any candidate attributes for that data stream, and it SHOULD NOT include any other ICE-related attributes defined in Section 5 for that data stream ๐Ÿ’€

4.4.1.1.3. Adding a Data Stream ๐ŸŒฑ

If an agent wants to add a new data stream, it sets the fields in the SDP for this data stream as if this were an initial offer for that data stream (Section 4.2.1). This kicks off ICE processing for this data stream โญ

4.4.1.2. Procedures for Full Implementations ๐Ÿ‘‘

This section describes additional procedures for full implementations, covering existing data streams ๐ŸŒธ

4.4.1.2.1. Before Nomination ๐Ÿงš

When an offerer sends a subsequent offer, in each m= section for which a candidate pair has not yet been nominated, the offer MUST include the same set of ICE-related information that the offerer included in the previous offer or answer. The agent MAY include additional candidates it did not offer previously, but which it has gathered since the last offer/answer exchange, including peer-reflexive candidates โœจ

The agent MAY change the default destination for media. As with initial offers, there MUST be a set of candidate attributes in the offer matching this default destination ๐Ÿ“

4.4.1.2.2. After Nomination ๐Ÿ”’

Once a candidate pair has been nominated for a data stream, the connection address, port, and transport protocol in each c= and m= line associated with that data stream MUST match the data associated with the nominated pair for that data stream. On top of that, the offerer only includes SDP candidate attributes (one per component) representing the local candidates of the nominated candidate pair. The offerer MUST NOT include any other SDP candidate attributes in the subsequent offer ๐Ÿ’…

Also, if the agent is controlling, it MUST include the remote-candidates attribute for each data stream whose checklist is in the Completed state. The attribute contains the remote candidates corresponding to the nominated pair in the valid list for each component of that data stream. It's needed to avoid a race condition ๐Ÿ˜ญ where the controlling agent chooses its pairs, but the updated offer beats the connectivity checks to the controlled agent, which doesn't even know these pairs are valid, let alone selected. See Appendix B for elaboration on this race condition ๐Ÿ”ฅ

4.4.1.3. Procedures for Lite Implementations ๐ŸŒˆ

If the ICE state is Running, a lite implementation MUST include all of its candidates for each component of each data stream in candidate attributes in any subsequent offer. The candidates are formed exactly the same way as the procedures for initial offers ๐Ÿฆ‹

A lite implementation MUST NOT add additional host candidates in a subsequent offer, and MUST NOT modify the username fragments and passwords. If an agent needs to offer additional candidates, or to modify the username fragments and passwords, it MUST request an ICE restart (Section 4.4.1.1.1) for that data stream ๐Ÿ™ˆ

If ICE has completed for a data stream, and the agent is controlled, the default destination for that data stream MUST be set to the remote candidate of the candidate pair for that component in the valid list. For a lite implementation, there is always just a single candidate pair in the valid list for each component of a data stream. Additionally, the agent MUST include a candidate attribute for each default destination ๐Ÿ’œ

If the ICE state is Completed, and the agent is controlling (which only happens when both agents are lite), the agent MUST include the remote-candidates attribute for each data stream. The attribute contains the remote candidates from the candidate pairs in the valid list (one pair for each component of each data stream) ๐ŸŒธ

4.4.2. Sending Subsequent Answer ๐Ÿ’Œ

If ICE is Completed for a data stream, and the offer for that data stream lacked the remote-candidates attribute, the rules for constructing the answer are identical to those for the offerer, except that the answerer MUST NOT include the remote-candidates attribute in the answer ๐ŸŽ€

A controlled agent receives an offer with the remote-candidates attribute for a data stream when its peer has concluded ICE processing for that data stream. This attribute is in the offer to deal with a race condition between the receipt of the offer and the receipt of the Binding response that tells the answerer which candidate will be selected by ICE. See Appendix B for an explanation of this race condition. So, processing an offer with this attribute depends on who wins the race ๐Ÿ‘‘

The agent forms a candidate pair for each component of the data stream by:

  • Setting the remote candidate equal to the offerer's default destination for that component (i.e., the contents of the m= and c= lines for RTP, and the rtcp attribute for RTCP)
  • Setting the local candidate equal to the transport address for that same component in the remote-candidates attribute in the offer.

The agent then checks whether each of these candidate pairs is present in the valid list. If a particular pair is not in the valid list, the check has "lost" the race. Call such a pair a "losing pair" ๐Ÿ˜ฌ

The agent finds all the pairs in the checklist whose remote candidates equal the remote candidate in the losing pair:

  • If none of the pairs is In-Progress, and at least one is Failed, it is most likely that a network failure, such as a network partition or serious packet loss, has occurred. The agent SHOULD generate an answer for this data stream as if the remote-candidates attribute had not been present, and then restart ICE for this stream ๐Ÿฅบ
  • If at least one of the pairs is In-Progress, the agent SHOULD wait for those checks to complete, and as each one completes, redo the processing in this section until there are no losing pairs โณ

Once there are no losing pairs, the agent can generate the answer. It MUST set the default destination for media to the candidates in the remote-candidates attribute from the offer (each of which will now be the local candidate of a candidate pair in the valid list). It MUST include a candidate attribute in the answer for each candidate in the remote-candidates attribute in the offer ๐Ÿซถ

4.4.2.1. ICE Restart ๐Ÿ”„

If the offerer in a subsequent offer requested an ICE restart (Section 4.4.1.1.1) for a data stream, and the answerer accepts the offer, the answerer follows the procedures for generating an initial answer ๐ŸŒฑ

For a given data stream, the answerer MAY include the same candidates that were used in the previous ICE session, but it MUST change the SDP ice-pwd and ice-ufrag attribute values ๐Ÿฆ‹

The answerer MAY modify the attribute values of the SDP ice-options and SDP ice-pacing attributes, and it MAY change its role using the SDP ice-lite attribute. The answerer MUST NOT modify the SDP ice-options, ice-pacing, and ice-lite attributes in a subsequent answer unless the answer is sent for an offer that was used to request an ICE restart (Section 4.4.1.1.1). If any of the SDP attributes have been modified in a subsequent offer that is not used to request an ICE restart, the answerer MUST reject the offer ๐Ÿšซ

4.4.2.2. Lite Implementation Specific Procedures ๐ŸŒท

If the received offer contains the remote-candidates attribute for a data stream, the agent forms a candidate pair for each component of the data stream by:

  • Setting the remote candidate equal to the offerer's default destination for that component (i.e., the contents of the m= and c= lines for RTP, and the rtcp attribute for RTCP).
  • Setting the local candidate equal to the transport address for that same component in the remote-candidates attribute in the offer.

The state of the checklist associated with that data stream is set to Completed โœ…

Furthermore, if the agent believed it was controlling, but the offer contained the remote-candidates attribute, both agents believe they are controlling. In this case, both would have sent updated offers around the same time ๐Ÿ˜ตโ€๐Ÿ’ซ

However, the signaling protocol carrying the offer/answer exchanges will have resolved this glare condition, so that one agent is always the 'winner' by having its offer received before its peer has sent an offer. The winner takes the role of controlling, so the loser (the answerer under consideration in this section) MUST change its role to controlled ๐Ÿฅ€

Consequently, if the agent was controlling based on the rules in Section 8.2 of [RFC8445] and was going to send an updated offer, it no longer needs to ๐Ÿ™Œ

Besides the potential role change, change in the valid list, and state changes, the construction of the answer is performed identically to the construction of an offer ๐ŸŽ€

4.4.3. Receiving Answer for a Subsequent Offer ๐Ÿ“ฌ

4.4.3.1. Procedures for Full Implementations โœจ

okay so there are times when the offerer gets an SDP answer that has NO ICE candidates in it, even though the first answer totally had them ๐Ÿ˜ญ. one "unexpected" answer like that can happen when an ICE-unaware Back-to-Back User Agent (B2BUA) pops in a media server during call hold, using third party call control procedures [RFC3725]. (skipping the messy details on how that works ๐Ÿ™ˆ) the result is that an answer the B2BUA built lands at the holding UA, and since the B2BUA doesn't know about ICE, that answer has no ICE candidates. ๐Ÿ’…

getting an answer with no ICE attributes here might feel unexpected, but it doesn't necessarily wreck the user experience. ๐Ÿซถ

when the offerer gets an answer that shows ICE support, it does one of the following things ๐Ÿ”ฅ:

  • If the offer was a restart, the agent MUST perform ICE restart procedures as specified in Section 4.4.3.1.1. ๐Ÿ”„
  • If the offer/answer exchange removed a data stream, or an answer rejected an offered data stream, an agent MUST flush the valid list for that data stream. It MUST also terminate any STUN transactions in progress for that data stream. ๐Ÿ›‘
  • If the offer/answer exchange added a new data stream, the agent MUST create a new checklist for it (and an empty valid list to start of course), which in turn triggers the candidate processing procedures [RFC8445]. ๐ŸŒฑ
  • If the checklist state associated with a data stream is Running, the agent recomputes the checklist. If a pair on the new checklist was also on the previous checklist, its candidate pair state is copied over. Otherwise, its candidate pair state is set to Frozen. If none of the checklists are active (meaning that the candidate pair states in each checklist are Frozen), appropriate procedures in [RFC8445] are performed to move candidate pair(s) to the Waiting state to further continue ICE processing. ๐Ÿงฉ
  • If the ICE state is Completed, and the SDP answer conforms to Section 4.4.2, the agent MUST remain in the Completed ICE state. ๐Ÿ‘‘

However, if the ICE support is no longer indicated in the SDP answer, the agent MUST fall back to [RFC3264] procedures and SHOULD NOT drop the dialog because of the missing ICE support or unexpected answer. When the agent sends a new offer, it MUST perform an ICE restart. ๐Ÿ™

4.4.3.1.1. ICE Restarts ๐Ÿ”

the agent MUST remember the nominated pair in the valid list for each component of the data stream, called the "previous selected pair", prior to the restart. ๐Ÿ’œ the agent will keep sending media using this pair, as described in Section 12 of [RFC8445]. once these destinations are noted, the agent MUST flush the valid lists and checklists, and then recompute the checklist and its states, thus triggering the candidate processing procedures [RFC8445]. main character restart energy ๐Ÿฆ‹

4.4.3.2. Procedures for Lite Implementations ๐ŸŒท

if ICE is restarting for a data stream, the agent MUST create a new valid list for that data stream. It MUST remember the nominated pair in the previous valid list for each component of the data stream, called the "previous selected pairs", and continue to send media there as described in Section 12 of [RFC8445]. The state of each checklist for each data stream MUST change to Running, and the ICE state MUST be set to Running. ๐ŸŒˆ


5. Grammar ๐Ÿ“œ

this specification defines eight new SDP attributes: the "candidate", "remote-candidates", "ice-lite", "ice-mismatch", "ice-ufrag", "ice-pwd", "ice-pacing", and "ice-options" attributes. ๐ŸŽ€

this section also gives you non-normative examples of the attributes defined. ๐Ÿ’–

the syntax for the attributes follows Augmented BNF as defined in [RFC5234]. โœจ

5.1. "candidate" Attribute ๐Ÿ’ซ

the "candidate" attribute is a media-level attribute only. It contains a transport address for a candidate that can be used for connectivity checks. ๐Ÿ”

   candidate-attribute   = "candidate" ":" foundation SP component-id SP
                           transport SP
                           priority SP
                           connection-address SP     ;from RFC 4566
                           port         ;port from RFC 4566
                           SP cand-type
                           [SP rel-addr]
                           [SP rel-port]
                           *(SP cand-extension)

   foundation            = 1*32ice-char
   component-id          = 1*3DIGIT
   transport             = "UDP" / transport-extension
   transport-extension   = token              ; from RFC 3261
   priority              = 1*10DIGIT
   cand-type             = "typ" SP candidate-types
   candidate-types       = "host" / "srflx" / "prflx" / "relay" / token
   rel-addr              = "raddr" SP connection-address
   rel-port              = "rport" SP port
   cand-extension        = extension-att-name SP extension-att-value
   extension-att-name    = token
   extension-att-value   = *VCHAR
   ice-char              = ALPHA / DIGIT / "+" / "/"

this grammar holds the main info about a candidate: its IP address, port, and transport protocol, plus its properties: the foundation, component ID, priority, type, and related transport address. ๐Ÿง

  • <connection-address>: is taken from RFC 4566 [RFC4566]. It is the IP address of the candidate, allowing for IPv4 addresses, IPv6 addresses, and fully qualified domain names (FQDNs). When parsing this field, an agent can tell an IPv4 address from an IPv6 address by checking for a colon in its value, since the presence of a colon indicates IPv6. An agent generating local candidates MUST NOT use FQDN addresses. An agent processing remote candidates MUST ignore "candidate" lines that include candidates with FQDNs or IP address versions that are not supported or recognized. The procedures for generation and handling of FQDN candidates, as well as how agents indicate support for such procedures, need to be specified in an extension specification. ๐ŸŒ
  • <port>: is also taken from RFC 4566 [RFC4566]. It is the port of the candidate. ๐Ÿšช
  • <transport>: indicates the transport protocol for the candidate. This specification only defines UDP. However, extensibility is provided to allow for future transport protocols to be used with ICE, by extending the subregistry "ICE Transport Protocols" under the "Interactive Connectivity Establishment (ICE)" registry. ๐Ÿšš
  • <foundation>: is composed of 1 to 32 <ice-char>s. It is an identifier that is equivalent for two candidates that are of the same type, share the same base, and come from the same STUN server. The foundation is used to optimize ICE performance in the Frozen algorithm as described in [RFC8445]. ๐Ÿง 
  • <component-id>: is a positive integer between 1 and 256 (inclusive) that identifies the specific component of the data stream for which this is a candidate. It MUST start at 1 and MUST increment by 1 for each component of a particular candidate. For data streams based on RTP, candidates for the actual RTP media MUST have a component ID of 1, and candidates for RTCP MUST have a component ID of 2. See Section 13 of [RFC8445] for additional discussion on extending ICE to new data streams. ๐Ÿ”ข
  • <priority>: is a positive integer between 1 and (2**31 - 1) inclusive. The procedures for computing a candidate's priority are described in Section 5.1.2 of [RFC8445]. ๐Ÿ†
  • <cand-type>: encodes the type of candidate. This specification defines the values "host", "srflx", "prflx", and "relay" for host, server-reflexive, peer-reflexive, and relayed candidates, respectively. Specifications for new candidate types MUST define how, if at all, various steps in the ICE processing differ from the ones defined by this specification. ๐Ÿท๏ธ
  • <rel-addr> and <rel-port>: convey transport addresses related to the candidate, useful for diagnostics and other purposes. <rel-addr> and <rel-port> MUST be present for server-reflexive, peer-reflexive, and relayed candidates. If a candidate is server-reflexive or peer-reflexive, <rel-addr> and <rel-port> are equal to the base for that server-reflexive or peer-reflexive candidate. If the candidate is relayed, <rel-addr> and <rel-port> are equal to the mapped address in the Allocate response that provided the client with that relayed candidate (see Section 6.3 of [RFC5766]). If the candidate is a host candidate, <rel-addr> and <rel-port> MUST be omitted. ๐Ÿ”—

In some cases, e.g., for privacy reasons, an agent may not want to reveal the related address and port. In this case the address MUST be set to "0.0.0.0" (for IPv4 candidates) or "::" (for IPv6 candidates) and the port to "9". ๐Ÿ™ˆ

the "candidate" attribute can itself be extended. The grammar allows for new name/value pairs to be added at the end of the attribute. Such extensions MUST be made through IETF Review or IESG Approval [RFC8126], and the assignments MUST contain the specific extension and a reference to the document defining the usage of the extension. ๐Ÿงฉ

an implementation MUST ignore any name/value pairs it doesn't understand. ๐Ÿซ 

here's an example SDP line for a UDP server-reflexive "candidate" attribute for the RTP component ๐ŸŽ€:

a=candidate:2 1 UDP 1694498815 192.0.2.3 45664 typ srflx raddr 203.0.113.141 rport 8998

5.2. "remote-candidates" Attribute ๐ŸŒธ

the syntax of the "remote-candidates" attribute is defined using Augmented BNF as defined in [RFC5234]. The "remote-candidates" attribute is a media-level attribute only. ๐Ÿ“

   remote-candidate-att = "remote-candidates:" remote-candidate
                            0*(SP remote-candidate)
   remote-candidate = component-id SP connection-address SP port

the attribute contains a connection-address and port for each component. The ordering of components is irrelevant. However, a value MUST be present for each component of a data stream. This attribute MUST be included in an offer by a controlling agent for a data stream that is Completed, and MUST NOT be included in any other case. ๐ŸŽฏ

here are some examples of "remote-candidates" SDP lines for the RTP and RTCP components ๐Ÿฆ‹:

a=remote-candidates:1 192.0.2.3 45664
a=remote-candidates:2 192.0.2.3 45665

5.3. "ice-lite" and "ice-mismatch" Attributes ๐ŸŒŸ

the syntax of the "ice-lite" and "ice-mismatch" attributes, both of which are flags, is:

   ice-lite               = "ice-lite"
   ice-mismatch           = "ice-mismatch"

"ice-lite" is a session-level attribute only, and indicates that an agent is a lite implementation. "ice-mismatch" is a media-level attribute and is only reported in the answer. It indicates that the offer arrived with a default destination for a media component that didn't have a corresponding "candidate" attribute. Including the "ice-mismatch" attribute for a given data stream implies that even though both agents support ICE, ICE procedures MUST NOT be used for this data stream, and [RFC3264] procedures MUST be used instead. ๐Ÿšจ

5.4. "ice-ufrag" and "ice-pwd" Attributes ๐Ÿ”

okay bestie, these two attributes carry the username fragment and password that ICE uses for message integrity, so they're basically the bouncers of the whole operation ๐Ÿ’… Here's their grammar:

ice-pwd-att           = "ice-pwd:" password
ice-ufrag-att         = "ice-ufrag:" ufrag
password              = 22*256ice-char
ufrag                 = 4*256ice-char

So ice-pwd and ice-ufrag can show up at either the session-level or the media-level ๐ŸŽ€ If both have them, the media-level value wins โœจ Think of the session-level one as a default that covers every data stream, unless a media-level one overrides it ๐Ÿ’– Either way, there MUST be an "ice-pwd" and an "ice-ufrag" attribute for each data stream ๐Ÿซถ And if two data streams share the same "ice-ufrag", they MUST have the same "ice-pwd" too, no exceptions ๐Ÿ˜ญ

These values MUST be chosen randomly at the very beginning of a session. The same goes when ICE is restarting for an agent ๐ŸŽฒ

[RFC8445] wants the "ice-ufrag" to hold at least 24 bits of randomness, and the "ice-pwd" to hold at least 128 bits of randomness ๐ŸŒˆ Because the grammar packs 6 bits of information into each character, that works out to "ice-ufrag" being at least 4 characters long, and "ice-pwd" being at least 22 characters long ๐Ÿงฎ You're allowed to go longer than 4 and 22 characters, MAY do it, all the way up to 256 characters ๐Ÿฆ‹ That upper limit exists so implementations can size their buffers, and the big ceiling leaves room to add more randomness over time ๐ŸŒธ

Now here's the spicy part. The STUN username attribute value tops out at 512 characters, and bandwidth matters too, so the "ice-ufrag" MUST NOT be longer than 32 characters when you're sending it ๐Ÿ“ But when you're receiving, an implementation MUST accept up to 256 characters ๐Ÿ‘‘ Be generous when you listen, careful when you talk ๐Ÿ’œ

Here's a sample of what these SDP lines look like ๐Ÿ“

a=ice-pwd:asd88fgpdd777uzjYhagZg
a=ice-ufrag:8hhY

5.5. "ice-pacing" Attribute โฑ๏ธ

The "ice-pacing" attribute is session-level, and it says how fast the sender wants its connectivity checks to go, measured as the Ta interval in milliseconds โœจ If you want the scoop on picking a pacing value, check out Section 14.2 of [RFC8445] ๐Ÿ“– Here's the grammar:

ice-pacing-att            = "ice-pacing:" pacing-value
pacing-value              = 1*10DIGIT

If the attribute isn't in an offer or an answer, it defaults to 50 ms, which is the recommended value in [RFC8445] ๐Ÿซง

Now, no matter what Ta value each agent picks, [RFC8445] says all the transactions from all agents combined (in case one implementation runs several agents at once) won't be sent more often than once every 5 ms ๐Ÿšฆ And once both agents have shared the pacing value they want, they both go with the larger of the two numbers ๐Ÿ† Iconic cooperation ๐Ÿซถ

Here's an "ice-pacing" line with a value of '50' ๐Ÿ’–

a=ice-pacing:50

5.6. "ice-options" Attribute ๐Ÿงฉ

The "ice-options" attribute works at both session-level and media-level ๐ŸŒˆ It's a list of tokens naming the options the agent supports ๐Ÿ“ The grammar goes like this:

ice-options           = "ice-options:" ice-option-tag
                          *(SP ice-option-tag)
ice-option-tag        = 1*ice-char

So if an offer has "ice-options", that means the agent supports a certain extension and is totally down to use it, as long as the peer agent also includes the same extension in its answer โœจ Sometimes the agents need extra extension-specific negotiation to figure out how that extension actually gets used in the session ๐Ÿค The details of those negotiation procedures, if there are any, MUST be defined by the specification that defines the extension (Section 10.2) ๐Ÿ“œ

Here's an "ice-options" line with 'ice2' and 'rtp+ecn' [RFC6679] in it ๐Ÿฆ‹

a=ice-options:ice2 rtp+ecn

6. Keepalives ๐Ÿ’“

All the ICE agents MUST follow the procedures in Section 11 of [RFC8445] for sending keepalives ๐Ÿซถ As [RFC8445] explains, keepalives get sent no matter whether the data stream is inactive, sendonly, recvonly, or sendrecv, and no matter whether there's a bandwidth attribute or what its value is ๐ŸŒธ And here's a bonus clue: an agent can tell its peer supports ICE by seeing "candidate" attributes for each media session ๐Ÿ•ต๏ธโ€โ™€๏ธ

7. SIP Considerations ๐Ÿ“ž

Quick heads-up: ICE is NOT meant for NAT traversal of SIP signaling. Nope, that's assumed to be handled by another mechanism [RFC5626] ๐Ÿ™…โ€โ™€๏ธ

When ICE is used with SIP, forking can turn one offer into a bunch of answers ๐ŸŒฟ In that case, ICE runs completely in parallel and independently for each answer ๐Ÿซง It treats the combo of the offer plus each answer as its own independent offer/answer exchange, with its own local candidates, pairs, checklists, states, and so on ๐ŸŽ€

7.1. Latency Guidelines โณ

ICE needs a series of STUN-based connectivity checks to happen between endpoints โœจ These checks kick off at the answerer once it generates its answer, and at the offerer once it receives the answer ๐Ÿ’œ They can take a while, so the messages you pick for offers and answers can change how laggy things feel to the user ๐Ÿ˜ญ Two latency numbers really matter here. The first is the post-pickup delay, which is the time between when a user "answers the phone" and when whatever they say can actually reach the caller ๐ŸŽง The second is the post-dial delay, which is the time between when a user types in the destination address and ringback starts because the called user agent has successfully started alerting ๐Ÿ“ž

There are two cases to think about: one where the offer is in the initial INVITE, and one where it shows up in a response ๐ŸŒˆ

7.1.1. Offer in INVITE ๐Ÿ’Œ

To cut down on post-dial delays, it is RECOMMENDED that the caller start gathering candidates before it actually sends its initial INVITE, so the candidates can ride along in the INVITE ๐Ÿš€ The caller can kick this off on user interface cues that a call is pending, like keypad activity or the phone going off-hook ๐Ÿ“ฑ

When the offer comes in, the answerer SHOULD generate an answer in a provisional response as soon as it finishes gathering candidates ๐Ÿซถ ICE requires that a provisional response with an SDP be sent reliably. You can do that with the existing Provisional Response Acknowledgment (PRACK) mechanism from [RFC3262], or with an ICE-specific optimization where the agent retransmits the provisional response using the exponential backoff timers described in [RFC3262] ๐Ÿ” Those retransmissions MUST stop once a STUN Binding request arrives with a transport address matching the candidate address for one of the data streams signaled in that SDP, or once the answer goes out in a 2xx response ๐Ÿ›‘ If no Binding request shows up before the last retransmit, the agent does NOT treat the session as terminated ๐Ÿ™ˆ And for ICE-lite peers, the agent MUST stop retransmitting the 18x response after sending it four times, since no Binding request is going to come, and the number four was picked arbitrarily to keep the 18x retransmits in check ๐Ÿงš

Once the answer has been sent, the agent SHOULD start its connectivity checks ๐Ÿƒโ€โ™€๏ธ Once candidate pairs for each component of a data stream land in the valid list, the answerer can start sending media on that data stream ๐ŸŽถ

Hold up though: before that point, any media that needs to go back toward the caller (like SIP early media [RFC3960]) MUST NOT be transmitted ๐Ÿšซ That's why implementations SHOULD hold off on alerting the called party until candidates for each component of each data stream have entered the valid list ๐Ÿ’… For a PSTN gateway, that means the setup message into the PSTN gets delayed until that point ๐Ÿ“ก It bumps up the post-dial delay, but it totally eliminates 'ghost rings' ๐Ÿ‘ป A ghost ring is when the called party hears the phone ring, picks up, hears nothing, and can't be heard either ๐Ÿ˜ญ This trick works without needing support for or use of preconditions [RFC3312] ๐Ÿ™Œ It also guarantees that not a single packet of media gets clipped, so the post-pickup delay is zero โœจ And if an agent decides to delay local alerting like this, it SHOULD generate a 180 response once alerting begins ๐Ÿ””

7.1.2. Offer in Response ๐ŸŽ

Besides cases where the offer is in an INVITE and the answer comes in the provisional and/or 200 OK response, ICE also works when the offer shows up in a response ๐Ÿ’ซ These setups are common in third party call control [RFC3725] ๐Ÿ“ž In those cases, ICE agents SHOULD generate their offers in a reliable provisional response (which MUST utilize [RFC3262]), and they shouldn't alert the user when the INVITE arrives ๐Ÿ™Š The answer will come back in a PRACK ๐Ÿซง This lets ICE processing finish before alerting, so there's no post-pickup delay, but call setup takes longer as a tradeoff ๐Ÿข Once ICE completes, the callee can alert the user, and then generate a 200 OK when they answer ๐ŸŽ€ That 200 OK contains no SDP, since the offer/answer exchange is already done ๐ŸŒท

Or, agents MAY put the offer in a 2xx instead, and then the answer arrives in the ACK ๐Ÿฆ‹ When that happens, the callee alerts the user as soon as the INVITE lands, and the ICE exchanges only happen after the user answers ๐Ÿ“ฒ That cuts down call-setup delay, but it can cause big post-pickup delays and media clipping ๐Ÿ˜ฌ

7.2. SIP Option Tags and Media Feature Tags ๐Ÿท๏ธ

[RFC5768] defines a SIP option tag and a media feature tag for use with ICE ๐ŸŒธ ICE implementations using SIP SHOULD support this specification, since it uses a feature tag in registrations to help interoperability through signaling intermediaries ๐Ÿค

7.3. Interactions with Forking ๐ŸŒ€

ICE gets along really well with forking. In fact, ICE fixes some of the problems forking causes ๐Ÿ’– Without ICE, when a call forks and the caller gets several incoming data streams, it has no way to tell which data stream belongs to which callee ๐Ÿ˜ตโ€๐Ÿ’ซ

With ICE, that problem goes away โœจ The connectivity checks that happen before media is sent carry username fragments, and those fragments get correlated to a specific callee ๐Ÿ”‘ Any media packets that show up later on the same candidate pair as the connectivity check get associated with that same callee ๐ŸŽฏ So the caller can do this correlation as long as it has received an answer ๐Ÿ‘‘

7.4. Interactions with Preconditions โœจ

Okay, so QoS preconditions (defined in [RFC3312] and [RFC4032]) only care about the transport addresses listed as the default targets for media in an offer/answer ๐ŸŽฏ. If ICE changes where media gets received, that change shows up in an updated offer that moves the default destination to match what ICE picked. ๐Ÿ’… From the outside, it looks like any other re-INVITE, so RFCs 3312 and 4032 handle it fully, even though the destination is changing because ICE is negotiating "in the background" ๐Ÿซถ

Here's the key bit ๐Ÿ‘€ An agent SHOULD NOT indicate that QoS preconditions have been met until the checks have finished and picked the candidate pairs that'll actually carry media. Don't claim you're ready before you are, bestie ๐Ÿ˜ญ

ICE also has interactions with connectivity preconditions [RFC5898]. Those are described over there, so go read them if you want the full tea ๐Ÿต Also, the procedures in Section 7.1 describe their own kind of "preconditions," but they have less functionality than the explicit preconditions in [RFC5898]. Not the same level of iconic ๐Ÿ’€

7.5. Interactions with Third Party Call Control

ICE works with Flows I, III, and IV from [RFC3725] ๐Ÿฆ‹ Flow I works even if the controller doesn't support or know about ICE. Flow IV works as long as the controller passes the ICE attributes along without changing them. Flow II is fundamentally incompatible with ICE ๐Ÿ˜ญ Each agent thinks it's the answerer, so neither one ever generates a re-INVITE. Not it ๐Ÿ’€

The flows for continued operation (see Section 7 of [RFC3725]) need some extra behavior from ICE implementations to work. Specifically, if an agent gets a mid-dialog re-INVITE that has no offer, it MUST restart ICE for each data stream and go through gathering new candidates again ๐Ÿ”„ On top of that, that list of candidates SHOULD include the ones currently being used for media, so the good stuff isn't left out โœจ

8. Interactions with Application Layer Gateways and SIP

Okay, the NAT crowd ๐ŸŒ Application Layer Gateways (ALGs) are functions inside a Network Address Translation (NAT) device that look inside packets and modify them, so application protocols can get through NAT ๐Ÿงš Session Border Controllers (SBCs) are close cousins of ALGs, but they're way less invisible because they actually sit there as application-layer SIP intermediaries. ICE has interactions with both SBCs and ALGs, so let's spill ๐Ÿซถ

If an ALG is SIP aware but not ICE aware, ICE will still work through it, as long as the ALG correctly modifies the SDP. A correct ALG behaves like this ๐Ÿ’–

  • The ALG does not modify the m= and c= lines or the rtcp attribute if they contain external addresses.
  • If the m= and c= lines contain internal addresses, the modification depends on the state of the ALG:
    • If the ALG already has a binding that maps an external port to an internal connection address and port matching the values in the m= and c= lines or rtcp attribute, the ALG uses that binding instead of creating a new one.
    • If the ALG does not already have a binding, it creates a new one and modifies the SDP, rewriting the m= and c= lines and rtcp attribute.

Unfortunately, a lot of ALGs are known to work poorly in these corner cases ๐Ÿ™ˆ ICE does not try to work around broken ALGs, because that's outside its scope. ICE can still help diagnose these problems, which usually show up as a mismatch between the set of candidates and the m= and c= lines and rtcp attributes. That's what the ice-mismatch attribute is for ๐Ÿ”

ICE works best through ALGs when the signaling runs over TLS ๐Ÿ” This stops the ALG from messing with the SDP messages and interfering with ICE. Implementations that are expected to be deployed behind ALGs SHOULD provide for TLS transport of the SDP. Protect that SDP, babe ๐Ÿ›ก๏ธ

If an SBC is SIP aware but not ICE aware, the result depends on how the SBC behaves. If it's acting as a proper Back-to-Back User Agent (B2BUA), the SBC will strip out any SDP attributes it doesn't understand, including the ICE attributes ๐Ÿ’€ So the call looks to both endpoints like the other side doesn't support ICE. ICE then gets disabled, and media flows through the SBC if the SBC asked for that. ๐Ÿ˜ค But if the SBC passes the ICE attributes through untouched and still changes the default destination for media (in the m= and c= lines and the rtcp attribute), that gets caught as an ICE mismatch, and ICE processing is aborted for the call. ICE isn't a tool for "working around" SBCs, and it's not going to be one. If an SBC is present, ICE won't be used and the SBC techniques take precedence ๐Ÿ‘‘


9. Security Considerations

Okay, this part is serious, so put your listening ears on ๐Ÿšจ The generic ICE security considerations are defined in [RFC8445], and the generic SDP offer/answer security considerations are defined in [RFC3264]. These security considerations also apply to implementations of this document ๐Ÿ”’

9.1. IP Address Privacy

In some cases, like for privacy reasons, an agent may not want to reveal the related address and port ๐Ÿ™Š In that case the address MUST be set to "0.0.0.0" (for IPv4 candidates) or "::" (for IPv6 candidates), and the port to '9'. Hide your address, but do it the right way ๐Ÿฆ‹

9.2. Attacks on the Offer/Answer Exchanges

โš ๏ธ Okay, this one is actually scary, so read it twice.

An attacker who can modify or disrupt the offer/answer exchanges themselves can easily launch a bunch of attacks with ICE ๐Ÿ˜ฑ They could aim media at the target of a DoS attack, they could insert themselves into the data stream, and more. These are similar to the general security considerations for offer/answer exchanges, and the security considerations in [RFC3264] apply. These attacks need techniques for message integrity and encryption for offers and answers, and when SIP is used, those are covered by the TLS mechanism [RFC3261]. So the usage of TLS with ICE is RECOMMENDED ๐Ÿ”๐Ÿ’œ

9.3. The Voice Hammer Attack

The voice hammer attack is an amplification attack, and it can happen even if the attacker is an authenticated and valid participant in a session ๐Ÿ’€ Here's how it goes: the attacker starts sessions with other agents and sneakily includes the connection address and port of a DoS target as the destination for media signaled in the SDP. That causes serious amplification. One offer/answer exchange can start a continuing flood of media packets, possibly at high rates (think video sources) ๐Ÿ˜ญ

ICE can help prevent this attack. If ICE is used, the agent that gets the malicious SDP will first run connectivity checks to the media target before sending any media there โœ… If that target is a third-party host, the checks won't succeed, so media never gets sent. The ICE extension defined in [RFC7675] can be used to protect even further against voice hammer attacks ๐Ÿซถ

Unfortunately, ICE doesn't help if it isn't used. In that case, an attacker could just send the offer without the ICE parameters ๐Ÿ™ƒ But in environments where the set of clients is known and limited to ones that support ICE, the server can reject any offers or answers that don't indicate ICE support. Gatekeeping, but make it cute ๐Ÿ’…

SIP user agents (UA) [RFC3261] that aren't willing to receive non-ICE answers MUST include an "ice" option tag [RFC5768] in the SIP Require header field in their offer ๐ŸŽ€ UAs that reject non-ICE offers will usually use a 421 response code, together with an option tag "ice" in the Require header field of the response.


10. IANA Considerations

Okay, IANA time ๐Ÿ“‹ The original ICE specification defined seven new SDP attributes, following the procedures of Section 8.2.4 of [RFC4566]. The registration info from that original spec is included here, with changes to add the Mux Category [RFC8859]. This section also defines a new SDP attribute, "ice-pacing" โœจ

10.1. SDP Attributes

10.1.1. "candidate" Attribute

Attribute Name:  candidate

Type of Attribute:  media-level

Subject to charset:  No

Purpose:  This attribute is used with Interactive Connectivity
   Establishment (ICE), and provides one of many possible candidate
   addresses for communication.  These addresses are validated with
   an end-to-end connectivity check using Session Traversal Utilities
   for NAT (STUN).

Appropriate Values:  See Section 5 of RFC 8839.

Contact Name:  IESG

Contact Email:  iesg@ietf.org

Reference:  RFC 8839

Mux Category:  TRANSPORT

10.1.2. "remote-candidates" Attribute

Attribute Name:  remote-candidates

Type of Attribute:  media-level

Subject to charset:  No

Purpose:  This attribute is used with Interactive Connectivity
   Establishment (ICE), and provides the identity of the remote
   candidates that the offerer wishes the answerer to use in its
   answer.

Appropriate Values:  See Section 5 of RFC 8839.

Contact Name:  IESG

Contact Email:  iesg@ietf.org

Reference:  RFC 8839

Mux Category:  TRANSPORT

10.1.3. "ice-lite" Attribute

Attribute Name:  ice-lite

Type of Attribute:  session-level

Subject to charset:  No

Purpose:  This attribute is used with Interactive Connectivity
   Establishment (ICE), and indicates that an agent has the minimum
   functionality required to support ICE inter-operation with a peer
   that has a full implementation.

Appropriate Values:  See Section 5 of RFC 8839.

Contact Name:  IESG

Contact Email:  iesg@ietf.org

Reference:  RFC 8839

Mux Category:  NORMAL

10.1.4. "ice-mismatch" Attribute

Attribute Name:  ice-mismatch

Type of Attribute:  media-level

Subject to charset:  No

Purpose:  This attribute is used with Interactive Connectivity
   Establishment (ICE), and indicates that an agent is ICE capable,
   but did not proceed with ICE due to a mismatch of candidates with
   the default destination for media signaled in the SDP.

Appropriate Values:  See Section 5 of RFC 8839.

Contact Name:  IESG

Contact e-mail:  iesg@ietf.org

Reference:  RFC 8839

Mux Category:  NORMAL

10.1.5. "ice-pwd" Attribute

Attribute Name:  ice-pwd

Type of Attribute:  session- or media-level

Subject to charset:  No

Purpose:  This attribute is used with Interactive Connectivity
   Establishment (ICE), and provides the password used to protect
   STUN connectivity checks.

Appropriate Values:  See Section 5 of RFC 8839.

Contact Name:  IESG

Contact e-mail:  iesg@ietf.org

Reference:  RFC 8839

Mux Category:  TRANSPORT

10.1.6. "ice-ufrag" Attribute

Attribute Name:  ice-ufrag

Type of Attribute:  session- or media-level

Subject to charset:  No

Purpose:  This attribute is used with Interactive Connectivity
   Establishment (ICE), and provides the fragments used to construct
   the username in STUN connectivity checks.

Appropriate Values:  See Section 5 of RFC 8839.

Contact Name:  IESG

Contact e-mail:  iesg@ietf.org

Reference:  RFC 8839

Mux Category:  TRANSPORT

10.1.7. "ice-options" Attribute

Attribute Name:  ice-options

Long Form:  ice-options

Type of Attribute:  session-level

Subject to charset:  No

Purpose:  This attribute is used with Interactive Connectivity
   Establishment (ICE), and indicates the ICE options or extensions
   used by the agent.

Appropriate Values:  See Section 5 of RFC 8839.

Contact Name:  IESG

Contact e-mail:  iesg@ietf.org

Reference:  RFC 8839

Mux Category:  NORMAL

10.1.8. "ice-pacing" Attribute ๐ŸŽ€

okay so this one's a new SDP attribute, "ice-pacing" ๐Ÿ’… Here's the full spec, no cap:

Attribute Name:  ice-pacing

Type of Attribute:  session-level

Subject to charset:  No

Purpose:  This attribute is used with Interactive Connectivity
   Establishment (ICE) to indicate desired connectivity check pacing
   values.

Appropriate Values:  See Section 5 of RFC 8839.

Contact Name:  IESG

Contact e-mail:  iesg@ietf.org

Reference:  RFC 8839

Mux Category:  NORMAL

10.2. Interactive Connectivity Establishment (ICE) Options Registry ๐ŸŒธ

bestie, IANA keeps a registry for "ice-options" identifiers ๐Ÿ—‚๏ธ New entries go in under the Specification Required policy from "Guidelines for Writing an IANA Considerations Section in RFCs" [RFC8126], so it's not a free-for-all, it's giving organized โœจ

ICE options can technically be any length according to the syntax in Section 5.6 ๐Ÿ™ˆ BUT they are RECOMMENDED to stay at 20 characters or less. The reason is simple: shorter means smaller messages and easier parsing, which is lowkey iconic ๐Ÿฆ‹ ICE options are defined at the session level.

A registration request MUST include the following info:

  • The ICE option identifier you want to register ๐Ÿ”‘
  • Name and email address of the organization or individuals who have change control ๐Ÿ“ง
  • A short description of the ICE extension the option relates to ๐Ÿ“
  • Reference(s) to the specification that defines the ICE option and the related extensions ๐Ÿ“š

10.3. Candidate Attribute Extension Subregistry Establishment ๐Ÿ’œ

this section makes a brand new subregistry called "Candidate Attribute Extensions" ๐ŸŽ‰ It lives under the SDP Parameters registry at http://www.iana.org/assignments/sdp-parameters.

The whole point of this subregistry is to register SDP "candidate" attribute extensions ๐Ÿงš

To get in, a "candidate" extension has to meet the "Specification Required" policies defined in [RFC8126]. No shortcuts, periodt ๐Ÿ’…

"candidate" attribute extensions MUST follow the 'cand-extension' syntax ๐Ÿซถ The attribute extension name MUST follow the 'extension-att-name' syntax, and the attribute extension value MUST follow the 'extension-att-value' syntax. Super strict, super clean โœจ

A registration request MUST include the following info:

  • The name of the attribute extension ๐Ÿท๏ธ
  • Name and email address of the organization or individuals who have change control ๐Ÿ“ง
  • A short description of the attribute extension ๐Ÿ“
  • A reference to a specification that describes the semantics, usage, and possible values of the attribute extension ๐Ÿ“š

11. Changes from RFC 5245 ๐ŸŒˆ

okay so the big glow-up is actually documented in [RFC8445] ๐Ÿ’– That one covers the changes to the common SIP procedures, like removing aggressive nomination, changing how candidate pair states are calculated, scheduling connectivity checks, and calculating timer values. Iconic behavior from that doc ๐Ÿ‘‘

This document then adds its own SDP offer/answer specific changes, and here they are:

  • SDP offer/answer realization and usage of the 'ice2' option ๐ŸŽ€
  • Definition and usage of the SDP "ice-pacing" attribute โญ
  • Explicit text saying an ICE agent must not generate candidates with FQDNs, and must discard such candidates if it receives them from the peer agent ๐Ÿ™…โ€โ™€๏ธ (it's giving boundaries)
  • Relaxing the requirement to include the SDP "rtcp" attribute ๐Ÿฆ‹
  • Generic clarifications of SDP offer/answer procedures ๐Ÿง 
  • ICE mismatch is now optional. An agent can choose not to trigger mismatch and instead treat the default candidate as an additional candidate ๐Ÿ”€
  • FQDNs and "0.0.0.0"/"::" IP addresses with port "9" default candidates do not trigger ICE mismatch ๐Ÿ˜ญ main character energy for the default candidate

12. References ๐Ÿงš

12.1. Normative References ๐Ÿ’–

okay these are the must-reads, the ones this spec leans on hard ๐Ÿซถ

12.2. Informative References ๐ŸŒ™

these are the extra-credit reads, good to know but not required ๐Ÿ“–

Appendix A. Examples โœจ

okay so this is the part where we get to see the whole thing actually working, bestie ๐ŸŽ€ the example is the one from Section 15 of [RFC8445], and the offer (message 5) gets encoded in SDP. I've folded the long lines so they fit, because we are not about wrapping chaos ๐Ÿ’…

v=0
o=jdoe 2890844526 2890842807 IN IP6 $L-PRIV-1.IP
s=
c=IN IP6 $NAT-PUB-1.IP
t=0 0
a=ice-options:ice2
a=ice-pacing:50
a=ice-pwd:asd88fgpdd777uzjYhagZg
a=ice-ufrag:8hhY
m=audio $NAT-PUB-1.PORT RTP/AVP 0
b=RS:0
b=RR:0
a=rtpmap:0 PCMU/8000
a=candidate:1 1 UDP 2130706431 $L-PRIV-1.IP $L-PRIV-1.PORT typ host
a=candidate:2 1 UDP 1694498815 $NAT-PUB-1.IP $NAT-PUB-1.PORT typ
 srflx raddr $L-PRIV-1.IP rport $L-PRIV-1.PORT

Now the offer with the variables swapped for their real values, so you can see the actual bits ๐Ÿฆ‹ (folded again for clarity):

v=0
o=jdoe 2890844526 2890842807 IN IP6 fe80::6676:baff:fe9c:ee4a
s=
c=IN IP6 2001:db8:8101:3a55:4858:a2a9:22ff:99b9
t=0 0
a=ice-options:ice2
a=ice-pacing:50
a=ice-pwd:asd88fgpdd777uzjYhagZg
a=ice-ufrag:8hhY
m=audio 45664 RTP/AVP 0
b=RS:0
b=RR:0
a=rtpmap:0 PCMU/8000
a=candidate:1 1 UDP 2130706431 fe80::6676:baff:fe9c:ee4a 8998
 typ host
a=candidate:2 1 UDP 1694498815 2001:db8:8101:3a55:4858:a2a9:22ff:99b9
 45664 typ srflx raddr fe80::6676:baff:fe9c:ee4a rport 8998

And the resulting answer looks like this ๐ŸŒธ

v=0
o=bob 2808844564 2808844564 IN IP4 $R-PUB-1.IP
s=
c=IN IP4 $R-PUB-1.IP
t=0 0
a=ice-options:ice2
a=ice-pacing:50
a=ice-pwd:YH75Fviy6338Vbrhrlp8Yh
a=ice-ufrag:9uB6
m=audio $R-PUB-1.PORT RTP/AVP 0
b=RS:0
b=RR:0
a=rtpmap:0 PCMU/8000
a=candidate:1 1 UDP 2130706431 $R-PUB-1.IP $R-PUB-1.PORT typ host

With the variables filled in:

v=0
o=bob 2808844564 2808844564 IN IP4 192.0.2.1
s=
c=IN IP4 192.0.2.1
t=0 0
a=ice-options:ice2
a=ice-pacing:50
a=ice-pwd:YH75Fviy6338Vbrhrlp8Yh
a=ice-ufrag:9uB6
m=audio 3478 RTP/AVP 0
b=RS:0
b=RR:0
a=rtpmap:0 PCMU/8000
a=candidate:1 1 UDP 2130706431 192.0.2.1 3478 typ host

Appendix B. The "remote-candidates" Attribute ๐Ÿงš

okay so the remote-candidates attribute exists to kill a race condition ๐Ÿ˜ญ between the updated offer and the STUN Binding response that moved a candidate into the valid list. Here's the drama: on receipt of message 4, agent L adds a candidate pair to the valid list. If there was only one data stream with one component, L could send an updated offer right then. BUT the check from agent R hasn't gotten its response yet, so R gets the updated offer (message 7) before the response (message 9) and doesn't know yet that the pair is valid. Not it! ๐Ÿ™…โ€โ™€๏ธ The fix is that the actual candidates at R that were selected by the offerer (the remote candidates) go inside the offer itself, and the answerer holds its answer until those pairs validate.

Figure 1 is the whole saga ๐Ÿ‘‡

   Agent L               Network               Agent R
      |(1) Offer            |                     |
      |------------------------------------------>|
      |(2) Answer           |                     |
      |<------------------------------------------|
      |(3) STUN Req.        |                     |
      |------------------------------------------>|
      |(4) STUN Res.        |                     |
      |<------------------------------------------|
      |(5) STUN Req.        |                     |
      |<------------------------------------------|
      |(6) STUN Res.        |                     |
      |-------------------->|                     |
      |                     |Lost                 |
      |(7) Offer            |                     |
      |------------------------------------------>|
      |(8) STUN Req.        |                     |
      |<------------------------------------------|
      |(9) STUN Res.        |                     |
      |------------------------------------------>|
      |(10) Answer          |                     |
      |<------------------------------------------|

                       Figure 1: Race Condition Flow

Appendix C. Why Is the Conflict Resolution Mechanism Needed? ๐Ÿค”

okay bestie, so when ICE runs between two peers, one agent acts as controlled and the other as controlling. Rules are defined as a function of implementation type and offerer/answerer to decide who's who. BUT the spec says that in some cases both sides might think they're controlling, or both might think they're controlled. How?? ๐Ÿ˜ณ

The both-controlled situation shows up in third party call control cases. Check out this flow:

         A         Controller          B
         |(1) INV()     |              |
         |<-------------|              |
         |(2) 200(SDP1) |              |
         |------------->|              |
         |              |(3) INV()     |
         |              |------------->|
         |              |(4) 200(SDP2) |
         |              |<-------------|
         |(5) ACK(SDP2) |              |
         |<-------------|              |
         |              |(6) ACK(SDP1) |
         |              |------------->|

                    Figure 2: Role Conflict Flow

This flow is a variation on flow III of RFC 3725 [RFC3725]. Honestly it's better than flow III because it sends fewer messages ๐Ÿ’… The controller sends an offerless INVITE to agent A, which replies with its offer, SDP1. Then the agent sends an offerless INVITE to agent B, which replies with its offer, SDP2. The controller uses each agent's offer to generate the answers. When this flow is used, ICE runs between agents A and B, but both think they're in the controlling role. Lucky for us, with the role conflict resolution procedures, this flow works properly when ICE is used โœจ

At this time there are no documented flows that can end up with both agents believing they're controlled. The conflict resolution procedures still allow for that case, just in case a flow shows up that fits ๐Ÿซถ


Appendix D. Why Send an Updated Offer? ๐Ÿ’–

so Section 12.1 of [RFC8445] describes the rules for sending media, and both agents can send media once ICE checks complete, without waiting for an updated offer. Honestly the only purpose of the updated offer is to "correct" the SDP so the default destination for media matches where media is actually going based on ICE (which will be the highest-priority nominated candidate pair) ๐ŸŽฏ

BUT why is the updated offer/answer exchange even needed?? In a pure offer/answer environment it wouldn't be. The offerer and answerer agree on the candidates through ICE and then start using them. As far as the agents themselves are concerned, the updated offer gives no new info. In practice though, loads of components along the signaling path read the SDP, like entities doing off-path QoS reservations, NAT traversal components such as ALGs and Session Border Controllers (SBCs), and diagnostic tools that passively monitor the network. For those tools to keep working without changes, the core property of SDP has to stay: the existing, pre-ICE definitions of the media addresses (the "m=" and "c=" lines and the "rtcp" attribute) must be retained. That's why an updated offer must be sent ๐ŸŒˆ


Acknowledgements ๐ŸŽ€

okay so a big chunk of this document was taken from [RFC5245], written by Jonathan Rosenberg. Some of it was also taken from [RFC6336], written by Magnus Westerlund and Colin Perkins ๐Ÿซถ

Many thanks to Flemming Andreasen for the shepherd review feedback ๐Ÿ’œ

Thanks also to these experts for their reviews and constructive feedback: Thomas Stach, Adam Roach, Peter Saint-Andre, Roman Danyliw, Alissa Cooper, Benjamin Kaduk, Mirja Kรผhlewind, Alexey Melnikov, and ร‰ric Vyncke for their detailed reviews ๐Ÿ‘‘


Contributors ๐ŸŒธ

The following experts contributed textual and structural improvements for this work:

Thomas Stach

Email: thomass.stach@gmail.com


Authors' Addresses ๐Ÿฆ‹

Marc Petit-Huguenin Impedance Mismatch

Email: marc@petit-huguenin.org

Suhas Nandakumar Cisco Systems 707 Tasman Dr Milpitas, CA 95035 United States of America

Email: snandaku@cisco.com

Christer Holmberg Ericsson Hirsalantie 11 FI-02420 Jorvas Finland

Email: christer.holmberg@ericsson.com

Ari Kerรคnen Ericsson FI-02420 Jorvas Finland

Email: ari.keranen@ericsson.com

Roman Shpount TurboBridge 4905 Del Ray Avenue, Suite 300 Bethesda, MD 20814 United States of America

Email: rshpount@turbobridge.com

๐Ÿ“ฆ where this page comes from