0 叠甲
头次抓包,头次用Wireshark抓包,头次分析数据流。
所以肯定有一些遗漏或者错误的地方。
慢慢修慢慢改。
1 Wireshark抓包
无论是用RPM包安装FreeSwitch还是用源码编译安装FreeSwitch,整个环境都是基于VMware虚拟机的,虚拟机的网络设置为桥接模式,也就是虚拟机和宿主机位于同一局域网网段内。在我现在的网络环境里,宿主机的IP是192.168.107.242
,虚拟机的IP是192.168.107.183
。
这次计划是虚拟机使用ffmpeg推流,宿主机用VLC拉流的同时使用Wireshark抓包。
首先看看怎么用Wireshark。
1.1 Wireshark的配置
打开Wireshark之后搜索ip.addr == 192.168.107.183 and (udp or rtcp)
,其中IP地址是推流地址(也就是我的那台虚拟机),同时筛选其中的UDP和RTCP流量。
之所以这里使用UDP而非RTP,是因为Wireshark需要SIP中的SDP信息才能知晓接下来的RTP信息,因此默认只是把RTP数据段作为UDP的有效载荷。
为了解析这个RTP数据包,我们可以将这个载荷作为RTP进行解码,也就是Wireshark中的"Decode as ……"
一般来说这时候就可以看抓包的信息了。
1.2 推流&拉流
其实推流相关的步骤我在上一篇文章里面大概说过了,具体就不在赘述了,为了简化一些逻辑,这次推流的内容就只是一个mp4文件中的音频流。
一行命令基本上就能解决问题:
1
|
ffmpeg -re -i 00\ -\ 序言.mp4 -vn -acodec copy -f rtp rtp://192.168.107.242:1234
|
然后在本地保存一下SDP文件,就可以使用VLC打开播放了。
2 抓包内容
2.1 一个RTCP包的分析
2.1.1 Wireshark输出
首先是裸数据:
1
2
3
4
5
|
3c 22 fb 7e 8d 8e 00 0c 29 66 ee 2e 08 00 45 00
00 38 dc d6 40 00 40 11 04 e4 c0 a8 6b b7 c0 a8
6b f2 b9 c6 04 d3 00 24 7d 57 80 c8 00 06 3f bf
e4 01 e8 91 3b cf 92 6e 97 8d 7d fd f9 cf 00 00
00 00 00 00 00 00
|
其次是数据的一些分析,属于太长不看系列的了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
Frame 310: 70 bytes on wire (560 bits), 70 bytes captured (560 bits) on interface en0, id 0
Section number: 1
Interface id: 0 (en0)
Interface name: en0
Interface description: Wi-Fi
Encapsulation type: Ethernet (1)
Arrival Time: Aug 24, 2023 10:15:43.574085000 CST
[Time shift for this packet: 0.000000000 seconds]
Epoch Time: 1692843343.574085000 seconds
[Time delta from previous captured frame: 0.008645000 seconds]
[Time delta from previous displayed frame: 0.000000000 seconds]
[Time since reference or first frame: 29.899979000 seconds]
Frame Number: 310
Frame Length: 70 bytes (560 bits)
Capture Length: 70 bytes (560 bits)
[Frame is marked: False]
[Frame is ignored: False]
[Protocols in frame: eth:ethertype:ip:udp:rtcp]
[Coloring Rule Name: UDP]
[Coloring Rule String: udp]
Ethernet II, Src: VMware_66:ee:2e (00:0c:29:66:ee:2e), Dst: Apple_7e:8d:8e (3c:22:fb:7e:8d:8e)
Destination: Apple_7e:8d:8e (3c:22:fb:7e:8d:8e)
Address: Apple_7e:8d:8e (3c:22:fb:7e:8d:8e)
.... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
.... ...0 .... .... .... .... = IG bit: Individual address (unicast)
Source: VMware_66:ee:2e (00:0c:29:66:ee:2e)
Address: VMware_66:ee:2e (00:0c:29:66:ee:2e)
.... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
.... ...0 .... .... .... .... = IG bit: Individual address (unicast)
Type: IPv4 (0x0800)
Internet Protocol Version 4, Src: 192.168.107.183, Dst: 192.168.107.242
0100 .... = Version: 4
.... 0101 = Header Length: 20 bytes (5)
Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
0000 00.. = Differentiated Services Codepoint: Default (0)
.... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0)
Total Length: 56
Identification: 0xdcd6 (56534)
010. .... = Flags: 0x2, Don't fragment
0... .... = Reserved bit: Not set
.1.. .... = Don't fragment: Set
..0. .... = More fragments: Not set
...0 0000 0000 0000 = Fragment Offset: 0
Time to Live: 64
Protocol: UDP (17)
Header Checksum: 0x04e4 [validation disabled]
[Header checksum status: Unverified]
Source Address: 192.168.107.183
Destination Address: 192.168.107.242
User Datagram Protocol, Src Port: 47558, Dst Port: 1235
Source Port: 47558
Destination Port: 1235
Length: 36
Checksum: 0x7d57 [unverified]
[Checksum Status: Unverified]
[Stream index: 6]
[Timestamps]
[Time since first frame: 0.000000000 seconds]
[Time since previous frame: 0.000000000 seconds]
UDP payload (28 bytes)
Real-time Transport Control Protocol (Sender Report)
10.. .... = Version: RFC 1889 Version (2)
..0. .... = Padding: False
...0 0000 = Reception report count: 0
Packet type: Sender Report (200)
Length: 6 (28 bytes)
Sender SSRC: 0x3fbfe401 (1069540353)
Timestamp, MSW: 3901832143 (0xe8913bcf)
Timestamp, LSW: 2456721293 (0x926e978d)
[MSW and LSW as NTP timestamp: Aug 24, 2023 02:15:43.571999999 UTC]
RTP timestamp: 2113796559
Sender's packet count: 0
Sender's octet count: 0
[RTCP frame length check: OK - 28 bytes]
|
2.1.2 分析
这个数据包总共四层:以太网II、IPv4、UDP、RTCP
数据包总共大小是70字节:
1
2
3
4
|
3c 22 fb 7e 8d 8e 00 0c 29 66 ee 2e 08 00 |<== Ethernet II
45 00 00 38 dc d6 40 00 40 11 04 e4 c0 a8 6b b7 c0 a8 6b f2 |<== IPv4
b9 c6 04 d3 00 24 7d 57 |<== UDP
80 c8 00 06 3f bf e4 01 e8 91 3b cf 92 6e 97 8d 7d fd f9 cf 00 00 00 00 00 00 00 00 |<== RTCP
|
2.1.2.1 Ethernet II 协议头 (14字节)
3c 22 fb 7e 8d 8e 00 0c 29 66 ee 2e 08 00|<==Ethernet II
前6字节表示目标MAC地址。
7-13这个6字节表示源MAC地址。
最后2字节标识传输种类,其中:
- 0x0800表示IPv4协议
- 0x86dd表示IPv6协议
- 0x0806表示ARP协议
2.1.2.2 IPv4协议头 (20字节)
45 00 00 38 dc d6 40 00 40 11 04 e4 c0 a8 6b b7 c0 a8 6b f2|<==IPv4
第1字节中:
前4位表示IPv4
后4位表示报文头长度为20字节
第2字节包含了区分服务
3 4 字节表示总长度,即头长度和数据长度之和,这里是0x0038,即56字节
5 6 字节为标识符
7 8 字节中:
前3位是标志位:
最前一位没有意义
中间位为1表示不分片
最后一位为1表示数据包后还有分片,0表示当前为最后一片
后13位表示分片偏移量
第9字节表示生存时间(TTL),0x40即允许在网络中进行64次跳
第10字节表示数据段的协议类型,其中11表示UDP协议
11 12两字节表示报文头校验和
13-16四字节表示发送方的IPv4地址
17-20四字节表示接受方的IPv4地址
2.1.2.3 UDP协议头 (8字节)
b9 c6 04 d3 00 24 7d 57|<==UDP
1 2 两字节:源端口,这里是0x852c 即34092
3 4 两字节:目标端口,这里是0x04d3即1235
5 6 两字节:整个UDP包的大小,0x0024即36
7 8 两字节:校验和
2.1.2.4 RTCP协议 (28字节)
80 c8 00 06 3f bf e4 01 e8 91 3b cf 92 6e 97 8d 7d fd f9 cf 00 00 00 00 00 00 00 00|<==RTCP
第1 字节:
第1 2 位表示RTP版本
第3位表示是否进行填充
4-8位表示 报告计数
第2 字节:包类型(这里是sender report)
3 4 字节:数据包大小0x0006 即28字节
5-8字节:同步源
9-12字节:时间戳
13-16字节:时间戳
17-20字节:时间戳
21-24字节:发送者包计数
25-28字节:发送者包计数
2.2 RTP的分析
RTP的数据包其实和RTCP很像,都是Ethernet II -> IPv4 -> UDP -> RTP的结构,主要的区别就在于RTP这个最里面的东西。
我们主要看三个报文头的区别
1
2
3
4
|
# RTCP的三个报文头
3c 22 fb 7e 8d 8e 00 0c 29 66 ee 2e 08 00 |<== Ethernet II
45 00 00 38 dc d6 40 00 40 11 04 e4 c0 a8 6b b7 c0 a8 6b f2 |<== IPv4
b9 c6 04 d3 00 24 7d 57 |<== UDP
|
1
2
3
4
|
# RTP的三个报文头
3c 22 fb 7e 8d 8e 00 0c 29 66 ee 2e 08 00 |<== Ethernet II
45 00 04 7f e0 b9 40 00 40 11 fc b9 c0 a8 6b b7 c0 a8 6b f2 |<== IPv4
b9 c5 04 d2 04 6b 5c 09 |<== UDP
|
通过对比,Ethernet II的报文头是完全相同的。
IPv4的报文头中第3 4字节和第11 12字节发生了变化,分辨表示了数据包总长度与校验和。
UDP报文头完全变化,其中目标端口变成了0x04d2,正好是我们设计的偶数端口1234。