-
Notifications
You must be signed in to change notification settings - Fork 2
/
analyze.go
84 lines (72 loc) · 2.5 KB
/
analyze.go
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
75
76
77
78
79
80
81
82
83
84
package nfp
import (
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"github.com/google/gopacket/tcpassembly"
)
// Analyze - run packet analysis on pcap handle for given duration
func Analyze(pcap *pcap.Handle, seconds uint64) NetMetrics {
var secondsRunning uint64
// Set up assembly
streamFactory := &HTTPStreamFactory{}
streamPool := tcpassembly.NewStreamPool(streamFactory)
assembler := tcpassembly.NewAssembler(streamPool)
packetSource := gopacket.NewPacketSource(pcap, pcap.LinkType())
packetSource.DecodeOptions.NoCopy = true // we promise not to alter slices (optimization)
packetSource.DecodeOptions.Lazy = true // lazy is evil; evil is good
packets := packetSource.Packets()
ticker := time.NewTicker(time.Second)
Loop:
for {
select {
case packet := <-packets:
// A nil packet indicates the end of a pcap file.
if packet == nil {
break Loop
}
if packet.NetworkLayer() == nil { //|| packet.TransportLayer() == nil {
metrics.UnusablePacket++
continue
}
if packet.ApplicationLayer() != nil &&
packet.ApplicationLayer().LayerType() == layers.LayerTypeDNS {
metrics.DNSPacket++
dns := packet.ApplicationLayer().(*layers.DNS)
for qi := range dns.Questions {
name := string(dns.Questions[qi].Name)
v, ok := metrics.DNSRequests[name]
if !ok {
metrics.DNSRequests[name] = 1
} else {
metrics.DNSRequests[name] = v + 1
}
}
} else if packet.TransportLayer() != nil && packet.TransportLayer().LayerType() == layers.LayerTypeTCP {
metrics.TCPPacket++
tcp := packet.TransportLayer().(*layers.TCP)
assembler.AssembleWithTimestamp(packet.NetworkLayer().NetworkFlow(),
tcp, packet.Metadata().Timestamp)
} else if _, ok := packet.Layer(layers.LayerTypeIPSecAH).(*layers.IPSecAH); ok {
metrics.IPSecAHPacket++
} else if _, ok := packet.Layer(layers.LayerTypeIPSecESP).(*layers.IPSecESP); ok {
metrics.IPSecESPPacket++
} else if packet.TransportLayer() != nil && packet.TransportLayer().LayerType() == layers.LayerTypeUDP {
metrics.UDPPacket++
//udp := packet.TransportLayer().(*layers.UDP)
//layers.LayerTypeIPSecAH
}
case <-ticker.C:
secondsRunning++
if seconds > 0 && secondsRunning >= seconds {
break Loop
}
if secondsRunning%60 == 0 {
// Every minute, flush connections that haven't seen activity in the past 2 minutes.
assembler.FlushOlderThan(time.Now().Add(time.Minute * -2))
}
}
}
return metrics
}