> For the complete documentation index, see [llms.txt](https://hacktricks.xsx.tw/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacktricks.xsx.tw/network-services-pentesting/pentesting-voip/basic-voip-protocols/sip-session-initiation-protocol.md).

# SIP (Session Initiation Protocol)

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS红队专家）</strong></a><strong>！</strong></summary>

支持HackTricks的其他方式：

* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)！
* 获取[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们的独家[NFT](https://opensea.io/collection/the-peass-family)收藏品
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>

## 基本信息

SIP（会话初始协议）是一种广泛用于在IP网络上建立、修改和终止多媒体会话（包括语音、视频和即时消息）的**信令和呼叫控制协议**。由**互联网工程任务组（IETF）开发，SIP在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穿越和防火墙问题时，配置和管理SIP可能会复杂。然而，其多功能性、可扩展性和在整个行业的广泛支持使其成为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**：用户代理使用REGISTER方法向SIP注册服务器**注册其当前位置**。REGISTER方法有助于维护用户的SIP URI与其当前IP地址之间的最新映射，从而实现呼叫路由和传递。

{% hint style="warning" %}
请注意，要给某人打电话**不需要使用REGISTER**。\
但是，为了执行**INVITE**，呼叫方可能需要**先进行身份验证**，否则将收到\*\*`401 Unauthorized`\*\*响应。
{% endhint %}

除了这些核心方法外，还有**其他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 <sip:jdoe@example.com>
From: Jane Smith <sip:jsmith@example.org>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 INVITE
Contact: <sip:jsmith@pc33.example.com>
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
```

<details>

<summary>每个参数的解释</summary>

1. **Request-Line**: `INVITE sip:jdoe@example.com SIP/2.0` - 这一行指示了方法（INVITE）、请求URI（sip:<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 <sip:jdoe@example.com>` - To头部指定了呼叫的接收者，包括其显示名称（John Doe）和SIP URI（sip:<jdoe@example.com>）。
5. **From**: `From: Jane Smith <sip:jsmith@example.org>;tag=1928301774` - From头部指定了呼叫的发送者，包括其显示名称（Jane Smith）和SIP URI（sip:<jsmith@example.org>）。"tag"参数用于唯一标识发送者在对话中的角色。
6. **Call-ID**: `Call-ID: a84b4c76e66710` - Call-ID头部唯一标识了两个用户代理之间的呼叫会话。
7. **CSeq**: `CSeq: 314159 INVITE` - CSeq头部包含一个序列号和请求中使用的方法。它用于将响应与请求匹配，并检测消息的乱序。
8. **Contact**: `Contact: <sip:jsmith@pc33.example.com>` - 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. **消息体**: 消息体包含了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）的属性。

</details>

### 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 <sip:alice@example.com>;tag=565656
To: Alice <sip:alice@example.com>
Call-ID: 1234567890@192.168.1.100
CSeq: 1 REGISTER
Contact: <sip:alice@192.168.1.100:5060>;expires=3600
Expires: 3600
Content-Length: 0
```

这个初始的REGISTER消息是由UA（Alice）发送到注册服务器。它包括重要信息，如期望的注册持续时间（Expires），用户的SIP URI（sip:<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 <sip:alice@example.com>;tag=565656
To: Alice <sip:alice@example.com>;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 未授权"的消息，其中包含一个"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 <sip:alice@example.com>;tag=565656
To: Alice <sip:alice@example.com>
Call-ID: 1234567890@192.168.1.100
CSeq: 2 REGISTER
Contact: <sip:alice@192.168.1.100:5060>;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 <sip:alice@example.com>;tag=565656
To: Alice <sip:alice@example.com>;tag=7878744
Call-ID: 1234567890@192.168.1.100
CSeq: 2 REGISTER
Contact: <sip:alice@192.168.1.100:5060>;expires=3600
Expires: 3600
Content-Length: 0
```

在注册服务器验证提供的凭据后，**它发送一个“200 OK”响应以指示注册成功**。响应包括注册的联系信息和注册的到期时间。此时，用户代理（Alice）已成功注册到SIP注册服务器，可以将针对Alice的传入SIP请求路由到适当的联系地址。

### 通话示例

<figure><img src="/files/YNR2yQ1sJZADBUXS3LYB" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
没有提到，但用户B需要在能够接收呼叫之前向Proxy 2发送**REGISTER消息**。
{% endhint %}
