如何在 Janus 中獲取 WebRTC 的流

聲網Agora發表於2018-12-27
 歡迎訪問 RTC 開發者社群,與更多實時音視訊、WebRTC開發者交流經驗。 

抓取WebRTC流量看起來相對簡單,大多數情況下確實是這樣:你只需要在其中一人的機器上安裝類似tcpdumpwireshark的抓包工具,然後檢視產生的檔案,大多數情況會是.pcap或.pcapng檔案。這些活動對於診斷連線問題或其它與WebRTC相關的問題很有用:實際上,wireshark可以自動檢測出STUN,DTLS之類的標準協議,這些是WebRTC PeerConnections所關注的。

本文關鍵是什麼?

抓取WebRTC流量的唯一問題就是,媒體內容會被加密。當檢查了STUN連線或DTLS握手之後,這不是一個問題,但是當你想要檢視RTP或RTCP包的時候,這將會成為一個問題,它將會被加密成SRTP和SRTCP。實際上,儘管SRTP標題沒有被加密,你可以任何形式抓取流量,但是SRTP負載不是,意味著你不能檢視它的內容。

大多數情況下你不需要檢視內容。正如期待的那樣,你依然可以檢視加密RTP包的標題,也就是最常被用到的資訊。不管怎樣,對於RTCP並不能這樣說:實際上,一條RTCP資訊可能實際上包含不止一個包,並且不存在一個共享的標題。除此之外,檢視RTP負載可能會有效。

這意味著抓取加密流量是可行的,但是為了診斷目的抓取無加密資料效果可能更好。不幸的是,無其它幫助下這是不可能的:實際上,WebRTC情況下瀏覽器經常傳送加密資料,即使有一些允許你抓取無加密資料進行測試,但是你還是需要依靠其它工具來獲取媒體流,才能進行這項工作。

進入Janus!

作為一個WebRTC媒體伺服器,Janus確實發揮了它的效果:實際上,它存在於PeerConnection的每一條媒體路徑上。除此之外,由於它為每個PeerConnections分別建立了安全環境,它可以獲得輸入和輸出的未加密的RTP和RTCP包。

我們一年前就是這樣想的,被Firefox所激勵,我們首先新增了text2pcap dump的支援,採取的方法很直接:

1.使用Admin API,開始抓取Janus處理檔案的資訊。
2.所有輸入輸出的RTP/RTCP包都被轉化為文字格式,儲存到相關檔案中。
3.抓取結束後,使用text2pcap App 將抓取檔案轉化為與Wiresharak或其它工具相容的格式。

請求的語法很簡單:

POST /admin/sessionId/handleId
{
        "janus" : "start_text2pcap",
        "folder" : "<folder to save the dump to; optional, current folder if missing>",
        "filename" : "<filename of the dump; optional, random filename if missing>",
        "truncate" : "<number of bytes to truncate at; optional, won't truncate if 0 or missing>",
        "transaction" : "<random alphanumeric string>",
        "admin_secret" : "<password specified in janus.cfg, if any>"
}
複製程式碼

如果已知了相關session和handle Id,可以輕易生成一句程式碼來對handle開始抓取:

curl -X POST -H "Content-Type: application/json" -d '{"janus": "start_text2pcap", "folder": "/tmp", "filename": "my-test2pcap-dump.txt", "transaction": "123", "admin_secret": "janusoverlord"}' http://localhost:7088/admin/8412133783240844/2377476017639045
複製程式碼

停止抓取更簡單,就像你需要一個stop_text2pcap請求來做這件事。

最終,你將會以類似的文字檔案結束:

I 18:47:14.126004 000000  80 e0 6c 5d [..] JANUS_TEXT2PCAP_RTP [session=3740061776621518][handle=3149681776118503]
O 18:47:14.128251 000000  80 e0 04 83 [..] JANUS_TEXT2PCAP_RTP [session=3740061776621518][handle=3149681776118503]
I 18:47:14.136577 000000  80 6f 54 8d [..] JANUS_TEXT2PCAP_RTP [session=3740061776621518][handle=3149681776118503]
O 18:47:14.136659 000000  80 6f 03 9f [..] JANUS_TEXT2PCAP_RTP [session=3740061776621518][handle=3149681776118503]
複製程式碼

你對此檔案不能做太多:我們看到一些輸入輸出包,在某個時間被儲存,還可以看到16進位制的負載值,每一行結尾有一些環境資訊。你需要把它傳給其它工具,例如text2pcap,將它轉化為你可以讀懂的檔案:

text2pcap -D -n -l 1 -i 17 -u 1000,2000 -t '%H:%M:%S.' /tmp/my-test2pcap-dump.txt /tmp/my-test2pcap-dump.pcapng複製程式碼

你可以參考說明書詳細學習應該怎樣做和工具提供的功能,上面的一行基本可以遍歷文字檔案,將每個包轉化為pcapng格式,使用不同IP和埠供兩方交流,更容易區分彼此。

但是文字序列化不是應該效率低下麼?

我很高興你問了這個問題!

那是對的:儘管上述方法簡單易行,並且出色的完成了它的工作,但是耗費了大量的CPU。這意味著,儘管看起來不錯,你不能將此方法應用於產品環境中,因為這樣做會影響你機器的效能。

我們需要另外一種方法,在Janus中直接儲存到原始pcap檔案中,而不是將其轉化為文字檔案,之後進行處理。這個方法模擬了文字抓取,但是有輕微的不同之處:
  1. 就像之前,你使用Admin API開始對Janus中的一個檔案進行抓取,但是使用不同的請求
  2. Pcap全域性標題在抓取之前就被儲存。
  3. 所有的輸入輸出RTP/RTCP包都被儲存為檔案,但是首先要建立一些假的乙太網/IP/UDP標題,並且都移pcap包標題為字首。

你可能注意到了這裡不包括寫入處理:由於我們直接儲存到pcap檔案中,這意味著,我們一停止抓取,檔案就馬上被生成,利用,使用適當的工具。除此之外,由於不需要文字序列化,而是直接寫入檔案,這個過程變得輕量化,影響基本可忽略,並且與Janus中的媒體記錄特性很好的契合。

儘管你使用了不同的方法儲存為.pcap檔案,而且命名為start_pcap,而不是start_text2pcap,它的語法與另一個完全一樣:這意味著你可以提供與之前一樣的資訊,並儲存它,無論是否縮短。觀察前面的例子,接著,下面是請求的格式:

curl -X POST -H "Content-Type: application/json" -d '{"janus": "start_pcap", "folder": "/tmp", "filename": "my-pcap-dump.pcap", "transaction": "123", "admin_secret": "janusoverlord"}' http://localhost:7088/admin/8412133783240844/2377476017639045
複製程式碼

注意,我們只改變了請求名稱和目標檔案的副檔名。其它完全一樣。

如果不想使用curl

目前為止,我們解釋了Jauns對於抓取未加密資料所提供的功能,如何使用Admin API請求利用這個特性。不管怎樣,你可能不想手動做這些事,或通過命令列。幸運的是,我準備了一個虛擬介面來做這些事。

Janus報告帶來一些可供使用的網路演示,包括了Admin API介面。這個介面在之前的文章中已經詳細介紹過,特別是使用它提供的資訊達到診斷問題的目的。我們不會重複這些細節,但是我們會關注一點,你應該如何在Janus中開始或停止抓取一個特定檔案。當然了,我們假定了你之前在HTTP外掛配置中開啟了Admin API後端。

如果你有Janus演示的最近的版本,開啟Admin API,嘗試導航現有session,選擇一個特定的handle。你應該在實際處理資訊前看到一個叫做開啟抓取的勾選框。

1001

點選它,如下:

1002

大多數設定應該清晰易懂,因為當介紹Admin API請求語法時,我們介紹了它們。第一個允許你選擇抓取型別,之前講到過,或者是直接儲存到pcap,或者是轉化為文字檔案之後處理。

1003

接著你被要求設定儲存檔案的路徑:

1004

你應該只關心包的第一個byte,而不是全部,這將會使在儲存之前縮短包變得有效。你可以使用縮短選擇:

1005

當抓取開始時,網頁將會改變相關的勾選框,將其轉化為控制資訊,讓你隨時可以暫停正在進行的抓取。

1006

當前的抓取狀態也會顯示在handle資訊中:

1007

一旦抓取完成,不管是否需要text2pcap,使用wireshark,最終你會得到你可以使用的檔案。假設使用了Wireshark,抓取介面如下所示:

1008

正如期待,我們可以看到兩個不同的IP(10.1.1.1和10.2.2.2)在不同埠相互交流。當Janus抓取流量時,10.1.1.1:1000總是peer的地址,10.2.2.2:2000總是Janus自己的地址。

當然,Wireshark自己並不能分辨這些UDP包的內容是RTP和RTCP資訊。這是我們需要告訴它的,將流量資訊解碼為RTP。

1009

之後,Wireshark顯示的資訊會變化:

1010

如你所見,Wireshark負責解釋RTP標題,使我們可以觀察和分析它。對於負載也可以這樣說,它將會被解密,並且被我們看到。

Wireshark一個很少被人知道的特性,是它也支援對某些媒體編解碼器的解封裝。這意味著,如果你告訴Wireshark一個包內含有特定編解碼器編碼的媒體資訊,它將會給你一個具體的編解碼資訊。VP8和H.264編解碼器處於其中,因此,如果在設定中將負載型別96和VP8穩定關聯起來,顯示的資訊將會再一次改變:

1011

儘管這張截圖與之前的相似,還是存在一些關鍵區別:例如, 注意對於敷在型別96的所有包,協議一列如何從RTP轉化為VP8。這意味著Wireshark正在使用更高階的解碼,也可以觀察負載:在VP8情況下,這意味著獲取以VP8負載描述為字首的實際媒體流內容。


相關文章