分析freeswitch返回403 Forbidden的原因
1、SIP協(xié)議的相關(guān)知識
403 Forbidden通常表示服務器理解請求,但拒絕執(zhí)行,常見原因包括認證失敗、權(quán)限不足、IP地址被阻止等。(最后找到是因為構(gòu)造的HA2生成的MD5碼導致認證失敗)2、解析SIP響應
在Go中處理SIP消息需要解析收到的響應,提取相關(guān)的頭部字段。根據(jù)每一個消息頭字段逐一排查。如何查看SIP消息的具體內(nèi)容REGISTER請求的結(jié)構(gòu),以及服務器返回的401和403響應的各個字段。特別是要注意WWW-Authenticate頭中的參數(shù),如realm、nonce、qop等,這些在生成認證響應時非常關(guān)鍵。- 如果qop是"auth",則response = MD5(HA1:nonce:nc:cnonce:qop:HA2)
- 如果qop未指定,則response = MD5(HA1:nonce:HA2)
- qop是"auth",所以需要包括nonce計數(shù)器、客戶端nonce以及qop值。所以正確的response計算應該包含這些參數(shù)
具體實現(xiàn):
設(shè)置過濾器,在過濾器中輸入sip進行過濾,找到相關(guān)的SIP請求和響應。然后,重點分析401和403響應的細節(jié),比如頭部信息、認證參數(shù)是否正確。比如nonce、cnonce、nc的值是否符合規(guī)范,或者哈希計算是否正確。需要指導他們在Wireshark中對比正常和異常的請求,查看Authorization頭中的各個參數(shù)是否正確。網(wǎng)絡(luò)通信問題
Go程序通過UDP發(fā)送和接收數(shù)據(jù),需要正確讀取服務器的響應,并處理可能的超時或網(wǎng)絡(luò)錯誤。NAT或防火墻導致的連接問題,雖然返回的是403,但實際可能是服務器沒有正確接收到認證請求,或者客戶端的Contact地址不可達。這時候需要檢查SIP消息中的Via和Contact頭部,確認地址和端口是否正確,是否被服務器接受。
3、Wireshark分析403 Forbidden全流程
(1)加載抓包文件
打開Wireshark → File → Open → 選擇抓包文件設(shè)置顯示過濾器(快速定位SIP流量):
sip || udp.port == 5060或者sip
(2)定位關(guān)鍵SIP事務
A.典型403錯誤流程

B.關(guān)鍵幀分析
- 初始REGISTER請求
Via: SIP/2.0/UDP 192.168.0.0:5060;branch=z9hG4bKd4e5f6a7
Max-Forwards: 70
From: <sip:1000@192.168.0.1>;tag=abcd1234
To: <sip:1000@192.168.0.1>
Call-ID: a1b2c3d4@192.168.0.0
CSeq: 1 REGISTER
Contact: <sip:1000@192.168.0.0:5060;transport=udp>
- 檢查要點:
Contact頭是否包含正確的客戶端地址
CSeq是否從1開始遞增
- 401 Unauthorized響應
Via: SIP/2.0/UDP 192.168.0.170:5060;received=192.168.0.170;branch=z9hG4bKd4e5f6a7;rport=5060
WWW-Authenticate: Digest realm="192.168.0.31", nonce="5e8f7g6h", qop="auth", algorithm=MD5
- 確認參數(shù)完整性:
algorithm 是否為MD5
- 帶認證的REGISTER請求
Authorization: Digest username="1000", realm="192.168.0.31",
nonce="5e8f7g6h", uri="sip:192.168.0.31",
response="d41d8cd98f00b204e9800998ecf8427e",
algorithm=MD5, qop=auth, nc=00000001,
cnonce="d4e5f6a7b8c9d0e1"

- 403 Forbidden響應
nonce、cnonce、nc的值是否符合規(guī)范,或者哈希計算是否正確。需要指導他們在Wireshark中對比正常和異常的請求,查看Authorization頭中的各個參數(shù)是否正確。
- MD5的計算
ha2 := md5Hex(fmt.Sprintf("REGISTER:sip:%s:%d",freeswitchIP,freeswitchPort)))
response := md5Hex(fmt.Sprintf("%s:%s:%s:%s:%s:%s",ha1, nonce, nc, cnonce, "auth", ha2))