Skip to content

Commit ab352e2

Browse files
authored
Merge pull request #4 from negbie/master
Custom SIP portrange, some error checks
2 parents dab65d8 + b553f73 commit ab352e2

File tree

7 files changed

+60
-50
lines changed

7 files changed

+60
-50
lines changed

build_static.sh

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#!/bin/sh
22

3+
# Thanks for the idea to use musl!
4+
# https://www.moiji-mobile.com/2017/10/15/static-binaries-for-go-with-docker/
5+
36
set -ex
47

58
apk update

config/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type InterfacesConfig struct {
2121
Type string `config:"type"`
2222
ReadFile string `config:"read_file"`
2323
WriteFile string `config:"write_file"`
24+
PortRange string `config:"port_range"`
2425
Snaplen int `config:"snaplen"`
2526
BufferSizeMb int `config:"buffer_size_mb"`
2627
ReadSpeed bool `config:"top_speed"`

decoder/decoder.go

+22-22
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ type Decoder struct {
3030
unknownCount int
3131
IPFlow gopacket.Flow
3232
UDPFlow gopacket.Flow
33-
lru *lru.Cache
34-
bigcache *bigcache.BigCache
35-
hash hash.Hash64
33+
SIPHash hash.Hash64
34+
SIPCache *lru.Cache
35+
RTCPCache *bigcache.BigCache
3636
}
3737

3838
type Packet struct {
@@ -56,14 +56,14 @@ func NewDecoder() *Decoder {
5656
host = "sniffer"
5757
}
5858

59-
la, err := lru.New(8000)
59+
sh := xxhash.New()
60+
61+
sc, err := lru.New(8000)
6062
if err != nil {
6163
logp.Err("lru %v", err)
6264
}
6365

64-
xh := xxhash.New()
65-
66-
bConf := bigcache.Config{
66+
rcConf := bigcache.Config{
6767
// number of shards (must be a power of 2)
6868
Shards: 1024,
6969
// time after which entry can be evicted
@@ -73,7 +73,7 @@ func NewDecoder() *Decoder {
7373
// max entry size in bytes, used only in initial memory allocation
7474
MaxEntrySize: 300,
7575
// prints information about additional memory allocation
76-
Verbose: true,
76+
Verbose: false,
7777
// cache will not allocate more memory than this limit, value in MB
7878
// if value is reached then the oldest entries can be overridden for the new ones
7979
// 0 value means no size limit
@@ -84,7 +84,7 @@ func NewDecoder() *Decoder {
8484
OnRemove: nil,
8585
}
8686

87-
bc, err := bigcache.NewBigCache(bConf)
87+
rc, err := bigcache.NewBigCache(rcConf)
8888
if err != nil {
8989
logp.Err("bigcache %v", err)
9090
}
@@ -99,9 +99,9 @@ func NewDecoder() *Decoder {
9999
tcpCount: 0,
100100
dnsCount: 0,
101101
unknownCount: 0,
102-
lru: la,
103-
hash: xh,
104-
bigcache: bc,
102+
SIPHash: sh,
103+
SIPCache: sc,
104+
RTCPCache: rc,
105105
}
106106
go d.flushFrag()
107107
go d.printStats()
@@ -126,12 +126,12 @@ func (d *Decoder) Process(data []byte, ci *gopacket.CaptureInfo) (*Packet, error
126126
}
127127

128128
if config.Cfg.Dedup {
129-
d.hash.Write(ip4.Payload)
129+
d.SIPHash.Write(ip4.Payload)
130130
//key := fastHash(ip4.Payload)
131-
key := d.hash.Sum64()
132-
d.hash.Reset()
133-
_, dup := d.lru.Get(key)
134-
d.lru.Add(key, nil)
131+
key := d.SIPHash.Sum64()
132+
d.SIPHash.Reset()
133+
_, dup := d.SIPCache.Get(key)
134+
d.SIPCache.Add(key, nil)
135135
if dup == true {
136136
d.dupCount++
137137
return nil, nil
@@ -251,7 +251,7 @@ func (d *Decoder) cacheSDPIPPort(payload []byte) {
251251
}
252252

253253
restPort := payload[posSDPPort:]
254-
if posRestPort := bytes.Index(restIP, []byte(" RTP")); posRestPort >= 0 {
254+
if posRestPort := bytes.Index(restPort, []byte(" RTP")); posRestPort >= 0 {
255255
SDPPort, err := strconv.Atoi(string(restPort[len("m=audio "):bytes.Index(restPort, []byte(" RTP"))]))
256256
if err != nil {
257257
logp.Warn("%v", err)
@@ -263,20 +263,20 @@ func (d *Decoder) cacheSDPIPPort(payload []byte) {
263263

264264
if posCallID := bytes.Index(payload, []byte("Call-ID: ")); posCallID >= 0 {
265265
restCallID := payload[posCallID:]
266-
if posRestCallID := bytes.Index(restIP, []byte("\r\n")); posRestCallID >= 0 {
266+
if posRestCallID := bytes.Index(restCallID, []byte("\r\n")); posRestCallID >= 0 {
267267
callID = restCallID[len("Call-ID: "):bytes.Index(restCallID, []byte("\r\n"))]
268268
} else {
269269
logp.Warn("Couldn't find end of Call-ID in '%s'", string(restCallID))
270270
}
271271
} else if posID := bytes.Index(payload, []byte("i: ")); posID >= 0 {
272272
restID := payload[posID:]
273-
if posRestID := bytes.Index(restIP, []byte("\r\n")); posRestID >= 0 {
273+
if posRestID := bytes.Index(restID, []byte("\r\n")); posRestID >= 0 {
274274
callID = restID[len("i: "):bytes.Index(restID, []byte("\r\n"))]
275275
} else {
276276
logp.Warn("Couldn't find end of Call-ID in '%s'", string(restID))
277277
}
278278
}
279-
d.bigcache.Set(SDPIP+RTCPPort, callID)
279+
d.RTCPCache.Set(SDPIP+RTCPPort, callID)
280280
}
281281
}
282282

@@ -287,7 +287,7 @@ func (d *Decoder) correlateRTCP(payload []byte) ([]byte, []byte, byte) {
287287
return nil, nil, 0
288288
}
289289

290-
corrID, err := d.bigcache.Get(d.IPFlow.Src().String() + d.UDPFlow.Src().String())
290+
corrID, err := d.RTCPCache.Get(d.IPFlow.Src().String() + d.UDPFlow.Src().String())
291291
if err != nil {
292292
logp.Warn("%v", err)
293293
return nil, nil, 0

example/rtp_rtcp_sip.pcap

902 KB
Binary file not shown.

main.go

+10-9
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,24 @@ func parseFlags() {
2525
var keepLogFiles int
2626

2727
flag.StringVar(&ifaceConfig.Device, "i", "", "Listen on interface")
28-
flag.StringVar(&ifaceConfig.Type, "t", "pcap", "Capture types are [af_packet, pcap, file]")
29-
flag.StringVar(&ifaceConfig.ReadFile, "rf", "", "Read packets from file. Please use -t file")
30-
flag.StringVar(&ifaceConfig.WriteFile, "wf", "", "Write packets to file")
31-
flag.IntVar(&ifaceConfig.Loop, "lp", 1, "Loop count over ReadFile")
32-
flag.BoolVar(&ifaceConfig.ReadSpeed, "rs", false, "Maximum read speed. Doesn't use packet timestamps")
33-
flag.IntVar(&ifaceConfig.Snaplen, "s", 32768, "Snap length")
28+
flag.StringVar(&ifaceConfig.Type, "t", "pcap", "Capture types are [pcap, af_packet]")
29+
flag.StringVar(&ifaceConfig.ReadFile, "rf", "", "Read packets from pcap file")
30+
flag.StringVar(&ifaceConfig.WriteFile, "wf", "", "Write packets to pcap file")
31+
flag.IntVar(&ifaceConfig.Loop, "lp", 1, "Loop count over ReadFile. Use 0 to loop forever")
32+
flag.BoolVar(&ifaceConfig.ReadSpeed, "rs", false, "Maximum pcap read speed. Doesn't use packet timestamps")
33+
flag.IntVar(&ifaceConfig.Snaplen, "s", 32768, "Snaplength")
34+
flag.StringVar(&ifaceConfig.PortRange, "pr", "5060-5090", "Portrange to capture SIP")
3435
flag.IntVar(&ifaceConfig.BufferSizeMb, "b", 64, "Interface buffersize (MB)")
3536
flag.IntVar(&keepLogFiles, "kl", 4, "Rotate the number of log files")
3637
flag.StringVar(&logging.Level, "l", "info", "Log level [debug, info, warning, error]")
3738
flag.BoolVar(&ifaceConfig.OneAtATime, "o", false, "Read packet for packet")
3839
flag.StringVar(&fileRotator.Path, "p", "./", "Log filepath")
3940
flag.StringVar(&fileRotator.Name, "n", "heplify.log", "Log filename")
4041
flag.Uint64Var(&rotateEveryKB, "r", 16384, "Log filesize (KB)")
41-
flag.StringVar(&config.Cfg.Mode, "m", "SIP", "Capture modes [DNS, LOG, SIP, RTCP, TLS]")
42+
flag.StringVar(&config.Cfg.Mode, "m", "SIP", "Capture modes [DNS, LOG, SIP, SIPRTCP, TLS]")
4243
flag.BoolVar(&config.Cfg.Dedup, "dd", true, "Deduplicate packets")
43-
flag.StringVar(&config.Cfg.Filter, "fi", "", "Filter out interesting packets like SIP INVITES, Handshakes ...")
44-
flag.StringVar(&config.Cfg.Discard, "di", "", "Discard uninteresting packets like SIP OPTIONS, HTTP Requests ...")
44+
flag.StringVar(&config.Cfg.Filter, "fi", "", "Filter interesting packets")
45+
flag.StringVar(&config.Cfg.Discard, "di", "", "Discard uninteresting packets")
4546
flag.StringVar(&config.Cfg.HepServer, "hs", "127.0.0.1:9060", "HEP Server address")
4647
flag.Parse()
4748

protos/rtcp.go

+16-15
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,13 @@ func (rp *RTCP_Packet) MarshalJSON() ([]byte, error) {
177177
func ParseRTCP(data []byte) ([]byte, error) {
178178
dataLen := len(data)
179179
if dataLen < 28 {
180-
return nil, fmt.Errorf("Useless data inside RTCP packet='%s' length=%d", string(data), len(data))
180+
return nil, fmt.Errorf("Useless data inside RTCP packet='%s' length=%d", string(data), dataLen)
181181
}
182182
pkt := &RTCP_Packet{}
183183
offset := 0
184184

185185
for dataLen > 0 {
186-
if dataLen%4 != 0 || dataLen < 4 {
186+
if dataLen < 4 || dataLen > 576 {
187187
return nil, fmt.Errorf("Fishy RTCP packet=%v length=%d", data, dataLen)
188188
}
189189

@@ -193,7 +193,7 @@ func ParseRTCP(data []byte) ([]byte, error) {
193193
RTCPType := data[offset+1]
194194
RTCPLength := binary.BigEndian.Uint16(data[offset+2:]) * 4
195195

196-
offset = offset + 4
196+
offset += 4
197197

198198
if receptionReportCount < 0 || receptionReportCount > 4 {
199199
return nil, fmt.Errorf("Fishy RTCP receptionReportCount=%d", receptionReportCount)
@@ -211,7 +211,7 @@ func ParseRTCP(data []byte) ([]byte, error) {
211211
pkt.SenderInformation.Rtp_timestamp = binary.BigEndian.Uint32(data[offset+12:])
212212
pkt.SenderInformation.Pkt_count = binary.BigEndian.Uint32(data[offset+16:])
213213
pkt.SenderInformation.Octet_count = binary.BigEndian.Uint32(data[offset+20:])
214-
offset = offset + 24
214+
offset += 24
215215

216216
if receptionReportCount > 0 && RTCPLength >= 24 {
217217
tmpReportBlocks := make([]RTCP_report_block, receptionReportCount)
@@ -227,20 +227,21 @@ func ParseRTCP(data []byte) ([]byte, error) {
227227
tmpReportBlocks[i].Delay_last_SR = binary.BigEndian.Uint32(data[offset+20:])
228228
tmpReportBlocks[i].ReportCount = receptionReportCount
229229
tmpReportBlocks[i].RTCPType = RTCPType
230-
offset = offset + 24
230+
offset += 24
231+
RTCPLength -= 24
231232
pkt.ReportBlocks = pkt.AddReportBlock(tmpReportBlocks[i])
232233
}
233234
}
234235

235236
case TYPE_RTCP_RR:
236-
if RTCPLength < 28 {
237+
if RTCPLength < 4 {
237238
return nil, fmt.Errorf("To small RTCP packet=%v length=%d type=%d", data[offset:RTCPLength], RTCPLength, RTCPType)
238239
}
239240

240241
pkt.Ssrc = binary.BigEndian.Uint32(data[offset:])
241-
offset = offset + 4
242+
offset += 4
242243

243-
if receptionReportCount > 0 && RTCPLength >= 28 {
244+
if receptionReportCount > 0 && RTCPLength >= 24 {
244245
tmpReportBlocks := make([]RTCP_report_block, receptionReportCount)
245246
for i := 0; i < int(receptionReportCount); i++ {
246247
tmpReportBlocks[i].SourceSsrc = binary.BigEndian.Uint32(data[offset:])
@@ -254,26 +255,27 @@ func ParseRTCP(data []byte) ([]byte, error) {
254255
tmpReportBlocks[i].Delay_last_SR = binary.BigEndian.Uint32(data[offset+20:])
255256
tmpReportBlocks[i].ReportCount = receptionReportCount
256257
tmpReportBlocks[i].RTCPType = RTCPType
257-
offset = offset + 24
258+
offset += 24
259+
RTCPLength -= 24
258260
pkt.ReportBlocks = pkt.AddReportBlock(tmpReportBlocks[i])
259261
}
260262
}
261263

262264
case TYPE_RTCP_SDES:
263265
logp.Debug("rtcp", "Discard RTCP_SDES packet type: %d", RTCPType)
264-
offset = offset + int(RTCPLength)
266+
offset += int(RTCPLength)
265267
case TYPE_RTCP_APP:
266268
logp.Debug("rtcp", "Discard RTCP_APP packet type: %d", RTCPType)
267-
offset = offset + int(RTCPLength)
269+
offset += int(RTCPLength)
268270
case TYPE_RTCP_BYE:
269271
logp.Debug("rtcp", "Discard RTCP_BYE packet type: %d", RTCPType)
270-
offset = offset + int(RTCPLength)
272+
offset += int(RTCPLength)
271273
case TYPE_RTCP_XR:
272274
logp.Debug("rtcp", "Discard RTCP_XR packet type: %d", RTCPType)
273-
offset = offset + int(RTCPLength)
275+
offset += int(RTCPLength)
274276
default:
275277
logp.Debug("rtcp", "Discard unsupported packet type: %d", RTCPType)
276-
offset = offset + int(RTCPLength)
278+
offset += int(RTCPLength)
277279
}
278280

279281
dataLen -= offset
@@ -285,6 +287,5 @@ func ParseRTCP(data []byte) ([]byte, error) {
285287
return nil, err
286288
}
287289

288-
logp.Debug("rtcp", "RTCP json payload:\n%v\n", string(rtcpPkt))
289290
return rtcpPkt, nil
290291
}

sniffer/sniffer.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,11 @@ func (sniffer *SnifferSetup) setFromConfig(cfg *config.InterfacesConfig) error {
9595

9696
switch sniffer.mode {
9797
case "SIP":
98-
sniffer.filter = "(greater 256 and portrange 5060-5090 or ip[6:2] & 0x1fff != 0) or (vlan and (greater 256 and portrange 5060-5090 or ip[6:2] & 0x1fff != 0))"
98+
sniffer.filter = "(greater 256 and portrange " + sniffer.config.PortRange + " or ip[6:2] & 0x1fff != 0) or (vlan and (greater 256 and portrange " + sniffer.config.PortRange + " or ip[6:2] & 0x1fff != 0))"
9999
case "RTCP":
100100
sniffer.filter = "(ip and ip[6] & 0x2 = 0 and ip[6:2] & 0x1fff = 0 and udp and udp[8] & 0xc0 = 0x80 and udp[9] >= 0xc8 && udp[9] <= 0xcc)"
101101
case "SIPRTCP":
102-
sniffer.filter = "(greater 256 and portrange 5060-5090 or ip[6:2] & 0x1fff != 0) or (ip and ip[6] & 0x2 = 0 and ip[6:2] & 0x1fff = 0 and udp and udp[8] & 0xc0 = 0x80 and udp[9] >= 0xc8 && udp[9] <= 0xcc)"
102+
sniffer.filter = "(greater 256 and portrange " + sniffer.config.PortRange + " or ip[6:2] & 0x1fff != 0) or (ip and ip[6] & 0x2 = 0 and ip[6:2] & 0x1fff = 0 and udp and udp[8] & 0xc0 = 0x80 and udp[9] >= 0xc8 && udp[9] <= 0xcc)"
103103
case "LOG":
104104
sniffer.filter = "greater 128 and port 514"
105105
case "DNS":
@@ -108,7 +108,7 @@ func (sniffer *SnifferSetup) setFromConfig(cfg *config.InterfacesConfig) error {
108108
sniffer.filter = "tcp and port 443 and tcp[(((tcp[12:1] & 0xf0) >> 2)):1] = 0x16 and ((tcp[(((tcp[12:1] & 0xf0) >> 2)+5):1] = 0x01) or (tcp[(((tcp[12:1] & 0xf0) >> 2)+5):1] = 0x02))"
109109
default:
110110
sniffer.mode = "SIP"
111-
sniffer.filter = "(greater 256 and portrange 5060-5090 or ip[6:2] & 0x1fff != 0) or (vlan and (greater 256 and portrange 5060-5090 or ip[6:2] & 0x1fff != 0))"
111+
sniffer.filter = "(greater 256 and portrange " + sniffer.config.PortRange + " or ip[6:2] & 0x1fff != 0) or (vlan and (greater 256 and portrange " + sniffer.config.PortRange + " or ip[6:2] & 0x1fff != 0))"
112112
}
113113

114114
logp.Info("Sniffer type: [%s] device: [%s] mode: [%s]", sniffer.config.Type, sniffer.config.Device, sniffer.mode)
@@ -167,13 +167,17 @@ func (sniffer *SnifferSetup) Init(testMode bool, mode string, factory WorkerFact
167167
sniffer.mode = mode
168168

169169
if interfaces.Device == "" && interfaces.ReadFile == "" {
170-
fmt.Printf("\nPlease use one of the following devices:\n\n")
170+
fmt.Printf("Please use one of the following devices:\n\n")
171171
_, err := ListDeviceNames(false, false)
172172
if err != nil {
173173
return fmt.Errorf("getting devices list: %v", err)
174174
}
175175
fmt.Println("")
176176
os.Exit(1)
177+
} else if interfaces.Device == "any" && interfaces.Type == "pcap" {
178+
fmt.Println("Interface 'any' and capture type 'pcap' will break VLAN capture!")
179+
fmt.Println("To listen on interface 'any' please use 'af_packet' capture type!")
180+
os.Exit(1)
177181
}
178182

179183
if !testMode {

0 commit comments

Comments
 (0)