RFC 7118
The WebSocket Protocol as a Transport for the Session Initiation Protocol (SIP)
RFC 7118: The WebSocket Protocol as a Transport for the Session Initiation Protocol (SIP) π
okay bestie, this is the RFC that lets SIP ride on WebSockets so SIP can run in the browser πβ¨ here's the title block so you know who's behind it:
- Organisation: Internet Engineering Task Force (IETF) π
- RFC number: 7118
- Title: The WebSocket Protocol as a Transport for the Session Initiation Protocol (SIP)
- Authors: I. Baz Castillo (Versatica), J. Millan Villegas (Versatica), V. Pascual (Quobis) π©βπ»
- Category: Standards Track π¦
- ISSN: 2070-1721
- Date: January 2014 πΈ
- Obsoletes / Updates: this document doesn't list anything it obsoletes or updates π§
Abstract β¨
so the WebSocket protocol lets clients and servers in web apps talk to each other in two directions, in real time π¬ this doc defines a WebSocket subprotocol that acts as a reliable transport between Session Initiation Protocol (SIP) entities, so SIP can work in web-oriented setups π«Ά
Status of This Memo π
This is an Internet Standards Track document.
This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 5741.
Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at http://www.rfc-editor.org/info/rfc7118.
Copyright Notice π₯
Copyright (c) 2014 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) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.
Table of Contents πΊοΈ
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
2. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1. Definitions . . . . . . . . . . . . . . . . . . . . . . . 3
3. The WebSocket Protocol . . . . . . . . . . . . . . . . . . . 3
4. The WebSocket SIP Subprotocol . . . . . . . . . . . . . . . . 4
4.1. Handshake . . . . . . . . . . . . . . . . . . . . . . . . 4
4.2. SIP Encoding . . . . . . . . . . . . . . . . . . . . . . 5
5. SIP WebSocket Transport . . . . . . . . . . . . . . . . . . . 6
5.1. Via Transport Parameter . . . . . . . . . . . . . . . . . 6
5.2. SIP URI Transport Parameter . . . . . . . . . . . . . . . 6
5.3. Via "received" Parameter . . . . . . . . . . . . . . . . 7
5.4. SIP Transport Implementation Requirements . . . . . . . . 7
5.5. Locating a SIP Server . . . . . . . . . . . . . . . . . . 8
6. Connection Keep-Alive . . . . . . . . . . . . . . . . . . . . 8
7. Authentication . . . . . . . . . . . . . . . . . . . . . . . 8
8. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 10
8.1. Registration . . . . . . . . . . . . . . . . . . . . . . 10
8.2. INVITE Dialog through a Proxy . . . . . . . . . . . . . . 12
9. Security Considerations . . . . . . . . . . . . . . . . . . . 16
9.1. Secure WebSocket Connection . . . . . . . . . . . . . . . 16
9.2. Usage of "sips" Scheme . . . . . . . . . . . . . . . . . 16
10. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 16
10.1. Registration of the WebSocket SIP Subprotocol . . . . . 16
10.2. Registration of New NAPTR Service Field Values . . . . . 17
10.3. SIP/SIPS URI Parameters Subregistry . . . . . . . . . . 17
10.4. Header Fields Subregistry . . . . . . . . . . . . . . . 17
10.5. Header Field Parameters and Parameter Values Subregistry 17
10.6. SIP Transport Subregistry . . . . . . . . . . . . . . . 18
11. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 18
12. References . . . . . . . . . . . . . . . . . . . . . . . . . 18
12.1. Normative References . . . . . . . . . . . . . . . . . . 18
12.2. Informative References . . . . . . . . . . . . . . . . . 19
Appendix A. Authentication Use Cases . . . . . . . . . . . . . . 21
A.1. Just SIP Authentication . . . . . . . . . . . . . . . . . 21
A.2. Just Web Authentication . . . . . . . . . . . . . . . . . 21
A.3. Cookie-Based Authentication . . . . . . . . . . . . . . . 22
Appendix B. Implementation Guidelines . . . . . . . . . . . . . 22
B.1. SIP WebSocket Client Considerations . . . . . . . . . . . 23
B.2. SIP WebSocket Server Considerations . . . . . . . . . . . 24
1. Introduction π
so the WebSocket protocol [RFC6455] lets clients and servers swap messages over a long-lived TCP connection, optionally wrapped in Transport Layer Security (TLS) [RFC5246] π the opening handshake borrows HTTP [RFC2616] semantics, which means WebSocket can reuse all the HTTP infrastructure that already exists π§
modern browsers ship a WebSocket client stack that follows the WebSocket API [WS-API] from the W3C π other client apps (on PCs and devices like smartphones) are expected to bring their own stack too, and this spec is what makes SIP work in all of those places π±
this spec defines a WebSocket subprotocol (as defined in Section 1.9 of [RFC6455]) for carrying SIP messages between a WebSocket client and server. it gives you a reliable, message-boundary-preserving transport for SIP π― it also defines the DNS Naming Authority Pointer (NAPTR) [RFC3403] service values and procedures that SIP entities need in order to use the WebSocket transport π media transport is out of scope here, so no audio/video stuff in this doc π
Section 3 in this specification relaxes the requirement in [RFC3261] by which the SIP server transport MUST add a "received" parameter in the top Via header in certain circumstances. π
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 [RFC2119]. π
2.1. Definitions π
SIP WebSocket Client: a SIP entity that can open outbound connections to WebSocket servers and talk over them using the WebSocket SIP subprotocol defined here π¦
SIP WebSocket Server: a SIP entity that can listen for inbound connections from WebSocket clients and talk over them using the WebSocket SIP subprotocol defined here π«Ά
3. The WebSocket Protocol π§
ok so WebSocket [RFC6455] is a transport layer that sits on top of TCP (optionally secured with TLS [RFC5246]), and both the client and the server can send message units in both directions βοΈ the protocol covers a connection handshake, negotiation of subprotocols and extensions, a frame format for application and control data, a masking mechanism, and status codes that explain why a connection closed π
the WebSocket handshake is based on HTTP [RFC2616] and uses the HTTP GET method with an "Upgrade" request. the client sends it, and if the negotiation works out, the server answers with an HTTP 101 status code π once that's done, the connection switches from HTTP over to WebSocket. the whole procedure was designed to reuse existing HTTP infrastructure πΈ during the handshake, client and server agree on which application protocol will run on top of the WebSocket transport. that application protocol (also called a "WebSocket subprotocol") defines the format and meaning of the messages the endpoints swap. it can be a custom protocol or a standardised one, like the WebSocket SIP subprotocol in this document π after the HTTP 101 response is handled, both sides reuse the same TCP connection to send WebSocket messages and control frames to each other. unlike plain HTTP, this connection is persistent and can carry many message exchanges β¨
WebSocket defines message units that applications use to exchange data, so it gives you a message-boundary-preserving transport layer π¦ those message units can hold either UTF-8 text or binary data, and the WebSocket stack is free to split them into several WebSocket text/binary transport frames whenever it needs to π§©
The WebSocket API [WS-API] for web browsers only defines callbacks to be invoked upon receipt of an entire message unit, regardless of whether it was received in a single WebSocket frame or split across multiple frames. π
4. The WebSocket SIP Subprotocol π¦
"WebSocket subprotocol" just means an application-level protocol layered on top of a WebSocket connection π this document specifies the WebSocket SIP subprotocol, which is what carries SIP requests and responses through a WebSocket connection π
4.1. Handshake π€
the SIP WebSocket Client and SIP WebSocket Server agree to use the WebSocket SIP subprotocol during the WebSocket handshake, as defined in Section 1.3 of [RFC6455]. the client MUST include the value "sip" in the Sec-WebSocket-Protocol header in its handshake request. the 101 reply from the server MUST contain "sip" in its matching Sec-WebSocket-Protocol header. π
the WebSocket client opens a WebSocket connection when it wants to send a SIP request, unless there's already an established WebSocket connection it can use for that request. if there's no HTTP 101 response during the WebSocket handshake, that counts as a transaction error under [RFC3261], Section 8.1.3.1., "Transaction Layer Errors" π
here's an example of a WebSocket handshake where the client asks the server for WebSocket SIP subprotocol support:
GET / HTTP/1.1
Host: sip-ws.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://www.example.com
Sec-WebSocket-Protocol: sip
Sec-WebSocket-Version: 13
and the server's response accepting the WebSocket SIP subprotocol looks like this:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: sip
once negotiation is complete, the WebSocket connection is established and can carry SIP requests and responses. messages that aren't SIP requests or responses MUST NOT be transmitted over this connection. π«
4.2. SIP Encoding π»
WebSocket messages can travel in either UTF-8 text frames or binary frames. SIP [RFC3261] allows both text and binary bodies in SIP requests and responses, so SIP WebSocket Clients and SIP WebSocket Servers MUST accept both text and binary frames. π«§
If there is at least one non-UTF-8 symbol in the whole SIP message (including headers and the body), then the whole message MUST be sent within a WebSocket binary message. Given the nature of JavaScript and the WebSocket API, it is RECOMMENDED to use UTF-8 encoding (or ASCII, which is a subset of UTF-8) for SIP messages carried over a WebSocket connection. π
(part 1 of 5, more RFC goodness coming, bestie π§β¨)
5. SIP WebSocket Transport π¦
okay so WebSocket [RFC6455] is a reliable protocol π, which means the SIP WebSocket subprotocol in this doc is a reliable SIP transport too β¨. Client and server transactions using WebSocket for transport MUST follow the procedures and timer values for reliable transports as defined in [RFC3261]. no cap, that's the rule π
Each SIP message MUST be carried within a single WebSocket message, and a WebSocket message MUST NOT contain more than one SIP message. Since WebSocket keeps message boundaries intact π«Ά, you don't need a Content-Length header in SIP messages when they travel over this subprotocol.
it's giving simplicity πΈ Parsing SIP gets easier for both clients and servers because there's no need to figure out where one message ends and the next begins using Content-Length headers. UDP and the Stream Control Transmission Protocol (SCTP) [RFC4168] also get this perk β¨
5.1. Via Transport Parameter
Via header fields in SIP messages carry a transport protocol identifier π. This doc defines the value "WS" for requests over plain WebSocket connections, and "WSS" for requests over secure WebSocket connections, where the WebSocket connection is set up using TLS [RFC5246] on top of TCP transport π.
The updated augmented BNF (Backus-Naur Form) [RFC5234] for this parameter looks like this. The original BNF is in [RFC3261], which was then updated by [RFC4168]:
transport =/ "WS" / "WSS"
5.2. SIP URI Transport Parameter
This document defines the value "ws" as the transport parameter for a SIP URI [RFC3986] that gets contacted using the SIP WebSocket subprotocol as its transport π¦.
The updated augmented BNF for this parameter is below. The original BNF is in [RFC3261]:
transport-param =/ "transport=" "ws"
5.3. Via "received" Parameter
Here's what [RFC3261], Section 18.2.1, "Receiving Requests" says:
When the server transport receives a request over any transport, it MUST examine the value of the "sent-by" parameter in the top Via header field value. If the host portion of the "sent-by" field contains a domain name, or if it contains an IP address that differs from the packet source address, the server MUST add a "received" parameter to that Via header field value. This parameter MUST contain the source address from which the packet was received.
okay but here's the tea β. Adding the "received" parameter doesn't vibe well with the WebSocket design π. The WebSocket handshake reuses the existing HTTP infrastructure, and there could be an unknown number of HTTP proxies and/or TCP load balancers between the SIP WebSocket Client and Server π. So the source address the server would write into the Via "received" parameter would be the address of whatever HTTP/TCP middleman is in front of it. That could leak sensitive info about the server's internal network topology to the client π.
Also, SIP responses can only be sent over the existing WebSocket connection, so the Via "received" parameter isn't that useful anyway π€·ββοΈ. To let the SIP WebSocket Server hide possibly sensitive info about its network, this document updates [RFC3261], Section 18.2.1 with the following:
When a SIP WebSocket Server receives a request, it MAY decide not to add a "received" parameter to the top Via header. Therefore, SIP WebSocket Clients MUST accept responses without such a parameter in the top Via header regardless of whether the Via "sent-by" field contains a domain name.
5.4. SIP Transport Implementation Requirements
From [RFC3261], Section 18, "Transport", we've got this:
All SIP elements MUST implement UDP and TCP. SIP elements MAY implement other protocols.
This transport lets SIP be used as a session establishment protocol in situations where none of the other SIP transports can be used π§. Some environments don't let SIP elements use UDP and TCP at all, so a SIP element acting as a SIP WebSocket Client isn't required to support UDP and TCP π.
5.5. Locating a SIP Server
[RFC3263] is the one that spells out how SIP entities should find SIP servers π. This spec defines the NAPTR service value "SIP+D2W" for SIP WebSocket Servers that support plain WebSocket connections, and "SIPS+D2W" for SIP WebSocket Servers that support secure WebSocket connections β¨.
At the time this document was written, DNS NAPTR/Service Record (SRV) queries could not be performed by commonly available WebSocket client stacks (in JavaScript engines and web browsers).
So if there are no DNS SRV records and no explicit port, the default port for a SIP URI using the "sip" scheme and the "ws" transport parameter is 80 π. For a SIP URI using the "sips" scheme and the "ws" transport parameter, the default port is 443 π.
6. Connection Keep-Alive π
SIP WebSocket Clients and Servers can keep their WebSocket connections open by sending periodic WebSocket "Ping" frames, as described in [RFC6455], Section 5.5.2 π.
The WebSocket API [WS-API] doesn't give web apps a way to control whether periodic WebSocket "Ping" frames get sent to the server. That keep-alive behavior is up to each web browser manufacturer and might also depend on how the browser is configured π.
The CRLF NAT keep-alive mechanism for SIP connection-oriented transports, defined in [RFC5626], Section 3.5.1, or the one in [RFC6223], can totally be used over the transport in this spec π«Ά.
7. Authentication π
This section explains how authentication works through the requirements in [RFC6455], [RFC6265], [RFC2617], and [RFC3261] π.
The WebSocket protocol [RFC6455] doesn't define an authentication mechanism. Instead, Section 10.5, "WebSocket Client Authentication" says:
This protocol doesn't prescribe any particular way that servers can authenticate clients during the WebSocket handshake. The WebSocket server can use any client authentication mechanism available to a generic HTTP server, such as cookies, HTTP authentication, or TLS authentication.
So for interoperability at the WebSocket authentication level, here's the list of mandatory-to-implement and optional mechanisms for SIP WebSocket Clients and Servers π:
- A SIP WebSocket Client MUST be ready to add a session cookie when it runs in a web browser (or acts like a browser navigating a website) and has previously gotten a session cookie from the web server whose URL domain matches the domain in the WebSocket URI πͺ. This mechanism is defined by [RFC6265].
- A SIP WebSocket Client MUST be ready to be challenged with an HTTP 401 status code [RFC2617] by the SIP WebSocket Server during the WebSocket handshake πββοΈ.
- A SIP WebSocket Client MAY use TLS client authentication (when on a secure WebSocket connection) as an optional authentication mechanism π.
Heads up though π¨: TLS client authentication in the WebSocket protocol is governed by the rules of the HTTP protocol, not the rules of SIP.
- A SIP WebSocket Server MUST be ready to read session cookies when they're present in the WebSocket handshake request, and use that cookie value to figure out whether the WebSocket connection was started by an HTTP client navigating a website on the same domain (or a subdomain) as the SIP WebSocket Server π§.
- A SIP WebSocket Server SHOULD be able to reject a WebSocket handshake request with an HTTP 401 status code by providing a Basic/Digest challenge as defined for the HTTP protocol πΈ.
Whether or not the SIP WebSocket Server requires authentication during the WebSocket handshake, authentication MAY be requested at the SIP level β¨.
Some authentication use cases are covered in Appendix A π .
8. Examples π
8.1. Registration
Alice (SIP WSS) proxy.example.com
| |
|HTTP GET (WS handshake) F1 |
|---------------------------->|
|101 Switching Protocols F2 |
|<----------------------------|
| |
|REGISTER F3 |
|---------------------------->|
|200 OK F4 |
|<----------------------------|
| |
Alice loads a web page in her browser and grabs the JavaScript that implements the WebSocket SIP subprotocol from this doc π». That JavaScript (a SIP WebSocket Client) opens a secure WebSocket connection to a SIP proxy/registrar (a SIP WebSocket Server) at proxy.example.com π¦. Once the WebSocket connection is up, Alice builds and sends a SIP REGISTER request that includes Outbound [RFC5626] and Globally Routable User Agent URI (GRUU) [RFC5627] support π. The JavaScript stack in a browser has no way to find out the local address the WebSocket connection was made from, so this implementation uses a random ".invalid" domain name for the Via header "sent-by" parameter and for the hostport of the URI in the Contact header (see Appendix B.1) π.
Message details (authentication and Session Description Protocol (SDP) bodies are left out for simplicity):
F1 HTTP GET (WS handshake) Alice -> proxy.example.com (TLS)
GET / HTTP/1.1
Host: proxy.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: https://www.example.com
Sec-WebSocket-Protocol: sip
Sec-WebSocket-Version: 13
F2 101 Switching Protocols proxy.example.com -> Alice (TLS)
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: sip
F3 REGISTER Alice -> proxy.example.com (transport WSS)
REGISTER sip:proxy.example.com SIP/2.0
Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bKasudf
From: sip:alice@example.com;tag=65bnmj.34asd
To: sip:alice@example.com
Call-ID: aiuy7k9njasd
CSeq: 1 REGISTER
Max-Forwards: 70
Supported: path, outbound, gruu
Contact: <sip:alice@df7jal23ls0d.invalid;transport=ws>
;reg-id=1
;+sip.instance="<urn:uuid:f81-7dec-14a06cf1>"
F4 200 OK proxy.example.com -> Alice (transport WSS)
SIP/2.0 200 OK
Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bKasudf
From: sip:alice@example.com;tag=65bnmj.34asd
To: sip:alice@example.com;tag=12isjljn8
Call-ID: aiuy7k9njasd
CSeq: 1 REGISTER
Supported: outbound, gruu
Contact: <sip:alice@df7jal23ls0d.invalid;transport=ws>
;reg-id=1
;+sip.instance="<urn:uuid:f81-7dec-14a06cf1>"
;pub-gruu="sip:alice@example.com;gr=urn:uuid:f81-7dec-14a06cf1"
;temp-gruu="sip:87ash54=3dd.98a@example.com;gr"
;expires=3600
8.2. INVITE Dialog through a Proxy π¦
Okay so this is the full call flow, and it's giving main character energy π Alice is on SIP over WSS, Bob is on plain old SIP over UDP, and the proxy in the middle does all the translating β¨
Alice (SIP WSS) proxy.example.com (SIP UDP) Bob
| | |
|INVITE F1 | |
|---------------------------->| |
|100 Trying F2 | |
|<----------------------------| |
| |INVITE F3 |
| |---------------------------->|
| |200 OK F4 |
| |<----------------------------|
|200 OK F5 | |
|<----------------------------| |
| | |
|ACK F6 | |
|---------------------------->| |
| |ACK F7 |
| |---------------------------->|
| | |
| Bidirectional RTP Media |
|<=========================================================>|
| | |
| |BYE F8 |
| |<----------------------------|
|BYE F9 | |
|<----------------------------| |
|200 OK F10 | |
|---------------------------->| |
| |200 OK F11 |
| |---------------------------->|
| | |
So in the same setup, Alice calls Bob's Address of Record (AOR) π The SIP WebSocket Server at proxy.example.com acts as a SIP proxy and routes the INVITE to Bob's contact address, which happens to be using SIP over UDP πΈ Bob picks up and then ends the call π
Here are the messages. Authentication and SDP bodies are left out to keep things simple π
F1 INVITE Alice -> proxy.example.com (transport WSS)
INVITE sip:bob@example.com SIP/2.0
Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bK56sdasks
From: sip:alice@example.com;tag=asdyka899
To: sip:bob@example.com
Call-ID: asidkj3ss
CSeq: 1 INVITE
Max-Forwards: 70
Supported: path, outbound, gruu
Route: <sip:proxy.example.com:443;transport=ws;lr>
Contact: <sip:alice@example.com
;gr=urn:uuid:f81-7dec-14a06cf1;ob>
Content-Type: application/sdp
F2 100 Trying proxy.example.com -> Alice (transport WSS)
SIP/2.0 100 Trying
Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bK56sdasks
From: sip:alice@example.com;tag=asdyka899
To: sip:bob@example.com
Call-ID: asidkj3ss
CSeq: 1 INVITE
F3 INVITE proxy.example.com -> Bob (transport UDP)
INVITE sip:bob@203.0.113.22:5060 SIP/2.0
Via: SIP/2.0/UDP proxy.example.com;branch=z9hG4bKhjhjqw32c
Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bK56sdasks
Record-Route: <sip:proxy.example.com;transport=udp;lr>,
<sip:h7kjh12s@proxy.example.com:443;transport=ws;lr>
From: sip:alice@example.com;tag=asdyka899
To: sip:bob@example.com
Call-ID: asidkj3ss
CSeq: 1 INVITE
Max-Forwards: 69
Supported: path, outbound, gruu
Contact: <sip:alice@example.com
;gr=urn:uuid:f81-7dec-14a06cf1;ob>
Content-Type: application/sdp
F4 200 OK Bob -> proxy.example.com (transport UDP)
SIP/2.0 200 OK
Via: SIP/2.0/UDP proxy.example.com;branch=z9hG4bKhjhjqw32c
;received=192.0.2.10
Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bK56sdasks
Record-Route: <sip:proxy.example.com;transport=udp;lr>,
<sip:h7kjh12s@proxy.example.com:443;transport=ws;lr>
From: sip:alice@example.com;tag=asdyka899
To: sip:bob@example.com;tag=bmqkjhsd
Call-ID: asidkj3ss
CSeq: 1 INVITE
Contact: <sip:bob@203.0.113.22:5060;transport=udp>
Content-Type: application/sdp
F5 200 OK proxy.example.com -> Alice (transport WSS)
SIP/2.0 200 OK
Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bK56sdasks
Record-Route: <sip:proxy.example.com;transport=udp;lr>,
<sip:h7kjh12s@proxy.example.com:443;transport=ws;lr>
From: sip:alice@example.com;tag=asdyka899
To: sip:bob@example.com;tag=bmqkjhsd
Call-ID: asidkj3ss
CSeq: 1 INVITE
Contact: <sip:bob@203.0.113.22:5060;transport=udp>
Content-Type: application/sdp
F6 ACK Alice -> proxy.example.com (transport WSS)
ACK sip:bob@203.0.113.22:5060;transport=udp SIP/2.0
Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bKhgqqp090
Route: <sip:h7kjh12s@proxy.example.com:443;transport=ws;lr>,
<sip:proxy.example.com;transport=udp;lr>,
From: sip:alice@example.com;tag=asdyka899
To: sip:bob@example.com;tag=bmqkjhsd
Call-ID: asidkj3ss
CSeq: 1 ACK
Max-Forwards: 70
F7 ACK proxy.example.com -> Bob (transport UDP)
ACK sip:bob@203.0.113.22:5060;transport=udp SIP/2.0
Via: SIP/2.0/UDP proxy.example.com;branch=z9hG4bKhwpoc80zzx
Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bKhgqqp090
From: sip:alice@example.com;tag=asdyka899
To: sip:bob@example.com;tag=bmqkjhsd
Call-ID: asidkj3ss
CSeq: 1 ACK
Max-Forwards: 69
F8 BYE Bob -> proxy.example.com (transport UDP)
BYE sip:alice@example.com;gr=urn:uuid:f81-7dec-14a06cf1;ob SIP/2.0
Via: SIP/2.0/UDP 203.0.113.22;branch=z9hG4bKbiuiansd001
Route: <sip:proxy.example.com;transport=udp;lr>,
<sip:h7kjh12s@proxy.example.com:443;transport=ws;lr>
From: sip:bob@example.com;tag=bmqkjhsd
To: sip:alice@example.com;tag=asdyka899
Call-ID: asidkj3ss
CSeq: 1201 BYE
Max-Forwards: 70
F9 BYE proxy.example.com -> Alice (transport WSS)
BYE sip:alice@example.com;gr=urn:uuid:f81-7dec-14a06cf1;ob SIP/2.0
Via: SIP/2.0/WSS proxy.example.com:443;branch=z9hG4bKmma01m3r5
Via: SIP/2.0/UDP 203.0.113.22;branch=z9hG4bKbiuiansd001
From: sip:bob@example.com;tag=bmqkjhsd
To: sip:alice@example.com;tag=asdyka899
Call-ID: asidkj3ss
CSeq: 1201 BYE
Max-Forwards: 69
F10 200 OK Alice -> proxy.example.com (transport WSS)
SIP/2.0 200 OK
Via: SIP/2.0/WSS proxy.example.com:443;branch=z9hG4bKmma01m3r5
Via: SIP/2.0/UDP 203.0.113.22;branch=z9hG4bKbiuiansd001
From: sip:bob@example.com;tag=bmqkjhsd
To: sip:alice@example.com;tag=asdyka899
Call-ID: asidkj3ss
CSeq: 1201 BYE
F11 200 OK proxy.example.com -> Bob (transport UDP)
SIP/2.0 200 OK
Via: SIP/2.0/UDP 203.0.113.22;branch=z9hG4bKbiuiansd001
From: sip:bob@example.com;tag=bmqkjhsd
To: sip:alice@example.com;tag=asdyka899
Call-ID: asidkj3ss
CSeq: 1201 BYE
9. Security Considerations π
Security is a big deal, so this part is serious business π€
9.1. Secure WebSocket Connection π
It is RECOMMENDED that SIP traffic carried over a WebSocket connection is protected with a secure WebSocket connection, which means TLS [RFC5246] over TCP π«Ά
When you set up a connection using SIP over secure WebSocket transport, the client MUST authenticate the server by checking the server's certificate with the WebSocket validation procedure in [RFC6455] β
Server operators, pay attention here: this authentication procedure is different from the procedure for SIP domain certificates defined in [RFC5922]. A certificate that works for SIP over TLS over TCP will probably not work for SIP over secure WebSocket connections. Don't assume it will π
9.2. Usage of "sips" Scheme π
The "sips" scheme in a SIP URI means the whole request path to the target has to be secure π So if that path includes a WebSocket connection, it MUST be a secure WebSocket connection, no exceptions π ββοΈ
10. IANA Considerations π
Here's what IANA gets to add to its registries π
10.1. Registration of the WebSocket SIP Subprotocol π§¦
IANA has registered the WebSocket SIP subprotocol in the "WebSocket Subprotocol Name" registry, with this data:
Subprotocol Identifier: sip
Subprotocol Common Name: WebSocket Transport for SIP (Session
Initiation Protocol)
Subprotocol Definition: [RFC7118]
10.2. Registration of New NAPTR Service Field Values π§
This document defines two new NAPTR service field values, SIP+D2W and SIPS+D2W, and IANA has registered them in the "Registry for the Session Initiation Protocol (SIP) NAPTR Resource Record Services Field". The entries look like this:
Services Field Protocol Reference
-------------- -------- ---------
SIP+D2W WS [RFC7118]
SIPS+D2W WS [RFC7118]
10.3. SIP/SIPS URI Parameters Subregistry π
IANA has added a reference to this document in the "SIP/SIPS URI Parameters" subregistry, which lives inside the "Session Initiation Protocol (SIP) Parameters" registry:
Parameter Name Predefined Values Reference
-------------- ----------------- ---------
transport Yes [RFC3261][RFC7118]
10.4. Header Fields Subregistry π¨
IANA has added a reference to this document in the "Header Fields" subregistry, inside the "Session Initiation Protocol (SIP) Parameters" registry:
Header Name compact Reference
----------- ------- ---------
Via v [RFC3261][RFC7118]
10.5. Header Field Parameters and Parameter Values Subregistry π
IANA has added a reference to this document in the "Header Field Parameters and Parameter Values" subregistry, inside the "Session Initiation Protocol (SIP) Parameters" registry:
Predefined
Header Field Parameter Name Values Reference
------------ -------------- ------ ---------
Via received No [RFC3261][RFC7118]
10.6. SIP Transport Subregistry π
This document adds a brand new subregistry, "SIP Transport", to the "Session Initiation Protocol (SIP) Parameters" registry. Its format and starting values are shown in this table:
+------------+------------------------+
| Transport | Reference |
+------------+------------------------+
| UDP | [RFC3261] |
| TCP | [RFC3261] |
| TLS | [RFC3261] |
| SCTP | [RFC3261], [RFC4168] |
| TLS-SCTP | [RFC4168] |
| WS | [RFC7118] |
| WSS | [RFC7118] |
+------------+------------------------+
Registering new values in this registry follows the "Standards Action" policy [RFC5226] π
11. Acknowledgements π
Huge thanks to everyone who joined the discussions on the SIPCORE and RTCWEB WG mailing lists π₯Ή They shared ideas and gave detailed reviews. This list is probably not complete, so if you're not on it, you're still iconic π«Ά Hadriel Kaplan, Paul Kyzivat, Robert Sparks, Adam Roach, Ranjit Avasarala, Xavier Marjou, Nataraju A. B., Martin Vopatek, Alexey Melnikov, Alan Johnston, Christer Holmberg, Salvatore Loreto, Kevin P. Fleming, Suresh Krishnan, Yaron Sheffer, Richard Barnes, Barry Leiba, Stephen Farrell, Ted Lemon, Benoit Claise, Pete Resnick, Binod P.G., and Saul Ibarra Corretge β¨
12. References π
12.1. Normative References
The must-read list π Every entry is copied exactly, so you can find each one:
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC2617] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S.,
Leach, P., Luotonen, A., and L. Stewart, "HTTP
Authentication: Basic and Digest Access Authentication",
RFC 2617, June 1999.
[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.
[RFC3403] Mealling, M., "Dynamic Delegation Discovery System (DDDS)
Part Three: The Domain Name System (DNS) Database", RFC
3403, October 2002.
[RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an
IANA Considerations Section in RFCs", BCP 26, RFC 5226,
May 2008.
[RFC5234] Crocker, D. and P. Overell, "Augmented BNF for Syntax
Specifications: ABNF", STD 68, RFC 5234, January 2008.
[RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security
(TLS) Protocol Version 1.2", RFC 5246, August 2008.
[RFC6265] Barth, A., "HTTP State Management Mechanism", RFC 6265,
April 2011.
[RFC6455] Fette, I. and A. Melnikov, "The WebSocket Protocol", RFC
6455, December 2011.
12.2. Informative References
The extra-credit reading π§ β¨ Same deal, copied word for word:
[RFC2606] Eastlake, D. and A. Panitz, "Reserved Top Level DNS
Names", BCP 32, RFC 2606, June 1999.
[RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext
Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
[RFC3327] Willis, D. and B. Hoeneisen, "Session Initiation Protocol
(SIP) Extension Header Field for Registering Non-Adjacent
Contacts", RFC 3327, December 2002.
[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
Resource Identifier (URI): Generic Syntax", STD 66, RFC
3986, January 2005.
[RFC4168] Rosenberg, J., Schulzrinne, H., and G. Camarillo, "The
Stream Control Transmission Protocol (SCTP) as a Transport
for the Session Initiation Protocol (SIP)", RFC 4168,
October 2005.
[RFC5626] Jennings, C., Mahy, R., and F. Audet, "Managing Client-
Initiated Connections in the Session Initiation Protocol
(SIP)", RFC 5626, October 2009.
[RFC5627] Rosenberg, J., "Obtaining and Using Globally Routable User
Agent URIs (GRUUs) in the Session Initiation Protocol
(SIP)", RFC 5627, October 2009.
[RFC5922] Gurbani, V., Lawrence, S., and A. Jeffrey, "Domain
Certificates in the Session Initiation Protocol (SIP)",
RFC 5922, June 2010.
[RFC6223] Holmberg, C., "Indication of Support for Keep-Alive", RFC
6223, April 2011.
[WS-API] W3C and I. Hickson, Ed., "The WebSocket API", September
2012.
Appendix A. Authentication Use Cases β¨
Okay so, this appendix is all about SIP over WebSocket scenarios where authentication happens in totally different ways π It's giving "every setup has its own vibe" π¦
A.1. Just SIP Authentication
So SIP Private Branch Exchange (PBX) model A implements the SIP WebSocket transport defined by this spec π Its implementation is 100% website agnostic π because it doesn't share any info with the web server that serves the HTML to browsers. That means the SIP WebSocket Server (here, PBX model A) has no clue what web login activity is happening on the website. Zero. Nada. π
In this simple setup, the SIP WebSocket Server doesn't inspect fields in the WebSocket handshake HTTP GET request, like the request URL, the Origin header value, the Host header value, or the Cookie header value (if there is one). BUT, some of those fields could be checked for minimal validation. For example, PBX model A could require that the Origin header value contains a specific URL, so only users navigating that website would be able to set up a WebSocket connection with PBX model A π₯
Once the WebSocket connection is up, PBX model A asks for SIP authentication on every SIP request coming over that connection. So SIP WebSocket Clients must be provisioned with their corresponding SIP password π
A.2. Just Web Authentication
Picture this: a SIP-to-PSTN (Public Switched Telephone Network) provider offers telephony service to clients logged into its website π The provider doesn't want to expose SIP passwords to the web, for security and privacy reasons π«Ά
Once the user is logged in on the web, the web server gives them a SIP identity (a SIP URI) and a session temporary token string π§ It also hands over the SIP WebSocket Client JavaScript application and SIP settings. The web server then stores the SIP identity and session token in a database π
The web app adds the SIP identity and session token as URL query parameters in the WebSocket handshake request and tries to connect. The SIP WebSocket Server checks the handshake request and validates that the session token matches the value stored in the database for that SIP identity. If it matches, the WebSocket connection gets "authenticated" for that SIP identity β¨ Then the SIP WebSocket Client can register and make calls π²
Here's the catch: the SIP WebSocket Server would still verify that the identity in those SIP requests (that is, the From URI value) matches the SIP identity the WebSocket connection is tied to. If it doesn't match, the SIP request gets rejected π ββοΈ
When the user logs out on the web, the web server removes the SIP identity and session token tuple from the database and notifies the SIP WebSocket Server. The server then revokes and closes the WebSocket connection π
No SIP authentication takes place in this scenario. Not one bit π
A.3. Cookie-Based Authentication
The Apache web server comes with a brand-new module: mod_sip_websocket π On port 80, the web server is set up to listen for both regular HTTP requests and WebSocket handshake requests. So the web server and the SIP WebSocket Server are co-located on the same host and same domain π
Once the user is logged in, they get the SIP WebSocket Client JavaScript application and SIP settings. The HTTP 200 response after the login procedure also contains a session cookie [RFC6265] πͺ Then the web app tries a WebSocket connection against the same URL/domain as the website. That means the browser automatically adds the session cookie into the WebSocket handshake request, as the WebSocket protocol [RFC6455] says it should π¦
The web server inspects the cookie value, just like it would for a regular HTTP request with a session cookie, so the login procedure doesn't have to happen again π If the cookie is valid, the WebSocket connection is authorized. And, same as the previous use case, the connection is also associated with a specific SIP identity, which has to be satisfied by every SIP request coming over that connection π
No SIP authentication takes place here either, just regular cookie usage like you see all over the World Wide Web πΈ
Appendix B. Implementation Guidelines π§
Let's set the scene π¬ Users open an application in their web browsers (probably behind NAT) that's provided by a server on an intranet. They log in by entering their user identifier and credentials, and then they retrieve a JavaScript application (along with the HTML) that implements a SIP WebSocket Client π
That SIP stack connects to a SIP WebSocket Server, which is an outbound SIP proxy that also implements classic SIP transports like UDP and TCP π₯ The HTTP GET method request the web browser sends for the WebSocket handshake includes a Cookie [RFC6265] header, with the value the server gave after the successful login πͺ The WebSocket server then inspects that cookie value to authorize the connection. Once the WebSocket connection is established, the SIP WebSocket Client does a SIP registration with a SIP registrar server that's reachable through the proxy. After that, the SIP WebSocket Client and Server exchange SIP messages like you'd normally expect π
This setup is pretty similar to the one where SIP user agents (UAs) sit behind NATs, connect to a proxy, and have to reuse the same TCP connection for incoming requests. Otherwise the proxy can't reach them directly π In both cases, the SIP UAs can only be reached through the proxy they're connected to π«Ά
The SIP Outbound extension [RFC5626] seems like the right fit here π So these SIP WebSocket Clients and the SIP registrar implement both the Outbound and Path [RFC3327] extensions, and the SIP proxy acts as an Outbound Edge Proxy (as defined in [RFC5626], Section 3.4) π¦
SIP WebSocket Clients in this scenario receive incoming SIP requests through the SIP WebSocket Server they're connected to. So in some call transfer cases, using GRUU [RFC5627] is super valuable π GRUU should be implemented in both the SIP WebSocket Clients and the SIP registrar.
Quick tea β: If a REFER request is sent to a third SIP user agent, and it includes the Contact URI of a SIP WebSocket Client as the target in its Refer-To header field, that URI is only reachable by the third SIP UA if it's a globally routable URI. That's where GRUU (Globally Routable User Agent URI) comes in π It's the solution for those scenarios. It makes the incoming request from the third SIP user agent go to the SIP registrar, which then routes the request to the SIP WebSocket Client via the Outbound Edge Proxy π
B.1. SIP WebSocket Client Considerations
Real talk: the JavaScript stack in web browsers can't figure out the local transport address used for originating WebSocket connections π So a SIP WebSocket Client running in that environment can make up a domain name with a random token followed by the ".invalid" top-level domain name, as stated in [RFC2606] π§© It then uses that inside its Via and Contact headers.
Good news: the Contact URI provided by SIP UAs that request (and receive) Outbound support isn't used for routing requests to those UAs. So it's totally safe to set a random domain in the Contact URI hostport π«Ά
Both the Outbound and GRUU specifications require a SIP UA to include a Uniform Resource Name (URN) in a "+sip.instance" parameter of the Contact header, in the SIP REGISTER requests they send π The client device is responsible for generating or collecting a suitable value for this π₯
Now, in web browsers, it's hard to generate or collect a suitable URN value from the browser itself π So this scenario suggests that the value gets generated according to [RFC5626], Section 4.1, by the web application running in the browser the first time it loads the JavaScript SIP stack code. Then it gets stored as a cookie within the browser πͺπ
B.2. SIP WebSocket Server Considerations β¨
okay so bestie, in this scenario the SIP WebSocket Server is basically a SIP Outbound Edge Proxy π¦ which means it has to support Outbound [RFC5626] and Path [RFC3327]. main character energy for sure π
the proxy does loose routing and stays in the path of dialogs, just like [RFC3261] says π§ and honestly this part is so important bc if it didn't stay in the path, in-dialog requests would fail π SIP WebSocket Clients literally rely on their SIP WebSocket Server to send and receive all their SIP messages, so the server has to be there the whole time π«Ά
Authors' Addresses
Inaki Baz Castillo
Versatica
Barakaldo, Basque Country
Spain
EMail: ibc@aliax.net
Jose Luis Millan Villegas
Versatica
Bilbao, Basque Country
Spain
EMail: jmillan@aliax.net
Victor Pascual
Quobis
Spain
EMail: victor.pascual@quobis.com
π¦ where this page comes from
- ietf: rfc7118 2014-01
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms