# SIP (Session Initiation Protocol) {{#include ../../../banners/hacktricks-training.md}} ## 基本信息 SIP (会话发起协议) 是一种**信令和呼叫控制协议**,广泛用于在 IP 网络上建立、修改和终止多媒体会话,包括语音、视频和即时消息。SIP 由**互联网工程任务组 (IETF)** 开发,定义在**RFC 3261**中,已成为 VoIP 和统一通信的事实标准。 SIP 的一些关键特性包括: 1. **基于文本的协议**:SIP 是一种基于文本的协议,使其易于阅读和调试。它基于请求-响应模型,类似于 HTTP,并使用 INVITE、ACK、BYE 和 CANCEL 等方法来控制呼叫会话。 2. **可扩展性和灵活性**:SIP 具有高度的可扩展性,可用于小规模部署以及大型企业和运营商级环境。它可以轻松扩展新功能,使其适应各种用例和需求。 3. **互操作性**:SIP 的广泛采用和标准化确保了不同设备、应用程序和服务提供商之间更好的互操作性,促进了各种平台之间的无缝通信。 4. **模块化设计**:SIP 与其他协议(如**RTP (实时传输协议)**用于媒体传输和**SDP (会话描述协议)**用于描述多媒体会话)协同工作。这种模块化设计允许更大的灵活性和与不同媒体类型和编解码器的兼容性。 5. **代理和重定向服务器**:SIP 可以使用代理和重定向服务器来促进呼叫路由,并提供呼叫转移、呼叫转接和语音邮件服务等高级功能。 6. **状态和即时消息**:SIP 不仅限于语音和视频通信。它还支持状态和即时消息,使广泛的统一通信应用成为可能。 尽管有许多优点,SIP 的配置和管理可能很复杂,特别是在处理 NAT 穿越和防火墙问题时。然而,它的多功能性、可扩展性和行业广泛支持使其成为 VoIP 和多媒体通信的热门选择。 ### SIP 方法 在**RFC 3261**中定义的核心 SIP 方法包括: 1. **INVITE**:用于**发起新会话(呼叫)**或修改现有会话。INVITE 方法携带会话描述(通常使用 SDP)以通知接收方有关提议会话的详细信息,例如媒体类型、编解码器和传输协议。 2. **ACK**:发送以**确认收到**对 INVITE 请求的最终响应。ACK 方法通过提供端到端确认来确保 INVITE 事务的可靠性。 3. **BYE**:用于**终止已建立的会话(呼叫)**。BYE 方法由会话中的任一方发送,以表示他们希望结束通信。 4. **CANCEL**:发送以**取消待处理的 INVITE** 请求,直到会话建立。CANCEL 方法允许发送方在改变主意或接收方没有响应时中止 INVITE 事务。 5. **OPTIONS**:用于**查询 SIP 服务器或用户代理的能力**。OPTIONS 方法可以发送以请求有关支持的方法、媒体类型或其他扩展的信息,而无需实际建立会话。 6. **REGISTER**:由用户代理用于**向 SIP 注册服务器注册其当前位置**。REGISTER 方法有助于维护用户的 SIP URI 和其当前 IP 地址之间的最新映射,从而实现呼叫路由和交付。 > [!WARNING] > 请注意,呼叫某人**不需要使用 REGISTER**。\ > 然而,可能需要在执行**INVITE**之前,呼叫者需要**进行身份验证**,否则将收到**`401 Unauthorized`** 响应。 除了这些核心方法外,还有**在其他 RFC 中定义的几种 SIP 扩展方法**,例如: 1. **SUBSCRIBE**:在 RFC 6665 中定义,SUBSCRIBE 方法用于**请求有关特定资源状态的通知**,例如用户的状态或呼叫状态。 2. **NOTIFY**:同样在 RFC 6665 中定义,NOTIFY 方法由服务器发送,以**通知订阅的用户代理**有关监控资源状态的变化。 3. **REFER**:在 RFC 3515 中定义,REFER 方法用于**请求接收方执行转接或引用第三方**。这通常用于**呼叫转接**场景。 4. **MESSAGE**:在 RFC 3428 中定义,MESSAGE 方法用于**在 SIP 用户代理之间发送即时消息**,使得在 SIP 框架内进行基于文本的通信成为可能。 5. **UPDATE**:在 RFC 3311 中定义,UPDATE 方法允许**在不影响现有对话状态的情况下修改会话**。这对于在进行中的呼叫中更新会话参数(例如编解码器或媒体类型)非常有用。 6. **PUBLISH**:在 RFC 3903 中定义,PUBLISH 方法由用户代理用于**向服务器发布事件状态信息**,使其对其他相关方可用。 ### SIP 响应代码 - **1xx (临时响应)**:这些响应表示请求已被接收,服务器正在继续处理。 - 100 Trying: 请求已被接收,服务器正在处理。 - 180 Ringing: 被叫方正在被提醒,将接听电话。 - 183 Session Progress: 提供有关呼叫进展的信息。 - **2xx (成功响应)**:这些响应表示请求已成功接收、理解和接受。 - 200 OK: 请求成功,服务器已满足请求。 - 202 Accepted: 请求已被接受处理,但尚未完成。 - **3xx (重定向响应)**:这些响应表示需要进一步的操作来满足请求,通常是通过联系替代资源。 - 300 Multiple Choices: 有多个可用选项,用户或客户端必须选择一个。 - 301 Moved Permanently: 请求的资源已分配新的永久 URI。 - 302 Moved Temporarily: 请求的资源暂时可在不同的 URI 上使用。 - 305 Use Proxy: 请求必须发送到指定的代理。 - **4xx (客户端错误响应)**:这些响应表示请求包含错误的语法或服务器无法满足请求。 - 400 Bad Request: 请求格式错误或无效。 - 401 Unauthorized: 请求需要用户身份验证。 - 403 Forbidden: 服务器理解请求但拒绝满足。 - 404 Not Found: 请求的资源在服务器上未找到。 - 408 Request Timeout: 服务器在准备等待的时间内未收到完整请求。 - 486 Busy Here: 被叫方当前忙碌,无法接听电话。 - **5xx (服务器错误响应)**:这些响应表示服务器未能满足有效请求。 - 500 Internal Server Error: 服务器在处理请求时遇到错误。 - 501 Not Implemented: 服务器不支持满足请求所需的功能。 - 503 Service Unavailable: 服务器当前无法处理请求,因维护或过载。 - **6xx (全局失败响应)**:这些响应表示请求无法被任何服务器满足。 - 600 Busy Everywhere: 呼叫的所有可能目的地都忙。 - 603 Decline: 被叫方不愿意参与呼叫。 - 604 Does Not Exist Anywhere: 请求的资源在网络中不可用。 ## 示例 ### SIP INVITE 示例 ``` INVITE sip:jdoe@example.com SIP/2.0 Via: SIP/2.0/UDP pc33.example.com;branch=z9hG4bK776asdhds Max-Forwards: 70 To: John Doe From: Jane Smith ;tag=1928301774 Call-ID: a84b4c76e66710 CSeq: 314159 INVITE Contact: User-Agent: ExampleSIPClient/1.0 Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO Content-Type: application/sdp Content-Length: 142 v=0 o=jsmith 2890844526 2890842807 IN IP4 pc33.example.com s=- c=IN IP4 pc33.example.com t=0 0 m=audio 49170 RTP/AVP 0 a=rtpmap:0 PCMU/8000te ```
每个参数解释 1. **Request-Line**: `INVITE sip:jdoe@example.com SIP/2.0` - 该行指示方法(INVITE)、请求URI(sip:[jdoe@example.com](mailto:jdoe@example.com))和SIP版本(SIP/2.0)。 2. **Via**: `Via: SIP/2.0/UDP pc33.example.com;branch=z9hG4bK776asdhds` - Via头指定传输协议(UDP)和客户端地址(pc33.example.com)。"branch"参数用于循环检测和事务匹配。 3. **Max-Forwards**: `Max-Forwards: 70` - 此头字段限制请求可以被代理转发的次数,以避免无限循环。 4. **To**: `To: John Doe ` - To头指定通话的接收者,包括他们的显示名称(John Doe)和SIP URI(sip:[jdoe@example.com](mailto:jdoe@example.com))。 5. **From**: `From: Jane Smith ;tag=1928301774` - From头指定通话的发送者,包括他们的显示名称(Jane Smith)和SIP URI(sip:[jsmith@example.org](mailto:jsmith@example.org))。"tag"参数用于唯一标识发送者在对话中的角色。 6. **Call-ID**: `Call-ID: a84b4c76e66710` - Call-ID头唯一标识两个用户代理之间的通话会话。 7. **CSeq**: `CSeq: 314159 INVITE` - CSeq头包含一个序列号和请求中使用的方法。它用于将响应与请求匹配并检测乱序消息。 8. **Contact**: `Contact: ` - Contact头提供发送者的直接路径,可用于后续请求和响应。 9. **User-Agent**: `User-Agent: ExampleSIPClient/1.0` - User-Agent头提供有关发送者的软件或硬件的信息,包括其名称和版本。 10. **Allow**: `Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO` - Allow头列出发送者支持的SIP方法。这有助于接收者了解在通信中可以使用哪些方法。 11. **Content-Type**: `Content-Type: application/sdp` - Content-Type头指定消息体的媒体类型,在这种情况下为SDP(会话描述协议)。 12. **Content-Length**: `Content-Length: 142` - Content-Length头指示消息体的大小(以字节为单位)。 13. **Message Body**: 消息体包含SDP会话描述,其中包括有关媒体类型、编解码器和提议会话的传输协议的信息。 - `v=0` - 协议版本(SDP的版本为0) - `o=jsmith 2890844526 2890842807 IN IP4 pc33.example.com` - 发起者和会话标识符 - `s=-` - 会话名称(单个连字符表示没有会话名称) - `c=IN IP4 pc33.example.com` - 连接信息(网络类型、地址类型和地址) - `t=0 0` - 时间信息(开始和停止时间,0 0表示会话没有边界) - `m=audio 49170 RTP/AVP 0` - 媒体描述(媒体类型、端口号、传输协议和格式列表)。在这种情况下,它指定使用RTP/AVP(实时传输协议/音频视频配置文件)和格式0(PCMU/8000)的音频流。 - `a=rtpmap:0 PCMU/8000` - 属性将格式(0)映射到编解码器(PCMU)及其时钟频率(8000 Hz)。
### SIP REGISTER 示例 REGISTER方法用于会话发起协议(SIP),允许用户代理(UA),例如VoIP电话或软电话,**向SIP注册服务器注册其位置**。此过程使服务器知道**将传入的SIP请求路由到注册用户的地方**。注册服务器通常是SIP代理服务器或专用注册服务器的一部分。 以下是涉及REGISTER身份验证过程的SIP消息的详细示例: 1. 从UA到注册服务器的初始**REGISTER**请求: ```yaml REGISTER sip:example.com SIP/2.0 Via: SIP/2.0/UDP 192.168.1.100:5060;branch=z9hG4bK776asdhds Max-Forwards: 70 From: Alice ;tag=565656 To: Alice Call-ID: 1234567890@192.168.1.100 CSeq: 1 REGISTER Contact: ;expires=3600 Expires: 3600 Content-Length: 0 ``` 此初始 REGISTER 消息由 UA(Alice)发送到注册服务器。它包含重要信息,例如所需的注册持续时间(Expires)、用户的 SIP URI(sip:[alice@example.com](mailto:alice@example.com))和用户的联系地址(sip:alice@192.168.1.100:5060)。 2. **401 Unauthorized** 来自注册服务器的响应: ```css cssCopy codeSIP/2.0 401 Unauthorized Via: SIP/2.0/UDP 192.168.1.100:5060;branch=z9hG4bK776asdhds From: Alice ;tag=565656 To: Alice ;tag=7878744 Call-ID: 1234567890@192.168.1.100 CSeq: 1 REGISTER WWW-Authenticate: Digest realm="example.com", nonce="abcdefghijk", algorithm=MD5, qop="auth" Content-Length: 0 ``` 注册服务器以“401 Unauthorized”消息响应,其中包含“WWW-Authenticate”头。该头包含UA进行身份验证所需的信息,例如**身份验证域、nonce和算法**。 3. 带有身份验证凭据的REGISTER请求: ```vbnet REGISTER sip:example.com SIP/2.0 Via: SIP/2.0/UDP 192.168.1.100:5060;branch=z9hG4bK776asdhds Max-Forwards: 70 From: Alice ;tag=565656 To: Alice Call-ID: 1234567890@192.168.1.100 CSeq: 2 REGISTER Contact: ;expires=3600 Expires: 3600 Authorization: Digest username="alice", realm="example.com", nonce="abcdefghijk", uri="sip:example.com", response="65a8e2285879283831b664bd8b7f14d4", algorithm=MD5, cnonce="lmnopqrst", qop=auth, nc=00000001 Content-Length: 0 ``` UA发送另一个REGISTER请求,这次包括**"Authorization"头,带有必要的凭据,如用户名、域、随机数和使用提供的信息和用户密码计算的响应值**。 这就是**Authorization响应**的计算方式: ```python import hashlib def calculate_sip_md5_response(username, password, realm, method, uri, nonce, nc, cnonce, qop): # 1. Calculate HA1 (concatenation of username, realm, and password) ha1_input = f"{username}:{realm}:{password}" ha1 = hashlib.md5(ha1_input.encode()).hexdigest() # 2. Calculate HA2 (concatenation of method and uri) ha2_input = f"{method}:{uri}" ha2 = hashlib.md5(ha2_input.encode()).hexdigest() # 3. Calculate the final response value (concatenation of h1, stuff and h2) response_input = f"{ha1}:{nonce}:{nc}:{cnonce}:{qop}:{ha2}" response = hashlib.md5(response_input.encode()).hexdigest() return response # Example usage username = "alice" password = "mysecretpassword" realm = "example.com" method = "REGISTER" uri = "sip:example.com" nonce = "abcdefghijk" nc = "00000001" cnonce = "lmnopqrst" qop = "auth" response = calculate_sip_md5_response(username, password, realm, method, uri, nonce, nc, cnonce, qop) print(f"MD5 response value: {response}") ``` 4. **成功注册** 来自注册服务器的响应: ```yaml SIP/2.0 200 OK Via: SIP/2.0/UDP 192.168.1.100:5060;branch=z9hG4bK776asdhds From: Alice ;tag=565656 To: Alice ;tag=7878744 Call-ID: 1234567890@192.168.1.100 CSeq: 2 REGISTER Contact: ;expires=3600 Expires: 3600 Content-Length: 0 ``` 在注册服务器验证提供的凭据后,**它发送一个 "200 OK" 响应以指示注册成功**。响应包括注册的联系信息和注册的过期时间。此时,用户代理(Alice)已成功注册到SIP注册服务器,针对Alice的传入SIP请求可以路由到适当的联系地址。 ### 呼叫示例
> [!NOTE] > 虽然没有提到,但用户B需要在能够接听电话之前向代理2发送**REGISTER消息**。 {{#include ../../../banners/hacktricks-training.md}}