SIP(Session Initiation Protocol,会话发起协议)是应用层的控制(信令)协议,用于创建、修改和终止与一个或多个参与者的会话(session)。这里的「会话」包括互联网电话呼叫、多媒体分发、多媒体会议。它不传输媒体本身——音视频走 RTP,SIP 只负责「谁来、在哪、怎么协商」。RFC 3261 第 1 章明确:SIP 是文本协议,使用 UTF-8 字符集,消息语法大量借鉴 HTTP/1.1,但SIP 不是 HTTP 的扩展。
RFC 3261 列出 SIP 的设计目标,理解这些目标才能理解它为什么长这样:
| 维度 | HTTP/1.1 | SIP/2.0 |
|---|---|---|
| 角色 | 浏览器=客户端,服务器=服务器 | UA = UAC + UAS,二者可互换角色 |
| 承载 | TCP 为主 | UDP / TCP / TLS / SCTP 皆可 |
| 版本 | HTTP/1.0、HTTP/1.1 可比较 | 固定 SIP/2.0,按字面比 |
| 消息边界 | 支持 chunked | 禁用 chunked,靠 Content-Length |
SIP 自底向上分四层,理解分层是理解「为什么某些头必须由事务层加、某些由传输层填」的关键:
RFC 3261 §6 定义了五类逻辑实体。它们都是逻辑角色,一个物理设备(比如一台软交换)可以同时是代理、注册、重定向服务器和定位服务——实现上可合并,逻辑上要分清。
| 实体 | RFC 章 | 职责 |
|---|---|---|
| UA(用户代理) | §8 | 会话的两端终点:UAC 发请求,UAS 回响应 |
| Proxy(代理) | §16 | 路由转发:确定下一跳、应用策略、认证 |
| Redirect(重定向) | §8.3 / §21.3 | 返回 3xx,告知客户端去哪找被叫 |
| Registrar(注册) | §10 | 处理 REGISTER,维护 AOR↔Contact 绑定 |
| Location(定位服务) | §10 / §16.5 | AOR → Contact 绑定的数据存储,被代理查询 |
| 术语 | 含义 |
|---|---|
| AOR(地址-of-记录) | 用户的逻辑公开地址(sip:user@domain),与设备解耦 |
| Contact(联系地址) | UA 当前实际可达 URI,AOR 与设备的桥梁 |
| Transaction(事务) | 请求 + 其全部响应;可靠性的基本单位 |
| Dialog(对话) | 两个 UA 的端到端持续关系;含 dialog ID / 路由集 |
| Call(呼叫) | 业务层概念,可含多条 Dialog |
| TU(事务用户) | 驱动事务的上一层逻辑(UA 核心 / 有状态代理) |
SIP 消息要么是客户端到服务器的请求,要么是服务器到客户端的响应。两者都由起始行 + 若干头字段 + 空行 + 可选消息体组成。起始行、每个头字段行、空行都必须以 CRLF 结尾;即使没有消息体,空行也必须存在。
请求以请求行开头,格式:Method SP Request-URI SP SIP-Version CRLF。元素间只允许单个 SP,不得有 LWS,不得有额外 CR/LF。
响应以状态行开头:SIP-Version SP Status-Code SP Reason-Phrase CRLF。Status-Code 是 3 位整数,首位决定类别;Reason-Phrase 给人看,客户端可忽略。
头字段格式 field-name: field-value,多个同名头可合并为逗号分隔列表(例外:WWW-Authenticate / Authorization / Proxy-Authenticate / Proxy-Authorization 不能合并,且可多次出现)。头字段可多行折叠(续行以 SP/HT 开头)。头名字大小写不敏感;除非定义另有说明,field-value、参数名、参数值大小写不敏感,但引号字符串大小写敏感。
Content-Type 给出;如经编码由 Content-Encoding 指示,否则省略。Content-Length 给出;UDP 上每个数据报承载一条完整消息,TCP 等流传输上靠 Content-Length 定位消息边界,且必须忽略起始行前的任何前导 CRLF。除 Content-Length 外,下列头字段几乎出现在每条请求里。悬停下表查看每个头的作用与取值规则:
| 头字段 | 由谁加 | 是否必须 | 作用 |
|---|---|---|---|
| Via | 每跳(UAC + 各代理) | 请求必须 m | 记录路径、匹配事务、指引响应返回 |
| Max-Forwards | UAC | 请求必须 m | 限制跳数防环;默认 70 |
| From | UAC | 请求必须 m | 发起者身份;携带 From-tag(dialog ID 的一部分) |
| To | UAC 写值,UAS 加 tag | 请求必须 m | 被叫身份;响应里加 To-tag(dialog ID 一部分) |
| Call-ID | UAC | 请求必须 m | 关联一组消息;dialog ID 组件之一;大小写敏感 |
| CSeq | UAC | 请求必须 m | 事务序号与方法;dialog 内必须 +1 递增 |
| Contact | UAC(INVITE/REGISTER) | INVITE 请求必须 m;REGISTER 必须 o | 本实例联系地址;INVITE 必含且唯一 |
RFC 3261 定义了六个方法;扩展方法由标准 Track RFC 另行定义(见 §17)。下面是六个标准方法的语义与关键点:
| 方法 | 用途 | 关键语义(照 RFC 3261) |
|---|---|---|
| INVITE | 建立 / 修改会话 | 带 SDP offer;唯一建 dialog 的请求;三次握手事务 |
| ACK | 确认 INVITE 响应 | 只配 INVITE;2xx 的 ACK 端到端、非 2xx 的属事务 |
| BYE | 终止会话 | dialog 内;终结呼叫 |
| CANCEL | 取消未决请求 | 同 branch 标识原事务;配 487 终结原请求 |
| REGISTER | 地址绑定(注册) | To=AOR;Contact=当前地址;写定位服务 |
| OPTIONS | 查询能力 / 保活 | 探测对端能力;200 OK 带 Allow |
状态码首位决定类别,后两位不参与分类。SIP/2.0 允许首位取值 1–6。
| 类别 | 含义 | 常见码(RFC 3261 §21 全列) |
|---|---|---|
| 1xx 临时 | 处理中 | 100 / 180 / 181 / 182 / 183 |
| 2xx 成功 | 成功 | 200 OK |
| 3xx 重定向 | 重定向 | 300 / 301 / 302 / 305 / 380 |
| 4xx 客户端错 | 请求有误 | 400/401/403/404/405/406/407/408/413/414/415/420/421/423/480/481/482/483/484/485/486/487/488/491/493 |
| 5xx 服务端错 | 服务器失败 | 500 / 501 / 502 / 503 / 504 / 505 / 513 |
| 6xx 全局失败 | 全局不可达 | 600 / 603 / 604 / 606 |
WWW-Authenticate,是用户-用户认证(被叫 UAS 挑战主叫);407 Proxy Authentication Required 配 Proxy-Authenticate,是代理-用户认证(代理挑战用户)。二者认证机制都用 HTTP Digest(§22)。§20 逐一定义头字段,「where」列说明它可出现在请求 (R) / 响应 (r) / 特定状态码后,「proxy」列说明代理可加(a)/改(m)/删(d)/必须可读(r)。下表浓缩自 §20 的 Table 2/3,给出每个头在六种方法(ACK/BYE/CAN/INV/OPT/REG)中的出现要求(m 必须 / o 可选 / c 从请求复制 / t 流式传输必须 / * 有消息体时必须 / - 不适用):
| 头字段 | where | proxy | 六方法要求 | 用途 |
|---|---|---|---|---|
| Accept(-Encoding/-Language) | R / 2xx / 415 | — | INV:o / OPT:m* / 415:c | 能力/编码/语言协商 |
| Alert-Info | R / 180 | ar | INV:o;180:ar | 替代振铃音 |
| Allow | R / r / 405 | — | INV:o / OPT:m* / 405:m | 支持的方法清单 |
| Authentication-Info | 2xx | — | INV/OPT/REG:o | Digest 双向认证 |
| Authorization | R | — | 各方法:o | 用户认证凭据 |
| Call-ID(i) | c | r | 全部:m | 消息组关联;dialog ID 组件 |
| Call-Info | R / 180 | ar | INV/OPT:o | 主被叫附加信息 |
| Contact(m) | R / 1xx / 2xx / 3xx | — | INV:m / 2xx:m / 3xx:o / REG:o | 联系地址;绑定/重定向 |
| Content-*(c/e/l) | — | (l 为 ar) | 有体:t/*;流式:l 必须 | 消息体元信息 |
| CSeq | c | r | 全部:m | 事务排序/标识 |
| Date | — | a | 各:o | 时间戳 |
| Error-Info | 300–699 | a | 各:o | 错误附加信息 |
| Expires | — | — | INV:o / REG:o | 过期时间 |
| From(f) | c | r | 全部:m | 发起者;dialog ID 组件 |
| In-Reply-To/Reply-To/Subject | R | — | INV:o | 呼叫关联/主题 |
| Max-Forwards | R | amr | 全部:m | 防环跳数 |
| Min-Expires | 423 | — | REG(423):m | 注册最小有效期 |
| MIME-Version | — | — | 各:o | MIME 版本 |
| Organization | — | ar | 各:o | 组织名 |
| Priority | R | ar | INV:o | 优先级 |
| Proxy-Authenticate/-Authorization | 407 / 401 / R | ar / dr | INV/OPT/REG:o(m@407) | 代理认证 |
| Proxy-Require | R | ar | 各:o | 强制代理支持选项 |
| Record-Route(r)/ Route(o) | R / 2xx,18x / R | ar / adr | INV/OPT:o;REG:- | 路径记录/路由集 |
| Require | — | ar | INV/OPT:c | 强制 UAS 支持选项 |
| Retry-After | 404,413,480,486,500,503,600,603 | — | 各:o | 重试建议 |
| Server | r | — | 各:o | 服务器标识 |
| Supported(k)/ Unsupported | R / 2xx / 420 | — | INV/OPT/REG:o(m*@2xx) | 支持/不支持选项 |
| Timestamp | — | — | 各:o | 时延测量 |
| To(t) | c(1) | r | 全部:m | 被叫;dialog ID 组件(远端 tag) |
| User-Agent | — | — | 各:o | UA 标识 |
| Via(v) | R / rc | amr / dr | 全部:m | 路径/事务匹配/响应返回 |
| Warning | r | — | 各:o | 警告信息 |
| WWW-Authenticate | 401 / 407 | ar | INV/OPT/REG:m(@401) | 用户认证挑战 |
当消息因 UDP MTU 限制可能过大时,可用缩写头名(语义不变,长/短形式可混用,实现必须都接受):
| 缩写 | 全称 | 缩写 | 全称 | |
|---|---|---|---|---|
a | Accept-Contact* | l | Content-Length | |
c | Content-Type | m | Contact | |
e | Content-Encoding | s | Subject | |
f | From | t | To | |
i | Call-ID | v | Via | |
k | Supported | u | Allow-Events* | |
o | Event* | * 非 RFC 3261 定义,由后续扩展(如 RFC 3840/6665)引入 | ||
i=Call-ID、m=Contact、e=Content-Encoding、l=Content-Length、c=Content-Type、f=From、s=Subject、t=To、v=Via。其余(a/k/o/u 等)来自后续扩展 RFC。SIP 与 SIPS URI 标识一个通信资源,可印在网页/名片/邮件里,含足以发起并维持会话的信息。SIPS 表示「安全联系该资源」——UAC 到该 URI 所属域之间必须用 TLS,之后由域策略决定域内安全机制。
| 组件 | 含义与规则 |
|---|---|
| user | 资源标识;可含 telephone-subscriber(建议 user=phone) |
| password | 语法允许但强烈不推荐(明文风险) |
| host | 目标主机(FQDN 或 IP);推荐 FQDN |
| port | 缺省 5060(sip)/ 5061(sips 或 TLS) |
| ;uri-parameters | transport/maddr/ttl/user/method/lr 等 |
| ?headers | 在 URI 里内联请求头(& 分隔) |
事务(transaction)= 一个请求 + 对其的所有响应(0+ 临时响应、≥1 最终响应)。它有客户端侧(发请求、收响应)与服务端侧(收请求、发响应),分别嵌入 UA 或有状态代理里。事务层是 SIP 可靠性的核心:在 UDP 上自实现重传、匹配、ACK。
| 定时器 | 取值 | 作用对象 / 含义 |
|---|---|---|
| T1 | 500 ms(默认) | RTT 估计;事务重传/超时的基准 |
| T2 | 4 s(默认) | 非 INVITE 重传间隔封顶 |
| T4 | 5 s(默认) | 网络清消息时间;K/I 定时器基准 |
| A | T1 → 翻倍 | INVITE 请求重传(UDP) |
| B | 64×T1 | INVITE 客户端事务超时 |
| D | 32s(UDP) / 0(可靠) | INVITE 客户端吸收响应重传 |
| E | T1 → min(2T1,T2) | 非 INVITE 请求重传(UDP) |
| F | 64×T1 | 非 INVITE 客户端事务超时 |
| G | T1 → min(2T1,T2) | INVITE 服务端重发最终响应(UDP) |
| H | 64×T1 | INVITE 服务端等 ACK 超时 |
| I | T4(UDP) / 0(可靠) | INVITE 服务端吸收多余 ACK |
| J | 64×T1(UDP) / 0(可靠) | 非 INVITE 服务端吸收请求重传 |
| K | T4(UDP) / 0(可靠) | 非 INVITE 客户端吸收响应重传 |
branch 与创建事务的请求顶层 Via branch 相同;② CSeq 的 method 与创建事务的请求 method 相同(因为 CANCEL 共享 branch,需靠 method 区分)。sent-by 相同(防不同客户意外/恶意重复 branch);③ method 相同,但 ACK 例外——其匹配的事务 method 是 INVITE。z9hG4bK 开头,故「全局唯一」可被直接信任;非魔数 branch(RFC 2543 兼容)则需回退用 Request-URI/To tag/From tag/Call-ID/CSeq/顶层 Via 全套匹配。传输层负责把消息送到下一跳。SIP 刻意支持多种传输,可靠性职责因传输而异:
| 传输 | 行为 | 可靠性职责 |
|---|---|---|
| UDP | 每数据报一条消息;事务层重传;建议 ≤1300B | 不可靠;事务层补 |
| TCP | 流式;Content-Length 分帧;忽略前导 CRLF | 可靠;事务层不重传 |
| TLS | sips 加密通道;端口 5061 | 可靠+加密 |
| SCTP | 面向消息;可靠;无需分帧 | 可靠 |
REGISTER 把AOR(To 头)绑定到当前 Contact,写入定位服务,供代理查询「这个用户现在在哪」。Request-URI 是注册服务器地址(不是被叫),From = 注册者。
| 操作 | 做法 | 说明 |
|---|---|---|
| 添加 / 刷新 | Contact: <sip:...>;expires=N | 绑定 AOR↔Contact;到期需刷新 |
| 移除 | Contact: * 配合 Expires: 0 | 注销全部 / 单条 |
| 获取 | 无 Contact 的 REGISTER | 查询当前绑定 |
| 优先级 | Contact: <sip:...>;q=0.7 | 多绑定分叉顺序 |
Dialog 是两个 UA 之间的端到端对等关系,仅由 INVITE 的 2xx 或 101–199(带 To tag)响应建立。它保存对话期内的路由集、序号、对端地址等状态。
| 环节 | route set 来源与顺序 |
|---|---|
| UAC 收到 2xx | Route set = 响应 Record-Route 逆序 |
| UAS 发 2xx | Route set = 请求 Record-Route 顺序 |
| dialog 内发请求 | 复用 route set;CSeq 必须 +1 |
任一方发 BYE(dialog 内请求,CSeq 递增)即终止 dialog;收到 BYE 的 UAS 回 200 OK 后 dialog 拆除。也可靠失败响应(如 408/481/503)或事务失败隐式终止。
下面是经典 SIP 梯形:主叫 Alice(atlanta.com)经出局/入局代理呼叫被叫 Bob(biloxi.com)。INVITE 带 SDP offer,200 OK 带 SDP answer,最后 ACK 确认。这正对应 RFC 3261 Figure 1 的消息流(此处简化为关键步骤)。
INVITE 消息体是 SDP offer(列出本端想用的媒体:音频/视频、编解码、地址、端口);200 OK 消息体是 answer(从 offer 中选兼容项)。规则(RFC 3264 §6):
代理是 SIP 网络的路由核心。按是否保存状态分两类:
| 类型 | 特点 |
|---|---|
| 有状态(Stateful) | 保存事务/dialog 状态;可认证、CANCEL、响应合并 |
| 无状态(Stateless) | 不保存状态;高吞吐;不能认证/CANCEL |
lr 参数正是为兼容 RFC 2543 的严格路由(会把 Request-URI 替换为 Route 第一个值)而设。重定向服务器不转发请求,而是回 3xx 响应,把「被叫当前地址」放在 Contact 里交给客户端,由客户端自己重新发请求到新地址。它是无状态的,不发起自己的事务。常见 3xx:
| 码 | 含义 | 用法 |
|---|---|---|
| 300 | 多选 | Contact 给多个候选 |
| 301 | 永久迁移 | 更新地址缓存 |
| 302 | 临时迁移 | 本次用新 Contact 重发 |
| 305 | 用代理 | 经 Contact 代理 |
| 380 | 替代服务 | Contact 给替代 |
CANCEL 取消一个仍在处理中的请求(典型:INVITE 已发但还没最终响应,主叫挂断)。关键点:
SIP 复用 HTTP 认证框架(RFC 2617),两种场景:
| 场景 | 挑战头 | 流程 |
|---|---|---|
| 用户-用户 | 401 + WWW-Authenticate | UAS 挑战;UAC 回 Authorization |
| 代理-用户 | 407 + Proxy-Authenticate | 代理挑战;UAC 回 Proxy-Authorization |
sips: URI 要求 UAC 到域边缘用 TLS,端口 5061;之后由域策略决定(可能仍走 TLS 或内部安全通道)。TLS 防窃听/中间人,但不解决「域内部是否可信」——它与 S/MIME 的端到端保护互补。
| 威胁(§26.1) | 说明与对策 |
|---|---|
| 注册劫持 | 认证注册;仅拥有者可改绑定 |
| 冒充服务器 | TLS/S/MIME/DNSSEC |
| 篡改消息体 | S/MIME 保护 SDP |
| 会话拆除 | dialog 内请求需正确 tag + 认证 |
| DoS / 放大 | 限重传/限速率/Max-Forwards |
RFC 3261 只定义六个方法,但明确允许扩展 RFC 增加新方法。以下是工程中常见、且已在标准 Track 落地的扩展方法:
| 方法 | RFC | 用途 |
|---|---|---|
| INFO | RFC 2976 | 通话中信息(DTMF 等) |
| REFER | RFC 3515 | 呼叫转接 |
| UPDATE | RFC 3311 | 早期修改会话(不建 dialog) |
| SUBSCRIBE / NOTIFY | RFC 6665 | 事件订阅/通知 |
| MESSAGE | RFC 3428 | 即时消息 |
| PRACK | RFC 3262 | 可靠临时响应确认 |
Supported / Require / Proxy-Require 协商:要求对端必须支持用 Require(不支持回 420);仅声明自己支持用 Supported。这正是 RFC 3261 §1「可扩展性」设计目标的落地机制。注意 REGISTER 的 Request-URI 是注册服务器(registrar.biloxi.com),而非被叫;To = AOR(bob@biloxi.com),Contact = 当前实际地址(192.0.2.4),Expires=3600 秒后绑定过期需刷新。
| 概念 | 一句话 |
|---|---|
| 端口 | sip: 5060(UDP/TCP/SCTP);sips: / TLS 5061 |
| 版本 | 字面 "SIP/2.0",发送必须大写 |
| 六方法 | INVITE / ACK / BYE / CANCEL / REGISTER / OPTIONS |
| 六必须头 | Via / Max-Forwards / From / To / Call-ID / CSeq(+建立 dialog 需 Contact) |
| branch cookie | 必须是 "z9hG4bK" 开头,全局唯一 |
| Max-Forwards | 默认 70 |
| 事务定时器基准 | T1=500ms, T2=4s, T4=5s;B/H=64·T1, D=32s, G/J=64·T1, K/I=T4 |
| dialog ID | Call-ID + 本地 tag + 远端 tag |
| From-tag / To-tag | UAC 加 From-tag;UAS 在响应加 To-tag |
| 事务 vs dialog | 事务=单请求可靠性单位;dialog=呼叫持续关系(含多事务) |
| 可靠性分工 | UDP 上事务层重传;TCP/TLS/SCTP 外包传输层 |
| 安全三件套 | sips/TLS + Digest 认证 + S/MIME |