-
Notifications
You must be signed in to change notification settings - Fork 2
/
extract.go
123 lines (108 loc) · 3.27 KB
/
extract.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
package main
import (
"fmt"
conntrack "github.com/florianl/go-conntrack"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)
func addIPv6IPTuple(con *conntrack.Con, pkt gopacket.Packet) {
ipLayer := pkt.Layer(layers.LayerTypeIPv6)
if ipv6, ok := ipLayer.(*layers.IPv6); ok {
con.Origin = &conntrack.IPTuple{
Src: &ipv6.SrcIP,
Dst: &ipv6.DstIP,
}
}
}
func addIPv4IPTuple(con *conntrack.Con, pkt gopacket.Packet) {
ipLayer := pkt.Layer(layers.LayerTypeIPv4)
if ipv4, ok := ipLayer.(*layers.IPv4); ok {
con.Origin = &conntrack.IPTuple{
Src: &ipv4.SrcIP,
Dst: &ipv4.DstIP,
}
}
}
func addL4Ports(con *conntrack.Con, srcPort, dstPort uint16, proto uint8) {
con.Origin.Proto = &conntrack.ProtoTuple{
Number: &proto,
SrcPort: &srcPort,
DstPort: &dstPort,
}
}
func extractConFromPayload(data []byte) (con conntrack.Con, err error) {
version := (data)[0] >> 4
if version == 4 {
pkt := gopacket.NewPacket(data, layers.LayerTypeIPv4, gopacket.NoCopy)
addIPv4IPTuple(&con, pkt)
if icmpLayer := pkt.Layer(layers.LayerTypeICMPv4); icmpLayer != nil {
icmp, _ := icmpLayer.(*layers.ICMPv4)
typeCode := icmp.TypeCode
icmpType := typeCode.Type()
icmpCode := typeCode.Code()
if icmpType != 8 || icmpCode != 0 {
err = fmt.Errorf("ignoring non-echo-request ICMP packets")
return
}
var protoNumber uint8 = 1
con.Origin.Proto = &conntrack.ProtoTuple{
Number: &protoNumber,
IcmpType: &icmpType,
IcmpCode: &icmpCode,
IcmpID: &icmp.Id,
}
return
}
if udpLayer := pkt.Layer(layers.LayerTypeUDP); udpLayer != nil {
udp, _ := udpLayer.(*layers.UDP)
addL4Ports(&con, uint16(udp.SrcPort), uint16(udp.DstPort), 17)
return
}
if tcpLayer := pkt.Layer(layers.LayerTypeTCP); tcpLayer != nil {
tcp, _ := tcpLayer.(*layers.TCP)
addL4Ports(&con, uint16(tcp.SrcPort), uint16(tcp.DstPort), 6)
return
}
err = fmt.Errorf("could not decode IPv4 packet")
} else if version == 6 {
pkt := gopacket.NewPacket(data, layers.LayerTypeIPv6, gopacket.NoCopy)
addIPv6IPTuple(&con, pkt)
if icmp6Layer := pkt.Layer(layers.LayerTypeICMPv6); icmp6Layer != nil {
icmp6, _ := icmp6Layer.(*layers.ICMPv6)
typeCode := icmp6.TypeCode
icmpType := typeCode.Type()
icmpCode := typeCode.Code()
if icmpType != 128 || icmpCode != 0 {
err = fmt.Errorf("ignoring non-echo-request ICMPv6 packets")
return
}
if echoLayer := pkt.Layer(layers.LayerTypeICMPv6Echo); echoLayer != nil {
echo, _ := echoLayer.(*layers.ICMPv6Echo)
var protoNumber uint8 = 58
con.Origin.Proto = &conntrack.ProtoTuple{
Number: &protoNumber,
Icmpv6Type: &icmpType,
Icmpv6Code: &icmpCode,
Icmpv6ID: &echo.Identifier,
}
return
}
err = fmt.Errorf("could not decode ICMPv6 packet")
return
}
if udpLayer := pkt.Layer(layers.LayerTypeUDP); udpLayer != nil {
udp, _ := udpLayer.(*layers.UDP)
addL4Ports(&con, uint16(udp.SrcPort), uint16(udp.DstPort), 17)
return
}
if tcpLayer := pkt.Layer(layers.LayerTypeTCP); tcpLayer != nil {
tcp, _ := tcpLayer.(*layers.TCP)
addL4Ports(&con, uint16(tcp.SrcPort), uint16(tcp.DstPort), 6)
return
}
err = fmt.Errorf("could not decode IPv6 packet")
} else {
err = fmt.Errorf("could not decode packet (non-IPv4/IPv6)")
}
return
}