/
main.go
93 lines (83 loc) · 1.94 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
package main
import (
"context"
"log"
"os/signal"
"syscall"
bpf "github.com/aquasecurity/libbpfgo"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)
func parseEvent(data []byte) {
// Decode a packet
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.Default)
// Get the TCP layer from this packet
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
log.Println("This is a TCP packet!")
// Get actual TCP data from this layer
tcp, _ := tcpLayer.(*layers.TCP)
log.Printf("From src port %d to dst port %d", tcp.SrcPort, tcp.DstPort)
}
}
func main() {
bpfModule, err := bpf.NewModuleFromFile("main.bpf.o")
if err != nil {
panic(err)
}
defer bpfModule.Close()
if err := bpfModule.BPFLoadObject(); err != nil {
panic(err)
}
hook := bpfModule.TcHookInit()
err = hook.SetInterfaceByName("lo")
if err != nil {
log.Fatalf("failed to set tc hook on interface lo: %v", err)
}
hook.SetAttachPoint(bpf.BPFTcIngress)
err = hook.Create()
if err != nil {
log.Println(err)
if errno, ok := err.(syscall.Errno); ok && errno != syscall.EEXIST {
log.Fatalf("tc hook create: %v", err)
}
}
defer hook.Destroy()
tcProg, err := bpfModule.GetProgram("handle_ingress")
if tcProg == nil {
log.Fatal(err)
}
var tcOpts bpf.TcOpts
tcOpts.ProgFd = int(tcProg.GetFd())
err = hook.Attach(&tcOpts)
if err != nil {
log.Fatal(err)
}
eventsChannel := make(chan []byte)
lostChannel := make(chan uint64)
pb, err := bpfModule.InitPerfBuf("events", eventsChannel, lostChannel, 1024)
if err != nil {
return
}
ctx, stop := signal.NotifyContext(
context.Background(), syscall.SIGINT, syscall.SIGTERM,
)
pb.Start()
defer func() {
pb.Stop()
pb.Close()
stop()
}()
log.Println("...")
loop:
for {
select {
case data := <-eventsChannel:
parseEvent(data)
case n := <-lostChannel:
log.Printf("lost %d events", n)
case <-ctx.Done():
break loop
}
}
log.Println("bye bye~")
}