飞信的 SIP 协议分析
進到新的團隊后,我的項目是為省級部門做一套企業級 IM 工具,這個工具同時和我們做的機構管理網站后臺交互,為用戶提供一套機構人員查詢和交流的桌面訪問入口。最近的任務是重新設計 IM 通信協議,項目擬化在 飛鴿傳書 (IpMsg) 的協議上改造,加入跨域和互聯網支持,因為默認的飛鴿協議只能在三級網絡設備之下的網段內通信。我準備在 飛鴿 和 中國電信的飛信 (Fetion) 的協議上研究一番,因為飛信是基于 SIP 協議的,和飛鴿相比 SIP 協議規格是開放的,又是類似 HTTP 的文本化協議,分析起來較容易,加上之前也搞過關于 SIP 的東西,覺得比較好上手,于是就從它開始了。
下面的協議分析參考了 nathan 的 Fetion 協議分析 系列,原文一共 10 篇,作者從 飛信的協議類型開始,講述了包括 飛信協議所支持的 SIP 方法和消息頭域 等各方面。在此佩服作者 nathan 的分析能力和毅力,畢竟這是一個耗時間的活。我這里照著原文的思路用工具分析了幾遍,對原文稍加刪改,把重點內容羅列如下:
?
-
飛信的協議類型
-
飛信的配置文件和服務器地址
-
飛信的配置文件和用戶密碼的加密方法
-
飛信協議支持的 SIP 方法及消息頭域
-
飛信的文本消息聊天交互過程
-
飛信手機語聊的 SIP 交互過程
-
飛信登錄時的身份驗證
飛信的協議類型??
1. HTTP 進行獲取系統配置、更新程序、注冊用戶。
2. HTTPS 進行登錄時密碼驗證。
3. 用戶通信時(用戶發消息、發短信),協議是 SIP,但不是標準的,稱為 SIP-C。
飛信的 SIP 協議承載有兩種,TCP、HTTP:
1. TCP 承載:連接服務器的 8080 端口,這時在客戶端的“網絡設置”中顯示的是“TCP 直接連接”,SIP 信令直接就放在 TCP 的包中。
2. HTTP承載:連接服務器的 80 端口,采用 POST 方式,將信令包在 POST 請求中,這時在客戶端的“網絡設置”中顯示的是“HTTP 直接連接”。
飛信的配置文件和服務器地址??
飛信工作時連的是 221.130.45.203 這個服務器,這個IP地址從哪來的呢?會變嗎?
飛信在開始時解析過一次域名:nav.fetion.com.cn,這個域名的 IP 是 221.130.45.201。
既然只解析過 nav.fetion.com.cn,那么 221.130.45.203 這個工作服務器 (SIP Proxy Server) 地址,就應該是nav.fetion.com.cn 返回來的了。確實是,但只是新安裝的飛信第一次登錄時返回,并保存在了本地。后面再登錄時,如果版本不更新,是不會再返回這些系統配置信息的。
飛信本地配置文件在 %USERPROFILE%/Application/Fetion 目錄下。這個目錄下有 configuration.dat 和飛信的用戶目錄,每個飛信用戶目錄下有 configuration.dat、contacts.dat、userinfo.dat 這三個配置文件,看名字就知道是與用戶相關的系統配置文件、好友列表文件、用戶的個人信息文件。
這些 XML 配置文件內容是經過變換的,可以通過下面兩個辦法知道里面的內容(另外后面章節還說明了變化的方法,和解密成明文的工具):
修改 FetionFx.exe 文件。用 ildasm 將FeionFX.exe 反匯編,將其中的 Imps.Client.Pc.PersistentManager.EncodeMode1 和 Imps.Client.Pc.PersistentManager.DecodeMode1 這兩個函數改掉,將這兩個函數體改成以下內容:
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
即立即將參數返回。然后再用 ilasm工具重新匯編生成 FetionFX.exe 文件,覆蓋掉以前那個,然后再運行飛信,所有配置文件就不會再加密了。
構造一個請求,發給 nav.fetion.com.cn。請求的內容很簡單,取系統配置的請求過程是:
(1). 請求:
local:port → 221.130.45.201:80
POST /nav/getsystemconfig.aspx HTTP/1.1
User-Agent: IIC2.0/PC 2.1.0.0
Host: nav.fetion.com.cn
Content-Length: 233
Connection: Keep-Alive
(2). 響應:
xxx.xxx.xxx.xxx:xxxx ← 221.130.45.201:80
HTTP/1.1 100 Continue
(3). 再請求:
local:port → 221.130.45.201:80
POST Content:
查看源代碼 打印幫助| <config> |
| ????<user mobile-no="139xxxxxxxx" /> |
| ????<client type="PC" version="2.1.0.0" platform="W5.1" /> |
| ????<servers version="12" /> |
| ????<service-no version="1" /> |
| ????<parameters version="4" /> |
| ????<hints version="4" /> |
| ????<http-applications version="5" /> |
| </config> |
將以上內容中的從 servers version 開始的 version 全置為 "0",服務器就會返回配置信息。配置信息是 UTF-8 編碼的。用 nc (netcat) 就可構造一個 HTTP POST 請求。
方法 1,可以查看和修改所有配置信息;方法 2 僅能查看系統配置信息。
與服務器地址相關的信息在飛信用戶目錄下的 configuration.dat 中,其明文如下:
查看源代碼 打印幫助| 1 | <sipc-proxy>221.130.45.203:8080</sipc-proxy>?????????????????? TCP 承載時的服務器地址 |
| 2 | <http-tunnel>HTTP://221.130.45.203/ht/sd.aspx</http-tunnel>??? HTTP 承載時的入口地址 |
| 3 | <get-pic-code>HTTP://221.130.45.201/nav/GetPicCode.aspx</get-pic-code>??? 注冊時,取驗證代碼圖片的 URL |
| 4 | <get-system-status>HTTP://221.130.45.201/nav/GetSystemStatus.aspx</get-system-status>??? 取系統狀態 |
這個配置信息放到飛信用戶目錄下是有原因的:SIP 能夠支持,登錄的服務器是可以分用戶群的,不同的用戶可以登錄不同的 Proxy,每個飛信用戶(手機)可以分別登錄到本省的 Proxy,就如同手機和電話網絡一樣。
用戶的密碼保存在 Application Data/Fetion 目錄下的 configuration.dat 中,這個密碼明文進行了加密(三重 DES,后面有說明,并給出解密方法)。
飛信的配置文件和用戶密碼的加密方法??
飛信配置文件的變換方法
飛信的配置文件其實不是加密,只是進行了一下變換。這種變換的編碼方法是:將原來的 XML 文本 (UTF-8) 進行壓縮,然后將壓縮后的結果進行 BASE64 編碼,編碼后的結果作為 XML 的 DocumentElement 的值,同時在 XML 的 DocumentElement 的 Attributes 中,加上 StoreMode=1。
壓縮采用的是標準 GZIP 算法,飛信用的是 .NET 的類庫 System.IO.Compression.GZipStream。
nathan 寫了一個工具 FetionCfgEditor 可以打開編輯這里的文件。
可以用這個修改飛信的群發短信的人數限制。目前,飛信群發短信時只能發給 8 個人,可以用 FetionCfgEditor 打開 configuration.dat,然后修改:<batch-sms-max-receivers>8</batch-sms-max-receivers>
飛信用戶密碼的加密方法
可以從 configuration.dat 得到用戶的密碼,這個是用 TripleDES 加密過的密碼,飛信使用 .NET 的 System.Security.Cryptography。
TripleDES 是對稱加密算法,只要知道 KEY 和 IV 就可以將其解密。
IV 在飛信中是固定的值。
KEY 的算法是:取當前用戶的 Windows SID,表示成字符形式 "S-1-5-xx-xxxxxxxxx-xxxxxxxxx...",求這個字串的MD5,KEY 即為這個字符串的 MD5 散列值。
飛信協議支持的 SIP 方法及消息頭域??
飛信所使用的協議版本標記是 "SIP-C/2.0",協議棧中標記的版權信息是 "Copyright (c) 2004-2006 China Mobile Limited. All rights reserved."。飛信對標準 SIP 協議 (RFC3261) 作了改動,是非標準的 SIP 協議。另外,飛信的設計者來自微軟,所以可以參考微軟的實時通信協議:Microsoft Real-Time Communications: Protocols and Technologies。
飛信的 SIP-C/2.0 協議中用到的頭域有:
全稱 飛信的縮寫 Authorization A Call-ID I Contact M ContentEncoding E ContentLength L ContentType C CSeq Q Date D EndPoints EP Event N Expires X From F MessageID XI ReferredBy RB ReferTo RT Require RQ RosterManager RM Source SO Supported K To T Unsupported UK WWWAuthenticate W以上有些頭域在 RFC3261 中沒有定義,其它 SIP 相關協議草案中有定義,如 Event。
消息體通過是用 SDP 協議 (RFC2327) 描述的,當然也可以是直接文本或 XML,如果是 SDP,按照協議應該由頭部的 Content-Type (MIME) 來決定,但飛信不是。
飛信所支持的 SIP Request Method 有包括:
-
ACK | A 方法
在飛信 SIP-C/2.0 中,縮寫為 A,用以 Session 發起方向 SIP Proxy 確認會話建立。
以下是一個 ACK 消息:
查看源代碼 打印幫助A fetion.com.cn SIP-C/2.0 I: 16 Q: 1 A T: sip:987654321@fetion.com.cn;p=1234 F: 123456789 其中 123456789 是發起方 (From) 的 SIP 地址,這個沒按 SIP 標準來表達,只是用了一個飛信號碼。
而接收目標地址 (To) 的 SIP 地址是完全的 SIP 地址 (SIP/SIPS URI)。SIP/SIPS URI 的規范參考 RFC3261 19 節。
-
BENOTIFY | BN 方法
這不是個標準的 SIP 方法,既沒在 RFC 中定義,也沒出現在 IETF 的協議草案中,這是微軟在其 LCS 中定義的:
From: MSDN
BENOTIFY ("best effort" notify) enhances server performance by eliminating the response requirement. Otherwise, a BENOTIFY request has the same behavior as NOTIFY. Applications that require NOTIFY support need to implement similar processing for BENOTIFY."
BENotify 是個不需要回復的 NOTIFY,微軟擴展出這個方法是為了支持大量用戶。以下是飛信的一個 BENotify 消息,表示用戶 987654321 的在線狀態的變化:
查看源代碼 打印幫助BN 123456789 SIP-C/2.0 Q: 13 BN N: presence X: xxxx I: 9 L: xxx ?? <events><event type="PresenceChanged"><presence uri="sip:987654321@fetion.com.cn;p=xxxx"><basic value="100" device-id="PCCL025722" device-type="PC" device-caps="simple-im,im-session,temp-group" /></presence></event></events> -
BYE | B 方法
以下是一個 BYE 的請求消息,用以結束會話:
查看源代碼 打印幫助B fetion.com.cn SIP-C/2.0 F: 123456789 I: 11 Q: 2 B T: sip:987654321@fetion.com.cn;p=1234 -
CANCEL | C 方法
用以取消正在進行中的 INVITE 請求。
-
INFO | IN 方法
用以在 SIP 協議中支持應用相關的控制信息,飛信傳文件時,用到了這個方法。這是 RFC 中的一個擴展。以下是一個 INFO 方法的消息:
查看源代碼 打印幫助IN fetion.com.cn SIP-C/2.0 F: 123456789 I: 22 Q: 3 IN T: sip:987654321@fetion.com.cn;p=1234 L: 266 ?? <action type="share-content" method="request"><transmit type="relay" session-id="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" /><file name="xxxxxx.xx" size="xxx" url="HTTP://221.130.45.206/hds/RamRelayDownloadShareContent.aspx?FileUri=xxxxxxxxxxxxx" /></action> -
INVITE | I 方法
這是用發起會話建立過程的 SIP 方法。以下是飛信的 INVITE 方法的一個協議消息,表示用戶 123456789 要求和 987654321 建立會話,準備進行文本消息的通信:
查看源代碼 打印幫助I fetion.com.cn SIP-C/2.0 F: 123456789 I: 16 Q: 1 I T: sip:987654321@fetion.com.cn;p=1234 K: text/html-fragment K: multiparty L: 137 ?? v=0 o=-0 0 IN xxx.xxx.xxx.xxx:xxxx s=session c=IN IP4 xxx.xxx.xxx.xxx:xxxx t=0 0 m=message 1769 sip sip:123456789@fetion.com.cn;p=xxxx -
MESSAGE | M 方法
這是一個標準的 SIP 擴展,用以支持即時消息。以下是飛信的一個 MESSAGE 消息,用戶 123456789 向用戶 987654321 發消息說“Hello!你好”:
查看源代碼 打印幫助M fetion.com.cn SIP-C/2.0 F: 123456789 I: 16 Q: 2 M T: sip:987654321@fetion.com.cn;p=1972 C: text/html-fragment K: SaveHistory L: 121 ?? <Font Face='Arial' Color='-16777216' Size='9'>Hello!</Font><Font Face='SimSun' Color='-16777216' Size='12'>你好</Font> -
NEGOTIATE | NEG 方法
這是一個擴展 SIP 方法,用以在會話建立 (INVITE) 前協商會話相關的參數。
-
NOTIFY | N 方法
這是一個擴展 SIP 方法 (RFC3265)。消息見前面的 BENOTIFY。這個消息是需要進行回復的。
-
OPTIONS | O 方法
標準的 SIP 方法,用來查詢對端或服務器的能力。比如了解對方支持什么編碼類型。在飛信傳文件時使用了以下消息:
查看源代碼 打印幫助O fetion.com.cn SIP-C/2.0 F: 123456789 I: 22 Q: 2 O K: ShareContent T: sip:987654321@fetion.com.cn;p=xxxx -
REFER | REF 方法
這是一個擴展 SIP 方法,其功能是要求接受方通過使用在請求中提供的聯系地址信息聯系第三方。
-
REGISTER | R 方法
這是 SIP 標準方法,用來向服務器登記。如以下飛信在注冊時發出的消息:
查看源代碼 打印幫助R fetion.com.cn SIP-C/2.0 F: 123456789 I: 1 Q: 2 R A: Digest response="xxxxxxxxxxxxxxxxxxxxxxxxxx",cnonce="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" L: 147 ?? <args><device type="PC" version="131" /><caps value="simple-im;im-session;temp-group" /><events value="contact;permission;system-message" /></args> -
SERVICE | S 方法
這是一個擴展 SIP 方法,用來向 SIP 服務器請求額外的服務。如以下飛信發出的消息:
(1). 飛信客戶端要求服務器返回用戶信息
查看源代碼 打印幫助S fetion.com.cn SIP-C/2.0 F: 123456789 I: 2 Q: 1 S N: GetPersonalInfo L: 172 ?? <args><personal version="11" attributes="all" /><services version="11" attributes="all" /><config version="109" attributes="all" /><mobile-device attributes="all" /></args> (2). 通過服務器開始飛信語聊
查看源代碼 打印幫助S fetion.com.cn SIP-C/2.0 F: 123456789 I: 12 Q: 1 S N: StartVoiceChat L: 103 ?? <args><voice-chat begin-date="2007-01-01 00:00:00.1234" /><users><user sid="987654321" /></users></args> -
SUBSCRIBE | SUB 方法
這是一個擴展 SIP 方法 (RFC3265)。這個方法被用來向服務器訂閱事件異步通知。服務器會用 NOTIFY 或 BENOTIFY 方法,將事件通知給飛信客戶端。如飛信訂閱用戶的 Presence 事件,比如上線、下線:
查看源代碼 打印幫助SUB fetion.com.cn SIP-C/2.0 F: 123456789 I: 1 Q: 1 SUB N: presence L: xxx ?? <args><subscription><contacts><contact uri="sip:xxxxxxxx@fetion.com.cn;p=xxxx" /><presence><basic attributes="all" /><personal attributes="all" /><extended types="sms;location;listening;ring-back-tone" /></presence></subscription></args>
飛信的文本消息聊天交互過程??
飛信的文本消息聊天的交互過程,對應于 RFC3261 中 SIP 梯形圖 (SIP Trapezoid) 中的 Media Session 階段
RFC3428 中對標準 SIP 擴展了一個 MESSAGE 方法,通過 MESSAGE 方法承載這種即時文本消息,如下:
User 1 Proxy User 2| F1 MESSAGE | ||--------------------> | F2 MESSAGE || | ----------------------->|| | || | F3 200 OK || | <-----------------------|| F4 200 OK | ||<-------------------- | || | |文本消息聊天示例
用例:
聊天雙方的飛信均在 TCP 承載下工作。
用戶 A,飛信號: 123456789, IP: 111.111.111.111:1111
用戶 B,飛信號: 987654321, IP: 222.222.222.222:2222
用戶 A 打開用戶列表向 用戶 B 發送文本消息 "Hello!測試",然后 用戶 A 關閉了聊天窗口,結束了這次消息對話過程。
用戶 A 與 SIP Proxy 的交互如下:
用戶 A 的 INVITE 請求
111.111.111.111:1111 → 221.130.45.203:8080 (SIP Proxy)
查看源代碼 打印幫助| I fetion.com.cn SIP-C/2.0 |
| F: 123456789 |
| I: 16 |
| Q: 1 I |
| T: sip:987654321@fetion.com.cn;p=1972 |
| K: text/html-fragment |
| K: multiparty |
| L: 137 |
| ?? |
| v=0 |
| o=-0 0 IN 111.111.111.111:1111 |
| s=session |
| c=IN IP4 111.111.111.111:1111 |
| t=0 0 |
| m=message 1111 sip sip:123456789@fetion.com.cn;p=xxxx |
上面是發到 Proxy 的第一條消息,是一個 INVITE 請求,發到飛信的服務器 221.130.45.203:8080。SIP 承載協議是 TCP,消息放在 TCP 的包中,使用 UTF-8 編碼。
第 1 行是請求行,I = INVITE,"fetion.com.cn" 是 Request-URI,"SIP-C/2.0" 是當前的 SIP 協議版本。
第 2 行到 L: 137 之間是頭域。
F = From,標識從用戶 A (123456789) 發出的請求。
I = Call-ID,按標準的 SIP 的規定,這應該是一個隨機產生的一個全局唯一的標識符,應該在客戶端和服務器整個交互的過程中保持不變,但在飛信的 SIP-C 協議中,這是一個序列號,第一次與 Proxy 建立連接發出第一個請求時,這個值為 1,以后每次發出一個請求加 1。
Q = CSeq,它由一個整數的序列號和一個 SIP 方法組成,SIP 方法與這個消息的 SIP 方法相同,這個序列號在一個會話過程中每次加 1,這樣來標識 SIP 消息的順序。
T = To,邏輯通信目的地址,注意和 Request-URI 的區別:Request-URI 是下一跳的地址,To 是整個 Dialog 期望的目標地址。
K = Supported,表示客戶端所支持的擴展。
L = Content-Length,消息體的長度。
從 v=0 開始的是消息體,用 SDP 描述:
v= (protocol version),在目前飛信的 INVITE 中,固定的 v=0。
o= (owner/creator and session identifier),在目前飛信的 INVITE 中,前面是固定的,后面是發起人(用戶 A)的 IP 地址和端口。
s= (session name),在目前飛信的 INVITE 中,固定的為 s=session。
c=* (connection information - not required if included in all media),在目前飛信的 INVITE 中,除后面的發起人(用戶 A)的 IP 地址和端口外,前面是固定的。
t= (time the session is active),在目前飛信的 INVITE 中,固定的為 "t=0 0"。
m= (media name and transport address),在目前飛信的 INVITE 中,"1111" 是發起人的 TCP 端口,后面的 sip:xxxxxxxx,是發起人的 URI。
Proxy 對 INVITE 的響應 (I:16, Q:1 I),表示正在查找 用戶 B。
111.111.111.111:1111 ← 221.130.45.203:8080
查看源代碼 打印幫助| SIP-C/2.0 100 Trying |
| Q: 1 I |
| T: sip:987654321@fetion.com.cn;p=xxxx |
| I: 16 |
Proxy 對 INVITE 的響應 (I:16, Q:1 I),表示 INVITE 執行成功 (200 OK)。其中 222.222.222.222:2222 是 用戶 B 的 IP 和端口。
111.111.111.111:1111 ← 221.130.45.203:8080
查看源代碼 打印幫助| SIP-C/2.0 200 OK |
| Q: 1 I |
| K: text/html-fragment |
| K: multiparty |
| T: sip:123456789@fetion.com.cn;p=xxx |
| I: 16 |
| L: 135 |
| ?? |
| v=0 |
| o=-0 0 IN 222.222.222.222:2222 |
| s=session |
| c=IN IP4 222.222.222.222:2222 |
| t=0 0 |
| m=message 2222 sip sip:987654321@fetion.com.cn;p=xxx |
用戶 A 向 Proxy 發出 ACK 消息。注意:INVITE-2xx-ACK 的特殊性,它是一個獨立的 SIP 事務。
111.111.111.111:1111 → 221.130.45.203:8080
查看源代碼 打印幫助| A fetion.com.cn SIP-C/2.0 |
| I: 16 |
| Q: 1 A |
| T: sip:987654321@fetion.com.cn;p=xxx |
| F: 123456789 |
用戶 A 向 用戶 B 發文本消息,內容是帶 XML 格式的 "Hello!測試"。
使用 MESSAGE | M 方法,消息體是 XML 表示的消息,消息頭和 INVITE 相似。
111.111.111.111:1111 → 221.130.45.203:8080
查看源代碼 打印幫助| M fetion.com.cn SIP-C/2.0 |
| F: 123456789 |
| I: 16 |
| Q: 2 M |
| T: sip:987654321@fetion.com.cn;p=xxxx |
| C: text/html-fragment |
| K: SaveHistory |
| L: 121 |
| ?? |
| <Font Face='Arial' Color='-16777216' Size='9'>Hello! </Font><Font Face='SimSun' Color='-16777216' Size='12'>測試</Font> |
這是 用戶 B 收到 用戶 A 發出的文本消息后回過來的響應,結果是 200 OK,其中 XI = MessageID。
111.111.111.111:1111 ← 221.130.45.203:8080
查看源代碼 打印幫助| SIP-C/2.0 200 OK |
| Q: 2 M |
| T: sip:123456798@fetion.com.cn;p=xxxx |
| I: 16 |
| D: Mon, 01 Mar 2007 00:00:00 GMT |
| XI: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
用戶 A 關閉聊天窗口結束聊天,向 用戶 B 發出了一個 BYE 消息。
111.111.111.111:1111 → 221.130.45.203:8080
查看源代碼 打印幫助| B fetion.com.cn SIP-C/2.0 |
| F: 123456789 |
| I: 16 |
| Q: 3 B |
| T: sip:987654321@fetion.com.cn;p=xxxxx |
用戶 B 對 用戶 A 的 BYE 的響應。
111.111.111.111:1111 ← 221.130.45.203:8080
查看源代碼 打印幫助| SIP-C/2.0 200 OK |
| Q: 3 B |
| T: sip:123456789@fetion.com.cn;p=xxxx |
| I: 16 |
在 用戶 B 那邊,整個交互過程和 用戶 A 這邊對應,例如:用戶 A 在發出 INVITE,要求和 B 會話,而用戶 B 這邊則是回應邀請。
用飛信發短信時,基本流程類似,如發一個內容為 "test" 的短信到 用戶 B 時,MESSAGE 消息如下:
111.111.111.111:1111 → 221.130.45.203:8080
查看源代碼 打印幫助| M fetion.com.cn SIP-C/2.0 |
| F: 12345678 |
| I: 16 |
| Q: 1 M |
| T: sip:987654321@fetion.com.cn;p=xxxx |
| N: SendSMS |
| L: 4 |
| ?? |
| test |
注意上面的 N = Event 頭域的值 SendSMS,表示發送短信。
上面分析是飛信通過 TCP 承載 SIP 時的情況,如果飛信通過 HTTP 承載呢,過程跟上面類似,不同的是,連接的是 221.130.45.203:80,協議是HTTP,采用的 POST 請求如下:
查看源代碼 打印幫助| POST /ht/sd.aspx?t=s&i=2 HTTP/1.1 |
| Host: 221.130.45.203 |
| ... |
| ?? |
| (Post Content) |
POST 的消息體就是上面的 SIP 消息。
飛信的文本聊天消息的內容是未加密又未變換的.
To 頭域中的 p=xxxx (To tag),和手機號碼號段有關系,手機號碼前 6 位數字相同的 p 值是相同的(電信運營商經常把前 6 位配成一個號首集 DNSET)。p 的值和手機號碼的對應關系如下:
可以用上面提到的方法查看好友列表文件 contacts.dat,發現 p=[手機號碼前 6 位] - 134099,估計 134100 是中移動的第一個號段。
飛信手機語聊的 SIP 交互過程??
用例:
用戶 A,飛信號: 123456789, IP: 111.111.111.111:1111
用戶 B,飛信號: 987654321, IP: 222.222.222.222:2222
用戶 A 向 用戶 B 發起手機語聊。
用戶 A 的這邊與 Proxy 的交互:
通過 Proxy 轉發,發出 INVITE 到 用戶 B:
111.111.111.111:1111 → 221.130.45.203:8080
查看源代碼 打印幫助| I fetion.com.cn SIP-C/2.0 |
| F: 1234567890 |
| I: 11 |
| Q: 1 I |
| T: sip:987654321@fetion.com.cn;p=xxxx |
| L: 180 |
| ?? |
| v=0 |
| o=-0 0 IN P4111.111.111.111:1111 |
| s=VoiceChat |
| c=IN IP4 111.111.111.111:1111 |
| t=0 0 |
| a=user:sip:987654321@fetion.com.cn;p=xxxx |
| m=ivr 1111 sip sip:123456789@fetion.com.cn;p=yyyy |
收到 Proxy 返回的 "正在聯絡 B":
111.111.111.111:1111 ← 221.130.45.203:8080
查看源代碼 打印幫助| SIP-C/2.0 100 Trying |
| Q: 1 I |
| T: sip:987654321@fetion.com.cn;p=xxxx |
| I: 11 |
收到 Proxy 轉來的 用戶 B 的同意消息:
111.111.111.111:1111 ← 221.130.45.203:8080
查看源代碼 打印幫助| SIP-C/2.0 200 OK |
| Q: 1 I |
| T: sip:987654321@fetion.com.cn;p=xxxx |
| I: 11 |
回復 用戶 B 已收到其同意的消息 (ACK):
111.111.111.111:1111 → 221.130.45.203:8080
查看源代碼 打印幫助| A fetion.com.cn SIP-C/2.0 |
| I: 11 |
| Q: 1 A |
| T: sip:987654321@fetion.com.cn;p=xxxx |
| F: 123456789 |
要求 Proxy 開始通過手機進行語聊,這里發出的是 S = Service 方法,用來請求服務器提供額外的服務,這個服務就是 N: StartVoiceChat。
111.111.111.111:1111 → 221.130.45.203:8080
查看源代碼 打印幫助| S fetion.com.cn SIP-C/2.0 |
| F: 123456789 |
| I: 12 |
| Q: 1 S |
| N: StartVoiceChat |
| L: 103 |
| ?? |
| <args><voice-chat begin-date="2007-00-00 00:00:00.0000" /><users><user sid="987654321" /></users></args> |
到這里就跟飛信無關了,下面就是 Proxy 那邊在通過 PLMN 網絡接通兩部手機,開始媒體會話。
用戶 B 方面:
用戶 B 收到 INVITE:
222.222.222.222:2222 ← 221.130.45.203:8080
查看源代碼 打印幫助| I 123456789 SIP-C/2.0 |
| Q: 1 I |
| F: sip:987654321@fetion.com.cn;p=xxxx |
| I: -1 |
| L: 178 |
| ?? |
| v=0 |
| o=-0 0 IN P4222.222.222.222:2222 |
| s=VoiceChat |
| c=IN IP4 222.222.222.222:2222 |
| t=0 0 |
| a=user:sip:123456789@fetion.com.cn;p=yyyy |
| m=ivr 3418 sip sip:987654321@fetion.com.cn;p=xxxx |
收到這個后,用戶 B 的飛信會彈出窗口,問用戶 B 是否接受用戶 A 發起的手機語聊。這個消息的消息體中的 a=,根據 SDP,這里使用 attribute:value 的形式。
用戶 B 發出同意消息:
222.222.222.222:2222 → 221.130.45.203:8080
查看源代碼 打印幫助| SIP-C/2.0 200 OK |
| I: -1 |
| Q: 1 I |
| F: sip:987654321@fetion.com.cn;p=xxxx |
| L: 180 |
| ?? |
| v=0 |
| o=-0 0 IN P4222.222.222.222:2222 |
| s=VoiceChat |
| c=IN IP4 222.222.222.222:2222 |
| t=0 0 |
| a=user:sip:987654321@fetion.com.cn;p=xxxx |
| m=ivr 1082 sip sip:123456789@fetion.com.cn;p=yyyy |
收到 用戶 A 的 ACK 確認:
222.222.222.222:2222 ← 221.130.45.203:8080
查看源代碼 打印幫助| A 123456789 SIP-C/2.0 |
| Q: 1 A |
| F: sip:987654321@fetion.com.cn;p=xxxx |
| I: -1 |
到這里 用戶 B 手機也就響了。
其實,上面這個過程比飛信的文本消息即時通信更能體現 SIP 的作用,SIP 的作用就是建立會話,至于會話的具體媒體,如:語音還是數據,這都不是 SIP 協議所關心的事情。
飛信登錄時的身份驗證??
飛信的整個登錄過程包括取系統配置、驗證身分、取聯系人、取離線消息等過程,下面主要說明身份驗證的過程。
飛信有兩步驗證身份,第一次是通過 SSL 向 SSIPortal 登錄時,第二次是用 SIP 協議向 Proxy 注冊時。
向 SSIPortal 登錄
飛信開始用戶登錄時,向 nav.fetion.com.cn 登錄,這是飛信的 SSIPortal(單點登錄入口)。使用 HTTP GET,如下:
https://nav.fetion.com.cn/ssiportal/SSIAppSignIn.aspx?mobileno=13XXXXXXXXX&pwd=XXXX
pwd 就是這個用戶的密碼。服務器驗證通過后,就會返回 200 OK,Cookie 中就有關鍵的 SSIC 了。SSIC 應該是服務器給客戶端的 Credential,以后再跟服務器以 HTTP 的方式打交道,就必須帶上這個 Credential 了,如下一步可以向 geturi.aspx 發 SIP 請求:
查看源代碼 打印幫助| POST /hds/geturi.aspx HTTP/1.1 |
| User-Agent: IIC2.0/PC 2.1.0.0 |
| Host: 221.130.45.205 |
| Cookie: ssic=xxxxxxxxxxxxxxxx |
| Content-Length: 0 |
| Connection: Keep-Alive |
如果飛信采用 HTTP 而非 TCP 的 SIP 承載,那么每次 POST 請求都必須帶上這個 SSIC。
除了獲得 Credential 外,此階段登錄還獲得用戶的 SIP URI,如 "sip:123456789@fetion.com.cn;p=xxxx"。
向 SIP Proxy 注冊
完成上一階段登錄后,就開始 SIP-C 的協議交互過程了,即用 REGISTER 方法向 Proxy 注冊:
xxx.xxx.xxx.xxx:xxx → 221.130.45.203:8080
查看源代碼 打印幫助| R fetion.com.cn SIP-C/2.0 |
| F: 123456789 |
| I: 1 |
| Q: 1 R |
| L: 249 |
| ?? |
| <args>.......</args> |
xxx.xxx.xxx.xxx:xxxx ← 221.130.45.203:8080
查看源代碼 打印幫助| SIP-C/2.0 401 Unauthorized |
| I: 1 |
| Q: 1 R |
| W: Digest algorithm="MD5-sess",nonce="xxxxxxxxxxxxxxxx" |
xxx.xxx.xxx.xxx:xxxx → 221.130.45.203:8080
查看源代碼 打印幫助| R fetion.com.cn SIP-C/2.0 |
| F: 123456789 |
| I: 1 |
| Q: 2 R |
| A: Digest response="xxxxxxxxxxxxxxx",cnonce="xxxxxxxxxxxxxxxx" |
| L: 249 |
| ?? |
| <args>...</args> |
xxx.xxx.xxx.xxx:xxxx ← 221.130.45.203:8080
查看源代碼 打印幫助| SIP-C/2.0 200 OK |
| I: 1 |
| Q: 2 R |
| X: 600 |
| L: 877 |
| ?? |
| <results>...</results> |
這是個標準的 Digest Authentication 驗證過程,參考 SIP 或 HTTP 協議。
在 W = WWWAuthenticate 這個頭域中,nonce 是服務器給出的,那么 response 和 cnonce 是怎么計算出來的呢?
計算 response 和 cnonce 需要用到 sid(指飛信號)、passwd、domain(用戶所屬的域,例如:fetion.com.cn)、nonce。飛信計算 cnonce 是用了 4 個隨機數組成一個 16 進制的字符串然后求這個字符串的 MD5;response 的計算方法是:
(1). 求 "sid:domain:passwd" 這個 UTF-8 字符串的 MD5 值,得出 key。
(2). 求 "key:nonce:cnonce" 這個 UTF-8 字符串的 MD5 字符串,得出 H1。
(3). 求 "REGISTER:sid" 這個 UTF-8 字符串的 MD5 字符串,得出 H2。
(4). 求 "H1:nonce:H2" 這個 UTF-8 字符串的 MD5 字符串,即為 response。
轉載或改編時,請務必以鏈接形式注明文章 原始出處、作者信息 和 著作聲明:
文章標題:飛信的 SIP 協議分析
收藏者:Breaker
著作聲明:收藏 分類文章,請遵循原作者的著作聲明
文章地址:http://codingdao.com/wp/post/fetion-sip-protocol-analysis/
?
?
轉自
http://codingdao.com/wp/post/fetion-sip-protocol-analysis/
總結
以上是生活随笔為你收集整理的飞信的 SIP 协议分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 渐进式jpg转换成基线式 jpg
- 下一篇: linux安装程序企鹅,在linux下安