This repository has been archived by the owner on Jun 14, 2023. It is now read-only.
/
event.go
159 lines (135 loc) · 3.42 KB
/
event.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package beater
import (
"net"
"strconv"
"time"
"github.com/elastic/beats/libbeat/beat"
"github.com/elastic/beats/libbeat/common"
)
type Locality uint8
const (
LocalityPrivate Locality = iota + 1
LocalityPublic
)
var localityNames = map[Locality]string{
LocalityPrivate: "private",
LocalityPublic: "public",
}
func (l Locality) String() string {
name, found := localityNames[l]
if found {
return name
}
return "unknown (" + strconv.Itoa(int(l)) + ")"
}
type FlowEvent struct {
TimeReceived time.Time // Time packet was read off socket.
TimeCreated time.Time // Time record was generated by "router".
SequenceNum uint32 // Message sequence number.
Type FlowType // Flow type (e.g. Netflow v9, IPFIX)
// Flow exporter's address.
DeviceAddr net.IP
// Flow times.
StartTime time.Time
LastTime time.Time
Duration time.Duration
// Flow volume.
Bytes uint64
Packets uint64
Direction *FlowDirection
// Layer 3 info.
SrcMAC net.HardwareAddr
DstMAC net.HardwareAddr
// Layer 4 Info.
// IP version. https://www.iana.org/assignments/version-numbers/version-numbers.xhtml
IPVersion uint8 // 4 = ipv4, 6=ipv6
IPClassOfTraffic uint8 // TOS for IPv4, Traffic Class for IPv6.
SrcIP net.IP
DstIP net.IP
SrcLocality Locality
DstLocality Locality
SrcPort uint16
DstPort uint16
Locality Locality
TCPFlags TCPFlag
// Layer 4 protocol (transport). Comes from the IPv4 and IPv6 headers.
// Netflow fields: protocolIdentifier (IPv4) and nextHeaderIPv6.
TransportProtocol IPProtocol
// Stable 5-tuple that's the same for both flow dirs.
FiveTuple string
FiveTupleHash string
// VLANs
IngressVLAN uint16
EgressVLAN uint16
// Raw Netflow fields.
Netflow map[string]interface{}
}
func (f *FlowEvent) toBeatEvent() beat.Event {
b := beat.Event{
Timestamp: f.TimeReceived.UTC(),
Fields: common.MapStr{
"event": common.MapStr{
"type": f.Type.String(),
"created": f.TimeCreated.UTC(),
"start": f.StartTime.UTC(),
"end": f.LastTime.UTC(),
"duration": f.Duration,
},
"device": common.MapStr{
"ip": f.DeviceAddr,
},
"flow": common.MapStr{
"sequence_num": f.SequenceNum,
"five_tuple": f.FiveTuple,
"id": f.FiveTupleHash,
"locality": f.Locality.String(),
},
"source": common.MapStr{
"ip": f.SrcIP.String(),
"locality": f.SrcLocality.String(),
},
"destination": common.MapStr{
"ip": f.DstIP.String(),
"locality": f.DstLocality.String(),
},
"network": common.MapStr{
"protocol": f.TransportProtocol.String(),
"total": common.MapStr{
"bytes": f.Bytes,
"packets": f.Packets,
},
},
"netflow": f.Netflow,
},
}
if len(f.SrcMAC) > 0 {
b.PutValue("source.mac", f.SrcMAC.String())
}
if len(f.DstMAC) > 0 {
b.PutValue("destination.mac", f.DstMAC.String())
}
if f.SrcPort > 0 {
b.PutValue("source.port", f.SrcPort)
}
if f.DstPort > 0 {
b.PutValue("destination.port", f.DstPort)
}
if f.Direction != nil {
switch *f.Direction {
case Ingress:
b.PutValue("network.direction", "inbound")
case Egress:
b.PutValue("network.direction", "outbound")
}
}
if f.TCPFlags > 0 {
b.PutValue("network.tcp.flags", f.TCPFlags.Strings())
}
if f.IngressVLAN > 0 {
b.PutValue("source.vlan", f.IngressVLAN)
}
if f.EgressVLAN > 0 {
b.PutValue("destination.vlan", f.EgressVLAN)
}
return b
}