-
Notifications
You must be signed in to change notification settings - Fork 18
/
netmon.go
110 lines (91 loc) · 2.73 KB
/
netmon.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
package main
import (
"context"
"fmt"
"sync"
"time"
"github.com/florianl/go-nflog/v2"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/pkg/errors"
)
const Unknown = "Unknown"
type NetworkMonitor struct {
CorrelationId string
Repo string
ApiClient *ApiClient
Status string
netMutex sync.RWMutex
}
var ipAddresses = make(map[string]int)
func (netMonitor *NetworkMonitor) MonitorNetwork(ctx context.Context, nflogger AgentNflogger, errc chan error) []string {
//sysLogger, err := syslog.NewLogger(syslog.LOG_INFO|syslog.LOG_USER, 1)
var err error
config := nflog.Config{
Group: 100,
Copymode: nflog.CopyPacket,
// Logger: sysLogger,
//ReadTimeout: 100 * time.Millisecond,
}
var nf NfLogger
if nflogger == nil {
nf, err = nflog.Open(&config)
if err != nil {
errc <- errors.Wrap(err, "failed to open nflog")
}
} else {
nf, err = nflogger.Open(&config) // for mock
if err != nil {
errc <- errors.Wrap(err, "failed to open nflog")
}
}
defer nf.Close()
fn := func(attrs nflog.Attribute) int {
go netMonitor.handlePacket(attrs)
return 0
}
// Register your function to listen on nflog group 100
err = nf.Register(ctx, fn)
if err != nil {
errc <- errors.Wrap(err, "failed to register nflog")
}
// Block till the context expires
<-ctx.Done()
return nil
}
func (netMonitor *NetworkMonitor) handlePacket(attrs nflog.Attribute) {
timestamp := time.Now().UTC() // *attrs.Timestamp
data := *attrs.Payload
packet := gopacket.NewPacket(data, layers.LayerTypeIPv4, gopacket.Default)
port := ""
isSYN := false
// Get the TCP layer from this packet
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
// Get actual TCP data from this layer
tcp, _ := tcpLayer.(*layers.TCP)
port = tcp.DstPort.String()
isSYN = tcp.SYN
}
// Get the IP layer from this packet
if ipv4Layer := packet.Layer(layers.LayerTypeIPv4); ipv4Layer != nil {
// Get actual TCP data from this layer
ipv4, _ := ipv4Layer.(*layers.IPv4)
netMonitor.netMutex.Lock()
ipv4Address := ipv4.DstIP.String()
_, found := ipAddresses[ipv4Address]
if !found {
ipAddresses[ipv4Address] = 1
if isSYN {
if netMonitor.Status == "Dropped" {
netMonitor.ApiClient.sendNetConnection(netMonitor.CorrelationId, netMonitor.Repo,
ipv4Address, port, "", netMonitor.Status, timestamp, Tool{Name: Unknown, SHA256: Unknown})
go WriteLog(fmt.Sprintf("ip address dropped: %s", ipv4Address))
if ipv4Address != StepSecuritySinkHoleIPAddress { // Sinkhole IP address will be covered by DNS block
go WriteAnnotation(fmt.Sprintf("StepSecurity Harden Runner: Traffic to IP Address %s was blocked", ipv4Address))
}
}
}
}
netMonitor.netMutex.Unlock()
}
}