The files in the output directory have the following naming scheme: The set of files with pattern rtp.x.* refer to the rtpbreak execution number x, the subset of files with pattern rtp.x.y.* refer to the RTP session number y (of the rtpbreak execution number x). At each execution and at each RTP session detection, x and y are respectively incremented. The set of output files of the rtpbreak execution number x is organized as follows:
xenion@gollum:~/dev/rtpbreak-1.3$ sudo src/rtpbreak -i wifi0 -g -m -d logz + rtpbreak v1.3 running here! + pid: 3580, date/time: 19/02/2008#09:49:21 + Configuration + INPUT Packet source: iface 'wifi0' Force datalink header length: disabled + OUTPUT Output directory: 'logz' RTP raw dumps: enabled RTP pcap dumps: enabled Fill gaps: enabled Dump noise: disabled Logfile: 'logz/rtp.0.txt' Logging to stdout: enabled Logging to syslog: disabled Be verbose: disabled + SELECT Sniff packets in promisc mode: enabled Add pcap filter: disabled Expecting even destination UDP port: disabled Expecting unprivileged source/destination UDP ports: disabled Expecting RTP payload type: any Expecting RTP payload length: any Packet timeout: 10.00 seconds Pattern timeout: 0.25 seconds Pattern packets: 5 + EXECUTION Running as user/group: root/root Running daemonized: disabled * You can dump stats sending me a SIGUSR2 signal * Reading packets... ! [rtp0] detected: pt=0(g711U) 192.168.0.30:2072 => 192.168.0.20:2074 ! [rtp1] detected: pt=0(g711U) 192.168.0.20:2074 => 192.168.0.30:2072 * [rtp1] probable reverse RTP stream: [rtp0] + Status Alive RTP Sessions: 2 Closed RTP Sessions: 0 Detected RTP Sessions: 2 Flushed RTP packets: 3358 Lost RTP packets: 122 (3.51%) Noise (false positive) packets: 0 + [rtp1] stats: packets inbuffer=262 flushed=1673 lost=61(3.52%), call_length=1m2s + [rtp0] stats: packets inbuffer=270 flushed=1685 lost=61(3.49%), call_length=1m2s * [rtp1] closed: packets inbuffer=0 flushed=2800 lost=115(3.95%), call_length=1m28s * [rtp0] closed: packets inbuffer=0 flushed=2819 lost=106(3.62%), call_length=1m28s -- Caught SIGINT signal (2), cleaning up... -- + Status Alive RTP Sessions: 0 Closed RTP Sessions: 2 Detected RTP Sessions: 2 Flushed RTP packets: 5619 Lost RTP packets: 221 (3.78%) Noise (false positive) packets: 0 + No active RTP streams xenion@gollum:~/dev/rtpbreak-1.3$
We've sent a SIGUSR2 signal to the rtpbreak process at call_length=1m2s, forcing a stats print. The final output directory content is the following:
xenion@gollum:~/dev/rtpbreak-1.3$ ls -1 logz rtp.0.0.pcap rtp.0.0.raw rtp.0.0.txt rtp.0.1.pcap rtp.0.1.raw rtp.0.1.txt rtp.0.txt xenion@gollum:~/dev/rtpbreak-1.3$
Those are the two RTP sessions logs:
xenion@gollum:~/dev/rtpbreak-1.3$ cat logz/rtp.0.0.txt RTP stream id: rtp.0.0 Packet source: iface 'wifi0' First seen packet: 19/02/2008#09:49:29 (pcap time) Stream peers: 192.168.0.30:2072 => 192.168.0.20:2074 RTP ssrc: 1695569992 RTP payload type: 0 (ITU-T G.711 PCMU) Last seen packet: 19/02/2008#09:50:57 (pcap time) Call length: 1m28s Flushed packets: 2819 Lost packets: 106 (3.62%) RTP payload length: 240 bytes (fixed) xenion@gollum:~/dev/rtpbreak-1.3$ cat logz/rtp.0.1.txt RTP stream id: rtp.0.1 Packet source: iface 'wifi0' First seen packet: 19/02/2008#09:49:29 (pcap time) Stream peers: 192.168.0.20:2074 => 192.168.0.30:2072 RTP ssrc: 112268413 RTP payload type: 0 (ITU-T G.711 PCMU) Probable reverse RTP stream id: rtp.0.0 Last seen packet: 19/02/2008#09:50:57 (pcap time) Call length: 1m28s Flushed packets: 2800 Lost packets: 115 (3.95%) RTP payload length: 240 bytes (fixed) xenion@gollum:~/dev/rtpbreak-1.3$
Now, we've to decode, mix and replay this recorded call:
xenion@gollum:~/dev/rtpbreak-1.3$ sox -r8000 -c1 -t ul logz/rtp.0.0.raw -t wav logz/0.wav xenion@gollum:~/dev/rtpbreak-1.3$ sox -r8000 -c1 -t ul logz/rtp.0.1.raw -t wav logz/1.wav xenion@gollum:~/dev/rtpbreak-1.3$ sox -m logz/0.wav logz/1.wav logz/call.wav xenion@gollum:~/dev/rtpbreak-1.3$ mplayer logz/call.wav
xenion@gollum:~/dev/rtpbreak-1.3$ rtpbreak -P2 -t100 -T100 -d logz -r h323.pcap + rtpbreak v1.3 running here! + pid: 4613, date/time: 19/02/2008#10:18:54 + Configuration + INPUT Packet source: rxfile 'h323.pcap' Force datalink header length: disabled + OUTPUT Output directory: 'logz' RTP raw dumps: enabled RTP pcap dumps: enabled Fill gaps: disabled Dump noise: disabled Logfile: 'logz/rtp.1.txt' Logging to stdout: enabled Logging to syslog: disabled Be verbose: disabled + SELECT Sniff packets in promisc mode: disabled Add pcap filter: disabled Expecting even destination UDP port: disabled Expecting unprivileged source/destination UDP ports: disabled Expecting RTP payload type: any Expecting RTP payload length: any Packet timeout: 100.00 seconds Pattern timeout: 100.00 seconds Pattern packets: 2 + EXECUTION Running as user/group: xenion/xenion Running daemonized: disabled * You can dump stats sending me a SIGUSR2 signal * Reading packets... ! [rtp0] detected: pt=102(?) 172.16.1.109:5004 => 172.16.1.105:5012 ! [rtp1] detected: pt=0(g711U) 172.16.1.105:5012 => 172.16.1.109:5004 * [rtp1] probable reverse RTP stream: [rtp0] ! [rtp2] detected: pt=31(h261) 172.16.1.109:5006 => 172.16.1.105:5014 * eof reached. -- Caught SIGTERM signal (15), cleaning up... -- * [rtp2] closed: packets inbuffer=0 flushed=2286 lost=0(0.00%), call_length=4m10s * [rtp1] closed: packets inbuffer=0 flushed=4465 lost=0(0.00%), call_length=4m8s * [rtp0] closed: packets inbuffer=0 flushed=6254 lost=0(0.00%), call_length=4m10s + Status Alive RTP Sessions: 0 Closed RTP Sessions: 3 Detected RTP Sessions: 3 Flushed RTP packets: 13005 Lost RTP packets: 0 (0.00%) Noise (false positive) packets: 70 + No active RTP streams xenion@gollum:~/dev/rtpbreak-1.3$The output directory content, after running examples 1 and 2, should be the following:
xenion@gollum:~/dev/rtpbreak-1.3$ ls -1 logz 0.wav 1.wav call.wav rtp.0.0.pcap rtp.0.0.raw rtp.0.0.txt rtp.0.1.pcap rtp.0.1.raw rtp.0.1.txt rtp.0.txt rtp.1.0.pcap rtp.1.0.raw rtp.1.0.txt rtp.1.1.pcap rtp.1.1.raw rtp.1.1.txt rtp.1.2.pcap rtp.1.2.raw rtp.1.2.txt rtp.1.txt xenion@gollum:~/dev/rtpbreak-1.3$The set of files of the second rtpbreak execution have prefix rtp.1. Those are the three RTP sessions logs:
xenion@gollum:~/dev/rtpbreak-1.3$ cat logz/rtp.1.0.txt RTP stream id: rtp.1.0 Packet source: rxfile 'h323.pcap' First seen packet: 14/11/2006#17:57:29 (pcap time) Stream peers: 172.16.1.109:5004 => 172.16.1.105:5012 RTP ssrc: 268399165 RTP payload type: 102 (Unknown) Last seen packet: 14/11/2006#18:01:39 (pcap time) Call length: 4m10s Flushed packets: 6254 Lost packets: 0 (0.00%) RTP payload length: 65 bytes (fixed) xenion@gollum:~/dev/rtpbreak-1.3$ cat logz/rtp.1.1.txt RTP stream id: rtp.1.1 Packet source: rxfile 'h323.pcap' First seen packet: 14/11/2006#17:57:29 (pcap time) Stream peers: 172.16.1.105:5012 => 172.16.1.109:5004 RTP ssrc: 1910395951 RTP payload type: 0 (ITU-T G.711 PCMU) Probable reverse RTP stream id: rtp.1.0 Last seen packet: 14/11/2006#18:01:37 (pcap time) Call length: 4m8s Flushed packets: 4465 Lost packets: 0 (0.00%) RTP payload length: 240 bytes (fixed) xenion@gollum:~/dev/rtpbreak-1.3$ cat logz/rtp.1.2.txt RTP stream id: rtp.1.2 Packet source: rxfile 'h323.pcap' First seen packet: 14/11/2006#17:57:29 (pcap time) Stream peers: 172.16.1.109:5006 => 172.16.1.105:5014 RTP ssrc: 267301810 RTP payload type: 31 (ITU-T H.261) Last seen packet: 14/11/2006#18:01:39 (pcap time) Call length: 4m10s Flushed packets: 2286 Lost packets: 0 (0.00%) RTP payload length: 945 bytes (variable, this is the last seen) xenion@gollum:~/dev/rtpbreak-1.3$
Now, we completely dissect the first packet of the third RTP session with tshark:
xenion@gollum:~/dev/rtpbreak-1.3$ cat logz/rtp.1.2.txt | grep "Stream peers" Stream peers: 172.16.1.109:5006 => 172.16.1.105:5014 xenion@gollum:~/dev/rtpbreak-1.3$ tshark -r logz/rtp.1.2.pcap -d udp.port==5006,rtp -c 1 -V Frame 1 (1073 bytes on wire, 1073 bytes captured) Arrival Time: Nov 14, 2006 17:57:29.972300000 [Time delta from previous captured frame: 0.000000000 seconds] [Time delta from previous displayed frame: 0.000000000 seconds] [Time since reference or first frame: 0.000000000 seconds] Frame Number: 1 Frame Length: 1073 bytes Capture Length: 1073 bytes [Frame is marked: False] [Protocols in frame: eth:ip:udp:rtp:h261] Ethernet II, Src: Dell_15:09:a6 (00:12:3f:15:09:a6), Dst: Dell_ca:ec:cd (00:14:22:ca:ec:cd) Destination: Dell_ca:ec:cd (00:14:22:ca:ec:cd) Address: Dell_ca:ec:cd (00:14:22:ca:ec:cd) .... ...0 .... .... .... .... = IG bit: Individual address (unicast) .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) Source: Dell_15:09:a6 (00:12:3f:15:09:a6) Address: Dell_15:09:a6 (00:12:3f:15:09:a6) .... ...0 .... .... .... .... = IG bit: Individual address (unicast) .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) Type: IP (0x0800) Internet Protocol, Src: 172.16.1.109 (172.16.1.109), Dst: 172.16.1.105 (172.16.1.105) Version: 4 Header length: 20 bytes Differentiated Services Field: 0x10 (DSCP 0x04: Unknown DSCP; ECN: 0x00) 0001 00.. = Differentiated Services Codepoint: Unknown (0x04) .... ..0. = ECN-Capable Transport (ECT): 0 .... ...0 = ECN-CE: 0 Total Length: 1059 Identification: 0x0000 (0) Flags: 0x04 (Don't Fragment) 0... = Reserved bit: Not set .1.. = Don't fragment: Set ..0. = More fragments: Not set Fragment offset: 0 Time to live: 64 Protocol: UDP (0x11) Header checksum: 0xdbc3 [correct] [Good: True] [Bad : False] Source: 172.16.1.109 (172.16.1.109) Destination: 172.16.1.105 (172.16.1.105) User Datagram Protocol, Src Port: wsm-server (5006), Dst Port: 5014 (5014) Source port: wsm-server (5006) Destination port: 5014 (5014) Length: 1039 Checksum: 0x5f17 [incorrect, should be 0x270c (maybe caused by "UDP checksum offload"?)] [Good Checksum: False] [Bad Checksum: True] Real-Time Transport Protocol 10.. .... = Version: RFC 1889 Version (2) ..0. .... = Padding: False ...0 .... = Extension: False .... 0000 = Contributing source identifiers count: 0 0... .... = Marker: False Payload type: ITU-T H.261 (31) Sequence number: 42926 Timestamp: 3003 Synchronization Source identifier: 0x0feeb3b2 (267301810) ITU-T Recommendation H.261 Start bit position: 0 End bit position: 2 Intra frame encoded data flag: False Motion vector flag: True GOB Number: 0 Macroblock address predictor: 0 Quantizer: 0 Horizontal motion vector data: 0 Vertical motion vector data: 0 H.261 stream: 00010006000113220300C0300DFF7FD1019B8103881035C0... xenion@gollum:~/dev/rtpbreak-1.3$The wrong UDP checksum comes from the original network packet, rtpbreak only reorders the network packets of each RTP stream. As we did, rtpbreak can be used together with tshark/wireshark to handle complex needs.
Scope: We want to (successfully) handle some particular scenarios. This is a list of problem description, (probable) cause and (hopefully) solution.
rtpbreak -i eth0 -n -t100 -T100
rtpbreak -i eth0 -n -P2
rtpbreak -i eth0 -m -n -P2 -t100 -T100This is the most aggressive (and computationally expensive) configuration of the detection heuristics and will always detect any RTP session.
The RTP sessions are composed by an ordered sequence of RTP packets. Those packets transport the Real Time data using the UDP transport protocol. The RTP packets must respect some well defined rules in order to be considered valid, this characteristic allows us to define a pattern on the single packet that is used to discriminate the captured network traffic from packets that can be RTP and those that securely are not. The fixed RTP header has this format:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |V=2|P|X| CC |M| PT | sequence number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | timestamp | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | synchronization source (SSRC) identifier | +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | contributing source (CSRC) identifiers | | .... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The following checks are performed (on each sniffed packet):
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | defined by profile | length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | header extension | | .... |
The length field indicates the extension size, header of the extension excluded. His presence is indicated by the X field value. If active, the RTP payload size is adjusted, checking it to be greater than 0.
The UDP packets passing those checks are considered like "maybe RTP" packets. Note that the IP and UDP packet checksums aren't checked because quite often they're erroneously computed by VoIP clients. The UDP packets passing those checks are compared with the already detected RTP sessions (this is called pattern over multiple packets). The comparison is done considering the following informations:
If it's identified a possible session, the UDP packet is inserted in his buffer. If this doesn't happen, a new one is created. When to a session are assigned a minimal set of UDP packets, it's considered valid and any UDP packet in his buffer is considered definitely RTP. This must happen before a timeout, after that the session is considered a false positive (noise packets) and destroyed.
To compile, type "make" in the top directory.
In order to decode the RTP streams with sox, you need sox with the support for the required formats. In debian, you need the following packages: