-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
137 lines (97 loc) · 2.83 KB
/
main.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package main
import (
"flag"
"fmt"
"log"
"net/http"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var ackItem = make(map[uint32]SequenceMap)
type SequenceMap struct {
DateTime int64
Count int
AckNumber uint32
NextSeqNumber uint32
WindowSize uint16
}
type MetricMap struct {
ipLayer *layers.IPv4
tcp *layers.TCP
deviceName string
}
func TcpStream(device string, filter string) {
var devicePrefix string
bpffilter := filter
rootDeviceList, err := pcap.FindAllDevs()
if err != nil {
panic(err)
}
if device == "" {
devicePrefix = "any"
} else {
devicePrefix = device
}
log.Println("Device to listen is ", devicePrefix)
handle, err := pcap.OpenLive(devicePrefix, 2048, true, pcap.BlockForever)
if err != nil {
fmt.Println(err)
}
defer handle.Close()
handle.SetBPFFilter(bpffilter)
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
for packet := range packetSource.Packets() {
index := packet.Metadata().InterfaceIndex
detectedDeviceName := rootDeviceList[index].Name
ipLayer := packet.Layer(layers.LayerTypeIPv4)
packetCount.WithLabelValues(detectedDeviceName).Add(1.0) // count of the package that we received
if ipLayer == nil {
continue
}
tcpLayer := packet.Layer(layers.LayerTypeTCP)
if tcpLayer == nil {
continue
}
tcp, ok := tcpLayer.(*layers.TCP)
ip, ok := ipLayer.(*layers.IPv4)
if ip.Flags.String() == "DF" {
dfMetric.WithLabelValues(ip.SrcIP.String(), ip.DstIP.String(), detectedDeviceName).Add(1.0)
}
for _, val := range tcp.Options {
if val.OptionType.String() == "WindowScale" {
windowscaleMetricCount.WithLabelValues(ip.SrcIP.String(), ip.DstIP.String(), detectedDeviceName).Add(1.0)
}
}
if tcp.RST == true {
rstMetric.WithLabelValues(ip.SrcIP.String(), ip.DstIP.String(), detectedDeviceName).Add(1.0)
}
metricData := MetricMap{ip, tcp, detectedDeviceName}
if !ok {
continue
}
if len(tcp.Payload) < 1 {
continue
}
ipPacketSize.WithLabelValues(detectedDeviceName).Add(float64(len(ip.Payload)))
tcpPacketSize.WithLabelValues(detectedDeviceName).Add(float64(len(tcp.Payload)))
tcpchan <- &metricData
}
}
func ExportPrometheus(port string, filter string) {
log.Println("Starting metric server:", port)
log.Println("Bpf filter to run:", filter)
http.Handle("/metrics", promhttp.Handler())
portToRun := ":" + port
http.ListenAndServe(portToRun, nil)
}
func main() {
port := flag.String("port", "9090", "port to run")
device := flag.String("device", "", "interface identifier to sniff")
filter := flag.String("filter", "tcp", "Definition of filter to run")
flag.Parse()
go RetransmissionHandler()
go ExportPrometheus(*port, *filter)
TcpStream(*device, *filter)
}