mirror of
https://github.com/safing/portmaster
synced 2025-09-02 02:29:12 +00:00
Add ebpf bandwidth monitoring
This commit is contained in:
parent
8a09ba6045
commit
daeafa406d
21 changed files with 707 additions and 35 deletions
147
firewall/interception/ebpf/bandwidth/bpf_bpfeb.go
Normal file
147
firewall/interception/ebpf/bandwidth/bpf_bpfeb.go
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
// Code generated by bpf2go; DO NOT EDIT.
|
||||||
|
//go:build arm64be || armbe || mips || mips64 || mips64p32 || ppc64 || s390 || s390x || sparc || sparc64
|
||||||
|
// +build arm64be armbe mips mips64 mips64p32 ppc64 s390 s390x sparc sparc64
|
||||||
|
|
||||||
|
package ebpf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf"
|
||||||
|
)
|
||||||
|
|
||||||
|
type bpfSkInfo struct {
|
||||||
|
Rx uint64
|
||||||
|
Tx uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type bpfSkKey struct {
|
||||||
|
SrcIp [4]uint32
|
||||||
|
DstIp [4]uint32
|
||||||
|
SrcPort uint16
|
||||||
|
DstPort uint16
|
||||||
|
Protocol uint8
|
||||||
|
Ipv6 uint8
|
||||||
|
_ [2]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadBpf returns the embedded CollectionSpec for bpf.
|
||||||
|
func loadBpf() (*ebpf.CollectionSpec, error) {
|
||||||
|
reader := bytes.NewReader(_BpfBytes)
|
||||||
|
spec, err := ebpf.LoadCollectionSpecFromReader(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't load bpf: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadBpfObjects loads bpf and converts it into a struct.
|
||||||
|
//
|
||||||
|
// The following types are suitable as obj argument:
|
||||||
|
//
|
||||||
|
// *bpfObjects
|
||||||
|
// *bpfPrograms
|
||||||
|
// *bpfMaps
|
||||||
|
//
|
||||||
|
// See ebpf.CollectionSpec.LoadAndAssign documentation for details.
|
||||||
|
func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error {
|
||||||
|
spec, err := loadBpf()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec.LoadAndAssign(obj, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bpfSpecs contains maps and programs before they are loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed ebpf.CollectionSpec.Assign.
|
||||||
|
type bpfSpecs struct {
|
||||||
|
bpfProgramSpecs
|
||||||
|
bpfMapSpecs
|
||||||
|
}
|
||||||
|
|
||||||
|
// bpfSpecs contains programs before they are loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed ebpf.CollectionSpec.Assign.
|
||||||
|
type bpfProgramSpecs struct {
|
||||||
|
SocketOperations *ebpf.ProgramSpec `ebpf:"socket_operations"`
|
||||||
|
UdpRecvmsg *ebpf.ProgramSpec `ebpf:"udp_recvmsg"`
|
||||||
|
UdpSendmsg *ebpf.ProgramSpec `ebpf:"udp_sendmsg"`
|
||||||
|
Udpv6Recvmsg *ebpf.ProgramSpec `ebpf:"udpv6_recvmsg"`
|
||||||
|
Udpv6Sendmsg *ebpf.ProgramSpec `ebpf:"udpv6_sendmsg"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// bpfMapSpecs contains maps before they are loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed ebpf.CollectionSpec.Assign.
|
||||||
|
type bpfMapSpecs struct {
|
||||||
|
PmBandwidthMap *ebpf.MapSpec `ebpf:"pm_bandwidth_map"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// bpfObjects contains all objects after they have been loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||||
|
type bpfObjects struct {
|
||||||
|
bpfPrograms
|
||||||
|
bpfMaps
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *bpfObjects) Close() error {
|
||||||
|
return _BpfClose(
|
||||||
|
&o.bpfPrograms,
|
||||||
|
&o.bpfMaps,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bpfMaps contains all maps after they have been loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||||
|
type bpfMaps struct {
|
||||||
|
PmBandwidthMap *ebpf.Map `ebpf:"pm_bandwidth_map"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *bpfMaps) Close() error {
|
||||||
|
return _BpfClose(
|
||||||
|
m.PmBandwidthMap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bpfPrograms contains all programs after they have been loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||||
|
type bpfPrograms struct {
|
||||||
|
SocketOperations *ebpf.Program `ebpf:"socket_operations"`
|
||||||
|
UdpRecvmsg *ebpf.Program `ebpf:"udp_recvmsg"`
|
||||||
|
UdpSendmsg *ebpf.Program `ebpf:"udp_sendmsg"`
|
||||||
|
Udpv6Recvmsg *ebpf.Program `ebpf:"udpv6_recvmsg"`
|
||||||
|
Udpv6Sendmsg *ebpf.Program `ebpf:"udpv6_sendmsg"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *bpfPrograms) Close() error {
|
||||||
|
return _BpfClose(
|
||||||
|
p.SocketOperations,
|
||||||
|
p.UdpRecvmsg,
|
||||||
|
p.UdpSendmsg,
|
||||||
|
p.Udpv6Recvmsg,
|
||||||
|
p.Udpv6Sendmsg,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _BpfClose(closers ...io.Closer) error {
|
||||||
|
for _, closer := range closers {
|
||||||
|
if err := closer.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not access this directly.
|
||||||
|
//
|
||||||
|
//go:embed bpf_bpfeb.o
|
||||||
|
var _BpfBytes []byte
|
BIN
firewall/interception/ebpf/bandwidth/bpf_bpfeb.o
Normal file
BIN
firewall/interception/ebpf/bandwidth/bpf_bpfeb.o
Normal file
Binary file not shown.
147
firewall/interception/ebpf/bandwidth/bpf_bpfel.go
Normal file
147
firewall/interception/ebpf/bandwidth/bpf_bpfel.go
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
// Code generated by bpf2go; DO NOT EDIT.
|
||||||
|
//go:build 386 || amd64 || amd64p32 || arm || arm64 || mips64le || mips64p32le || mipsle || ppc64le || riscv64
|
||||||
|
// +build 386 amd64 amd64p32 arm arm64 mips64le mips64p32le mipsle ppc64le riscv64
|
||||||
|
|
||||||
|
package ebpf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf"
|
||||||
|
)
|
||||||
|
|
||||||
|
type bpfSkInfo struct {
|
||||||
|
Rx uint64
|
||||||
|
Tx uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type bpfSkKey struct {
|
||||||
|
SrcIp [4]uint32
|
||||||
|
DstIp [4]uint32
|
||||||
|
SrcPort uint16
|
||||||
|
DstPort uint16
|
||||||
|
Protocol uint8
|
||||||
|
Ipv6 uint8
|
||||||
|
_ [2]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadBpf returns the embedded CollectionSpec for bpf.
|
||||||
|
func loadBpf() (*ebpf.CollectionSpec, error) {
|
||||||
|
reader := bytes.NewReader(_BpfBytes)
|
||||||
|
spec, err := ebpf.LoadCollectionSpecFromReader(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't load bpf: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadBpfObjects loads bpf and converts it into a struct.
|
||||||
|
//
|
||||||
|
// The following types are suitable as obj argument:
|
||||||
|
//
|
||||||
|
// *bpfObjects
|
||||||
|
// *bpfPrograms
|
||||||
|
// *bpfMaps
|
||||||
|
//
|
||||||
|
// See ebpf.CollectionSpec.LoadAndAssign documentation for details.
|
||||||
|
func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error {
|
||||||
|
spec, err := loadBpf()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec.LoadAndAssign(obj, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bpfSpecs contains maps and programs before they are loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed ebpf.CollectionSpec.Assign.
|
||||||
|
type bpfSpecs struct {
|
||||||
|
bpfProgramSpecs
|
||||||
|
bpfMapSpecs
|
||||||
|
}
|
||||||
|
|
||||||
|
// bpfSpecs contains programs before they are loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed ebpf.CollectionSpec.Assign.
|
||||||
|
type bpfProgramSpecs struct {
|
||||||
|
SocketOperations *ebpf.ProgramSpec `ebpf:"socket_operations"`
|
||||||
|
UdpRecvmsg *ebpf.ProgramSpec `ebpf:"udp_recvmsg"`
|
||||||
|
UdpSendmsg *ebpf.ProgramSpec `ebpf:"udp_sendmsg"`
|
||||||
|
Udpv6Recvmsg *ebpf.ProgramSpec `ebpf:"udpv6_recvmsg"`
|
||||||
|
Udpv6Sendmsg *ebpf.ProgramSpec `ebpf:"udpv6_sendmsg"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// bpfMapSpecs contains maps before they are loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed ebpf.CollectionSpec.Assign.
|
||||||
|
type bpfMapSpecs struct {
|
||||||
|
PmBandwidthMap *ebpf.MapSpec `ebpf:"pm_bandwidth_map"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// bpfObjects contains all objects after they have been loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||||
|
type bpfObjects struct {
|
||||||
|
bpfPrograms
|
||||||
|
bpfMaps
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *bpfObjects) Close() error {
|
||||||
|
return _BpfClose(
|
||||||
|
&o.bpfPrograms,
|
||||||
|
&o.bpfMaps,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bpfMaps contains all maps after they have been loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||||
|
type bpfMaps struct {
|
||||||
|
PmBandwidthMap *ebpf.Map `ebpf:"pm_bandwidth_map"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *bpfMaps) Close() error {
|
||||||
|
return _BpfClose(
|
||||||
|
m.PmBandwidthMap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bpfPrograms contains all programs after they have been loaded into the kernel.
|
||||||
|
//
|
||||||
|
// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||||
|
type bpfPrograms struct {
|
||||||
|
SocketOperations *ebpf.Program `ebpf:"socket_operations"`
|
||||||
|
UdpRecvmsg *ebpf.Program `ebpf:"udp_recvmsg"`
|
||||||
|
UdpSendmsg *ebpf.Program `ebpf:"udp_sendmsg"`
|
||||||
|
Udpv6Recvmsg *ebpf.Program `ebpf:"udpv6_recvmsg"`
|
||||||
|
Udpv6Sendmsg *ebpf.Program `ebpf:"udpv6_sendmsg"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *bpfPrograms) Close() error {
|
||||||
|
return _BpfClose(
|
||||||
|
p.SocketOperations,
|
||||||
|
p.UdpRecvmsg,
|
||||||
|
p.UdpSendmsg,
|
||||||
|
p.Udpv6Recvmsg,
|
||||||
|
p.Udpv6Sendmsg,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _BpfClose(closers ...io.Closer) error {
|
||||||
|
for _, closer := range closers {
|
||||||
|
if err := closer.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not access this directly.
|
||||||
|
//
|
||||||
|
//go:embed bpf_bpfel.o
|
||||||
|
var _BpfBytes []byte
|
BIN
firewall/interception/ebpf/bandwidth/bpf_bpfel.o
Normal file
BIN
firewall/interception/ebpf/bandwidth/bpf_bpfel.o
Normal file
Binary file not shown.
179
firewall/interception/ebpf/bandwidth/interface.go
Normal file
179
firewall/interception/ebpf/bandwidth/interface.go
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
package ebpf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf"
|
||||||
|
"github.com/cilium/ebpf/link"
|
||||||
|
"github.com/cilium/ebpf/rlimit"
|
||||||
|
"github.com/safing/portbase/log"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang -cflags "-O2 -g -Wall -Werror" bpf ../programs/bandwidth.c
|
||||||
|
|
||||||
|
var ebpfInterface = struct {
|
||||||
|
objs bpfObjects
|
||||||
|
sockOptionsLink link.Link
|
||||||
|
udpv4SMLink link.Link
|
||||||
|
udpv4RMLink link.Link
|
||||||
|
udpv6SMLink link.Link
|
||||||
|
udpv6RMLink link.Link
|
||||||
|
}{
|
||||||
|
objs: bpfObjects{},
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetupBandwidthInterface() error {
|
||||||
|
|
||||||
|
// Allow the current process to lock memory for eBPF resources.
|
||||||
|
err := rlimit.RemoveMemlock()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to remove memlock: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load pre-compiled programs and maps into the kernel.
|
||||||
|
err = loadBpfObjects(&ebpfInterface.objs, nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("feiled loading objects: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
// Defer the cleanup function to be called at the end of the enclosing function
|
||||||
|
// If there was an error during the execution, shutdown the BandwithInterface
|
||||||
|
ShutdownBandwithInterface()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Find the cgroup path
|
||||||
|
path, err := findCgroupPath()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("faield to find cgroup paths: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach socket options for monitoring connections
|
||||||
|
ebpfInterface.sockOptionsLink, err = link.AttachCgroup(link.CgroupOptions{
|
||||||
|
Path: path,
|
||||||
|
Program: ebpfInterface.objs.bpfPrograms.SocketOperations,
|
||||||
|
Attach: ebpf.AttachCGroupSockOps,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to open module sockops: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach Udp Ipv4 recive message tracing
|
||||||
|
ebpfInterface.udpv4RMLink, err = link.AttachTracing(link.TracingOptions{
|
||||||
|
Program: ebpfInterface.objs.UdpRecvmsg,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to open trace Udp IPv4 recvmsg: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach UDP IPv4 send message tracing
|
||||||
|
ebpfInterface.udpv4SMLink, err = link.AttachTracing(link.TracingOptions{
|
||||||
|
Program: ebpfInterface.objs.UdpSendmsg,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to open trace Udp IPv4 sendmsg: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach UDP IPv6 receive message tracing
|
||||||
|
ebpfInterface.udpv6RMLink, err = link.AttachTracing(link.TracingOptions{
|
||||||
|
Program: ebpfInterface.objs.Udpv6Recvmsg,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to open trace Udp IPv6 recvmsg: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach UDP IPv6 send message tracing
|
||||||
|
ebpfInterface.udpv6RMLink, err = link.AttachTracing(link.TracingOptions{
|
||||||
|
Program: ebpfInterface.objs.Udpv6Sendmsg,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to open trace Udp IPv6 sendmsg: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example code that will print the bandwidth table every 10 seconds
|
||||||
|
// go func() {
|
||||||
|
// ticker := time.NewTicker(10 * time.Second)
|
||||||
|
// defer ticker.Stop()
|
||||||
|
// for range ticker.C {
|
||||||
|
// printBandwidthData()
|
||||||
|
// }
|
||||||
|
// }()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShutdownBandwithInterface shuts down the bandwidth interface by closing the associated links and objects.
|
||||||
|
func ShutdownBandwithInterface() {
|
||||||
|
// Close the sockOptionsLink if it is not nil
|
||||||
|
if ebpfInterface.sockOptionsLink != nil {
|
||||||
|
ebpfInterface.sockOptionsLink.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the udpv4SMLink if it is not nil
|
||||||
|
if ebpfInterface.udpv4SMLink != nil {
|
||||||
|
ebpfInterface.udpv4SMLink.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the udpv4RMLink if it is not nil
|
||||||
|
if ebpfInterface.udpv4RMLink != nil {
|
||||||
|
ebpfInterface.udpv4RMLink.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the udpv6SMLink if it is not nil
|
||||||
|
if ebpfInterface.udpv6SMLink != nil {
|
||||||
|
ebpfInterface.udpv6SMLink.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the udpv6RMLink if it is not nil
|
||||||
|
if ebpfInterface.udpv6RMLink != nil {
|
||||||
|
ebpfInterface.udpv6RMLink.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the ebpfInterface objects
|
||||||
|
ebpfInterface.objs.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func findCgroupPath() (string, error) {
|
||||||
|
cgroupPath := "/sys/fs/cgroup"
|
||||||
|
|
||||||
|
var st syscall.Statfs_t
|
||||||
|
err := syscall.Statfs(cgroupPath, &st)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
isCgroupV2Enabled := st.Type == unix.CGROUP2_SUPER_MAGIC
|
||||||
|
if !isCgroupV2Enabled {
|
||||||
|
cgroupPath = filepath.Join(cgroupPath, "unified")
|
||||||
|
}
|
||||||
|
return cgroupPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func printBandwidthData() {
|
||||||
|
iter := ebpfInterface.objs.bpfMaps.PmBandwidthMap.Iterate()
|
||||||
|
var skKey bpfSkKey
|
||||||
|
var skInfo bpfSkInfo
|
||||||
|
for iter.Next(&skKey, &skInfo) {
|
||||||
|
log.Debugf("Connection: %d %s:%d %s:%d %d %d", skKey.Protocol,
|
||||||
|
arrayToIP(skKey.SrcIp, skKey.Ipv6).String(), skKey.SrcPort,
|
||||||
|
arrayToIP(skKey.DstIp, skKey.Ipv6).String(), skKey.DstPort,
|
||||||
|
skInfo.Rx, skInfo.Tx,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// arrayToIP converts IP number array to net.IP
|
||||||
|
func arrayToIP(ipNum [4]uint32, ipv6 uint8) net.IP {
|
||||||
|
if ipv6 == 0 {
|
||||||
|
return unsafe.Slice((*byte)(unsafe.Pointer(&ipNum)), 4)
|
||||||
|
} else {
|
||||||
|
return unsafe.Slice((*byte)(unsafe.Pointer(&ipNum)), 16)
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
|
@ -75,7 +75,7 @@ type bpfProgramSpecs struct {
|
||||||
//
|
//
|
||||||
// It can be passed ebpf.CollectionSpec.Assign.
|
// It can be passed ebpf.CollectionSpec.Assign.
|
||||||
type bpfMapSpecs struct {
|
type bpfMapSpecs struct {
|
||||||
Events *ebpf.MapSpec `ebpf:"events"`
|
PmConnectionEvents *ebpf.MapSpec `ebpf:"pm_connection_events"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// bpfObjects contains all objects after they have been loaded into the kernel.
|
// bpfObjects contains all objects after they have been loaded into the kernel.
|
||||||
|
@ -97,12 +97,12 @@ func (o *bpfObjects) Close() error {
|
||||||
//
|
//
|
||||||
// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign.
|
// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||||
type bpfMaps struct {
|
type bpfMaps struct {
|
||||||
Events *ebpf.Map `ebpf:"events"`
|
PmConnectionEvents *ebpf.Map `ebpf:"pm_connection_events"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *bpfMaps) Close() error {
|
func (m *bpfMaps) Close() error {
|
||||||
return _BpfClose(
|
return _BpfClose(
|
||||||
m.Events,
|
m.PmConnectionEvents,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
BIN
firewall/interception/ebpf/connection_listener/bpf_bpfeb.o
Normal file
BIN
firewall/interception/ebpf/connection_listener/bpf_bpfeb.o
Normal file
Binary file not shown.
|
@ -75,7 +75,7 @@ type bpfProgramSpecs struct {
|
||||||
//
|
//
|
||||||
// It can be passed ebpf.CollectionSpec.Assign.
|
// It can be passed ebpf.CollectionSpec.Assign.
|
||||||
type bpfMapSpecs struct {
|
type bpfMapSpecs struct {
|
||||||
Events *ebpf.MapSpec `ebpf:"events"`
|
PmConnectionEvents *ebpf.MapSpec `ebpf:"pm_connection_events"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// bpfObjects contains all objects after they have been loaded into the kernel.
|
// bpfObjects contains all objects after they have been loaded into the kernel.
|
||||||
|
@ -97,12 +97,12 @@ func (o *bpfObjects) Close() error {
|
||||||
//
|
//
|
||||||
// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign.
|
// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||||
type bpfMaps struct {
|
type bpfMaps struct {
|
||||||
Events *ebpf.Map `ebpf:"events"`
|
PmConnectionEvents *ebpf.Map `ebpf:"pm_connection_events"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *bpfMaps) Close() error {
|
func (m *bpfMaps) Close() error {
|
||||||
return _BpfClose(
|
return _BpfClose(
|
||||||
m.Events,
|
m.PmConnectionEvents,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,6 @@ type infoPacket struct {
|
||||||
pmpacket.Base
|
pmpacket.Base
|
||||||
}
|
}
|
||||||
|
|
||||||
// InfoOnly returns whether the packet is informational only and does not
|
|
||||||
// represent an actual packet.
|
|
||||||
func (pkt *infoPacket) InfoOnly() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadPacketData does nothing on Linux, as data is always fully parsed.
|
// LoadPacketData does nothing on Linux, as data is always fully parsed.
|
||||||
func (pkt *infoPacket) LoadPacketData() error {
|
func (pkt *infoPacket) LoadPacketData() error {
|
||||||
return fmt.Errorf("can't load data in info only packet")
|
return fmt.Errorf("can't load data in info only packet")
|
|
@ -5,21 +5,18 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/link"
|
"github.com/cilium/ebpf/link"
|
||||||
"github.com/cilium/ebpf/ringbuf"
|
"github.com/cilium/ebpf/ringbuf"
|
||||||
"github.com/cilium/ebpf/rlimit"
|
"github.com/cilium/ebpf/rlimit"
|
||||||
|
|
||||||
"github.com/safing/portbase/log"
|
"github.com/safing/portbase/log"
|
||||||
"github.com/safing/portmaster/network/packet"
|
"github.com/safing/portmaster/network/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang -cflags "-O2 -g -Wall -Werror" -type Event bpf program/monitor.c
|
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang -cflags "-O2 -g -Wall -Werror" -type Event bpf ../programs/monitor.c
|
||||||
var stopper chan struct{}
|
var stopper chan struct{}
|
||||||
|
|
||||||
// StartEBPFWorker starts the ebpf worker.
|
|
||||||
func StartEBPFWorker(ch chan packet.Packet) {
|
func StartEBPFWorker(ch chan packet.Packet) {
|
||||||
stopper = make(chan struct{})
|
stopper = make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -35,7 +32,7 @@ func StartEBPFWorker(ch chan packet.Packet) {
|
||||||
log.Errorf("ebpf: failed to load ebpf object: %s", err)
|
log.Errorf("ebpf: failed to load ebpf object: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer objs.Close() //nolint:errcheck
|
defer objs.Close()
|
||||||
|
|
||||||
// Create a link to the tcp_connect program.
|
// Create a link to the tcp_connect program.
|
||||||
linkTCPConnect, err := link.AttachTracing(link.TracingOptions{
|
linkTCPConnect, err := link.AttachTracing(link.TracingOptions{
|
||||||
|
@ -45,7 +42,7 @@ func StartEBPFWorker(ch chan packet.Packet) {
|
||||||
log.Errorf("ebpf: failed to attach to tcp_v4_connect: %s ", err)
|
log.Errorf("ebpf: failed to attach to tcp_v4_connect: %s ", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer linkTCPConnect.Close() //nolint:errcheck
|
defer linkTCPConnect.Close()
|
||||||
|
|
||||||
// Create a link to the udp_v4_connect program.
|
// Create a link to the udp_v4_connect program.
|
||||||
linkUDPV4, err := link.AttachTracing(link.TracingOptions{
|
linkUDPV4, err := link.AttachTracing(link.TracingOptions{
|
||||||
|
@ -55,7 +52,7 @@ func StartEBPFWorker(ch chan packet.Packet) {
|
||||||
log.Errorf("ebpf: failed to attach to udp_v4_connect: %s ", err)
|
log.Errorf("ebpf: failed to attach to udp_v4_connect: %s ", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer linkUDPV4.Close() //nolint:errcheck
|
defer linkUDPV4.Close()
|
||||||
|
|
||||||
// Create a link to the udp_v6_connect program.
|
// Create a link to the udp_v6_connect program.
|
||||||
linkUDPV6, err := link.AttachTracing(link.TracingOptions{
|
linkUDPV6, err := link.AttachTracing(link.TracingOptions{
|
||||||
|
@ -65,14 +62,14 @@ func StartEBPFWorker(ch chan packet.Packet) {
|
||||||
log.Errorf("ebpf: failed to attach to udp_v6_connect: %s ", err)
|
log.Errorf("ebpf: failed to attach to udp_v6_connect: %s ", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer linkUDPV6.Close() //nolint:errcheck
|
defer linkUDPV6.Close()
|
||||||
|
|
||||||
rd, err := ringbuf.NewReader(objs.bpfMaps.Events)
|
rd, err := ringbuf.NewReader(objs.bpfMaps.PmConnectionEvents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("ebpf: failed to open ring buffer: %s", err)
|
log.Errorf("ebpf: failed to open ring buffer: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rd.Close() //nolint:errcheck
|
defer rd.Close()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
<-stopper
|
<-stopper
|
||||||
|
@ -111,7 +108,6 @@ func StartEBPFWorker(ch chan packet.Packet) {
|
||||||
Src: arrayToIP(event.Saddr, packet.IPVersion(event.IpVersion)),
|
Src: arrayToIP(event.Saddr, packet.IPVersion(event.IpVersion)),
|
||||||
Dst: arrayToIP(event.Daddr, packet.IPVersion(event.IpVersion)),
|
Dst: arrayToIP(event.Daddr, packet.IPVersion(event.IpVersion)),
|
||||||
PID: int(event.Pid),
|
PID: int(event.Pid),
|
||||||
SeenAt: time.Now(),
|
|
||||||
}
|
}
|
||||||
if isEventValid(event) {
|
if isEventValid(event) {
|
||||||
log.Debugf("ebpf: PID: %d conn: %s:%d -> %s:%d %s %s", info.PID, info.LocalIP(), info.LocalPort(), info.RemoteIP(), info.RemotePort(), info.Version.String(), info.Protocol.String())
|
log.Debugf("ebpf: PID: %d conn: %s:%d -> %s:%d %s %s", info.PID, info.LocalIP(), info.LocalPort(), info.RemoteIP(), info.RemotePort(), info.Version.String(), info.Protocol.String())
|
||||||
|
@ -127,7 +123,6 @@ func StartEBPFWorker(ch chan packet.Packet) {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// StopEBPFWorker stops the ebpf worker.
|
|
||||||
func StopEBPFWorker() {
|
func StopEBPFWorker() {
|
||||||
close(stopper)
|
close(stopper)
|
||||||
}
|
}
|
||||||
|
@ -153,12 +148,11 @@ func isEventValid(event bpfEvent) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// arrayToIP converts IP number array to net.IP.
|
// arrayToIP converts IP number array to net.IP
|
||||||
func arrayToIP(ipNum [4]uint32, ipVersion packet.IPVersion) net.IP {
|
func arrayToIP(ipNum [4]uint32, ipVersion packet.IPVersion) net.IP {
|
||||||
if ipVersion == packet.IPv4 {
|
if ipVersion == packet.IPv4 {
|
||||||
// FIXME: maybe convertIPv4 from windowskext package
|
|
||||||
return unsafe.Slice((*byte)(unsafe.Pointer(&ipNum)), 4)
|
return unsafe.Slice((*byte)(unsafe.Pointer(&ipNum)), 4)
|
||||||
|
} else {
|
||||||
|
return unsafe.Slice((*byte)(unsafe.Pointer(&ipNum)), 16)
|
||||||
}
|
}
|
||||||
// FIXME: maybe use convertIPv6 from windowskext package
|
|
||||||
return unsafe.Slice((*byte)(unsafe.Pointer(&ipNum)), 16)
|
|
||||||
}
|
}
|
204
firewall/interception/ebpf/programs/bandwidth.c
Normal file
204
firewall/interception/ebpf/programs/bandwidth.c
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
#include "vmlinux-x86.h"
|
||||||
|
#include "bpf/bpf_helpers.h"
|
||||||
|
#include "bpf/bpf_tracing.h"
|
||||||
|
#include "bpf/bpf_core_read.h"
|
||||||
|
|
||||||
|
#define AF_INET 2
|
||||||
|
#define AF_INET6 10
|
||||||
|
|
||||||
|
#define PROTOCOL_TCP 6
|
||||||
|
#define PROTOCOL_UDP 17
|
||||||
|
|
||||||
|
char __license[] SEC("license") = "Dual MIT/GPL";
|
||||||
|
|
||||||
|
struct sk_key {
|
||||||
|
u32 src_ip[4];
|
||||||
|
u32 dst_ip[4];
|
||||||
|
u16 src_port;
|
||||||
|
u16 dst_port;
|
||||||
|
u8 protocol;
|
||||||
|
u8 ipv6;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sk_info {
|
||||||
|
u64 rx;
|
||||||
|
u64 tx;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Max number of connections that will be kept. Increse the number if it's not enough.
|
||||||
|
#define SOCKOPS_MAP_SIZE 5000
|
||||||
|
struct {
|
||||||
|
__uint(type, BPF_MAP_TYPE_LRU_HASH);
|
||||||
|
__uint(max_entries, SOCKOPS_MAP_SIZE);
|
||||||
|
__type(key, struct sk_key);
|
||||||
|
__type(value, struct sk_info);
|
||||||
|
} pm_bandwidth_map SEC(".maps");
|
||||||
|
|
||||||
|
SEC("sockops")
|
||||||
|
int socket_operations(struct bpf_sock_ops *skops) {
|
||||||
|
switch (skops->op) {
|
||||||
|
case BPF_SOCK_OPS_TCP_CONNECT_CB: // Outgoing connections
|
||||||
|
// Set flag so any modification on the socket, will trigger this function.
|
||||||
|
bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_ALL_CB_FLAGS);
|
||||||
|
return 0;
|
||||||
|
case BPF_SOCK_OPS_TCP_LISTEN_CB: // Listening ports
|
||||||
|
bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_ALL_CB_FLAGS);
|
||||||
|
// No rx tx data for this socket object.
|
||||||
|
return 0;
|
||||||
|
case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: // Incoming connections
|
||||||
|
// Set flag so any modification on the socket, will trigger this function.
|
||||||
|
bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_ALL_CB_FLAGS);
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bpf_sock *sk = skops->sk;
|
||||||
|
if (sk == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sk_key key = {0};
|
||||||
|
key.protocol = PROTOCOL_TCP;
|
||||||
|
if(sk->family == AF_INET) {
|
||||||
|
// Generate key for IPv4
|
||||||
|
key.src_ip[0] = sk->src_ip4;
|
||||||
|
key.src_port = sk->src_port;
|
||||||
|
key.dst_ip[0] = sk->dst_ip4;
|
||||||
|
key.dst_port = __builtin_bswap16(sk->dst_port);
|
||||||
|
key.ipv6 = 0;
|
||||||
|
|
||||||
|
struct sk_info newInfo = {0};
|
||||||
|
newInfo.rx = skops->bytes_received;
|
||||||
|
newInfo.tx = skops->bytes_acked;
|
||||||
|
|
||||||
|
bpf_map_update_elem(&pm_bandwidth_map, &key, &newInfo, BPF_ANY);
|
||||||
|
} else if(sk->family == AF_INET6){
|
||||||
|
// Generate key for IPv6
|
||||||
|
for(int i = 0; i < 4; i++) {
|
||||||
|
key.src_ip[i] = sk->src_ip6[i];
|
||||||
|
}
|
||||||
|
key.src_port = sk->src_port;
|
||||||
|
for(int i = 0; i < 4; i++) {
|
||||||
|
key.dst_ip[i] = sk->dst_ip6[i];
|
||||||
|
}
|
||||||
|
key.dst_port = __builtin_bswap16(sk->dst_port);
|
||||||
|
key.ipv6 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// udp_sendmsg hookes to the equvelent kernel function and saves the bandwoth data
|
||||||
|
SEC("fentry/udp_sendmsg")
|
||||||
|
int BPF_PROG(udp_sendmsg, struct sock *sk, struct msghdr *msg, size_t len) {
|
||||||
|
struct sock_common *skc = &sk->__sk_common;
|
||||||
|
|
||||||
|
// Create a key for the map and set all the nececery information.
|
||||||
|
struct sk_key key = {0};
|
||||||
|
key.protocol = PROTOCOL_UDP;
|
||||||
|
key.src_ip[0] = skc->skc_rcv_saddr;
|
||||||
|
key.dst_ip[0] = skc->skc_daddr;
|
||||||
|
key.src_port = skc->skc_num;
|
||||||
|
key.dst_port = __builtin_bswap16(skc->skc_dport);
|
||||||
|
key.ipv6 = 0;
|
||||||
|
|
||||||
|
// Update the map with the new information
|
||||||
|
struct sk_info *info = bpf_map_lookup_elem(&pm_bandwidth_map, &key);
|
||||||
|
if (info != NULL) {
|
||||||
|
__sync_fetch_and_add(&info->tx, len);
|
||||||
|
} else {
|
||||||
|
struct sk_info newInfo = {0};
|
||||||
|
|
||||||
|
newInfo.tx = len;
|
||||||
|
bpf_map_update_elem(&pm_bandwidth_map, &key, &newInfo, BPF_ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// udp_recvmsg hookes to the equvelent kernel function and saves the bandwoth data
|
||||||
|
SEC("fentry/udp_recvmsg")
|
||||||
|
int BPF_PROG(udp_recvmsg, struct sock *sk, struct msghdr *msg, size_t len, int flags, int *addr_len) {
|
||||||
|
struct sock_common *skc = &sk->__sk_common;
|
||||||
|
|
||||||
|
// Create a key for the map and set all the nececery information.
|
||||||
|
struct sk_key key = {0};
|
||||||
|
key.protocol = PROTOCOL_UDP;
|
||||||
|
key.src_ip[0] = skc->skc_rcv_saddr;
|
||||||
|
key.dst_ip[0] = skc->skc_daddr;
|
||||||
|
key.src_port = skc->skc_num;
|
||||||
|
key.dst_port = __builtin_bswap16(skc->skc_dport);
|
||||||
|
key.ipv6 = 0;
|
||||||
|
|
||||||
|
// Update the map with the new information
|
||||||
|
struct sk_info *info = bpf_map_lookup_elem(&pm_bandwidth_map, &key);
|
||||||
|
if (info != NULL) {
|
||||||
|
__sync_fetch_and_add(&info->rx, len);
|
||||||
|
} else {
|
||||||
|
struct sk_info newInfo = {0};
|
||||||
|
|
||||||
|
newInfo.rx = len;
|
||||||
|
bpf_map_update_elem(&pm_bandwidth_map, &key, &newInfo, BPF_ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// udpv6_sendmsg hookes to the equvelent kernel function and saves the bandwoth data
|
||||||
|
SEC("fentry/udpv6_sendmsg")
|
||||||
|
int BPF_PROG(udpv6_sendmsg, struct sock *sk, struct msghdr *msg, size_t len) {
|
||||||
|
struct sock_common *skc = &sk->__sk_common;
|
||||||
|
|
||||||
|
// Create a key for the map and set all the nececery information.
|
||||||
|
struct sk_key key = {0};
|
||||||
|
key.protocol = PROTOCOL_UDP;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
key.src_ip[i] = skc->skc_v6_rcv_saddr.in6_u.u6_addr32[i];
|
||||||
|
key.dst_ip[i] = skc->skc_v6_rcv_saddr.in6_u.u6_addr32[i];
|
||||||
|
}
|
||||||
|
key.src_port = skc->skc_num;
|
||||||
|
key.dst_port = __builtin_bswap16(skc->skc_dport);
|
||||||
|
key.ipv6 = 1;
|
||||||
|
|
||||||
|
// Update the map with the new information
|
||||||
|
struct sk_info *info = bpf_map_lookup_elem(&pm_bandwidth_map, &key);
|
||||||
|
if (info != NULL) {
|
||||||
|
__sync_fetch_and_add(&info->tx, len);
|
||||||
|
} else {
|
||||||
|
struct sk_info newInfo = {0};
|
||||||
|
newInfo.tx = len;
|
||||||
|
bpf_map_update_elem(&pm_bandwidth_map, &key, &newInfo, BPF_ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// udpv6_recvmsg hookes to the equvelent kernel function and saves the bandwoth data
|
||||||
|
SEC("fentry/udpv6_recvmsg")
|
||||||
|
int BPF_PROG(udpv6_recvmsg, struct sock *sk, struct msghdr *msg, size_t len, int flags, int *addr_len) {
|
||||||
|
struct sock_common *skc = &sk->__sk_common;
|
||||||
|
|
||||||
|
// Create a key for the map and set all the nececery information.
|
||||||
|
struct sk_key key = {0};
|
||||||
|
key.protocol = PROTOCOL_UDP;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
key.src_ip[i] = skc->skc_v6_rcv_saddr.in6_u.u6_addr32[i];
|
||||||
|
key.dst_ip[i] = skc->skc_v6_rcv_saddr.in6_u.u6_addr32[i];
|
||||||
|
}
|
||||||
|
key.src_port = skc->skc_num;
|
||||||
|
key.dst_port = __builtin_bswap16(skc->skc_dport);
|
||||||
|
key.ipv6 = 1;
|
||||||
|
|
||||||
|
// Update the map with the new information
|
||||||
|
struct sk_info *info = bpf_map_lookup_elem(&pm_bandwidth_map, &key);
|
||||||
|
if (info != NULL) {
|
||||||
|
__sync_fetch_and_add(&info->rx, len);
|
||||||
|
} else {
|
||||||
|
struct sk_info newInfo = {0};
|
||||||
|
newInfo.rx = len;
|
||||||
|
bpf_map_update_elem(&pm_bandwidth_map, &key, &newInfo, BPF_ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ char __license[] SEC("license") = "GPL";
|
||||||
struct {
|
struct {
|
||||||
__uint(type, BPF_MAP_TYPE_RINGBUF);
|
__uint(type, BPF_MAP_TYPE_RINGBUF);
|
||||||
__uint(max_entries, 1 << 24);
|
__uint(max_entries, 1 << 24);
|
||||||
} events SEC(".maps");
|
} pm_connection_events SEC(".maps");
|
||||||
|
|
||||||
// Event struct that will be sent to Go on each new connection. (The name should be the same as the go generate command)
|
// Event struct that will be sent to Go on each new connection. (The name should be the same as the go generate command)
|
||||||
struct Event {
|
struct Event {
|
||||||
|
@ -41,7 +41,7 @@ SEC("fentry/tcp_connect")
|
||||||
int BPF_PROG(tcp_connect, struct sock *sk) {
|
int BPF_PROG(tcp_connect, struct sock *sk) {
|
||||||
// Alloc space for the event
|
// Alloc space for the event
|
||||||
struct Event *tcp_info;
|
struct Event *tcp_info;
|
||||||
tcp_info = bpf_ringbuf_reserve(&events, sizeof(struct Event), 0);
|
tcp_info = bpf_ringbuf_reserve(&pm_connection_events, sizeof(struct Event), 0);
|
||||||
if (!tcp_info) {
|
if (!tcp_info) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ int BPF_PROG(udp_v4_connect, struct sock *sk) {
|
||||||
|
|
||||||
// Allocate space for the event.
|
// Allocate space for the event.
|
||||||
struct Event *udp_info;
|
struct Event *udp_info;
|
||||||
udp_info = bpf_ringbuf_reserve(&events, sizeof(struct Event), 0);
|
udp_info = bpf_ringbuf_reserve(&pm_connection_events, sizeof(struct Event), 0);
|
||||||
if (!udp_info) {
|
if (!udp_info) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ int BPF_PROG(udp_v6_connect, struct sock *sk) {
|
||||||
|
|
||||||
// Allocate space for the event.
|
// Allocate space for the event.
|
||||||
struct Event *udp_info;
|
struct Event *udp_info;
|
||||||
udp_info = bpf_ringbuf_reserve(&events, sizeof(struct Event), 0);
|
udp_info = bpf_ringbuf_reserve(&pm_connection_events, sizeof(struct Event), 0);
|
||||||
if (!udp_info) {
|
if (!udp_info) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
package interception
|
package interception
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/safing/portmaster/firewall/interception/ebpf"
|
// bandwidth "github.com/safing/portmaster/firewall/interception/ebpf/bandwidth"
|
||||||
|
conn_listener "github.com/safing/portmaster/firewall/interception/ebpf/connection_listener"
|
||||||
"github.com/safing/portmaster/firewall/interception/nfq"
|
"github.com/safing/portmaster/firewall/interception/nfq"
|
||||||
"github.com/safing/portmaster/network"
|
"github.com/safing/portmaster/network"
|
||||||
"github.com/safing/portmaster/network/packet"
|
"github.com/safing/portmaster/network/packet"
|
||||||
|
@ -9,13 +10,19 @@ import (
|
||||||
|
|
||||||
// start starts the interception.
|
// start starts the interception.
|
||||||
func start(ch chan packet.Packet) error {
|
func start(ch chan packet.Packet) error {
|
||||||
ebpf.StartEBPFWorker(ch)
|
// Start ebpf new connection listener
|
||||||
|
conn_listener.StartEBPFWorker(ch)
|
||||||
|
// Start ebpf bandwidth listener
|
||||||
|
// bandwidth.SetupBandwidthInterface()
|
||||||
return StartNfqueueInterception(ch)
|
return StartNfqueueInterception(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// stop starts the interception.
|
// stop starts the interception.
|
||||||
func stop() error {
|
func stop() error {
|
||||||
ebpf.StopEBPFWorker()
|
// Stop ebpf connection listener
|
||||||
|
conn_listener.StopEBPFWorker()
|
||||||
|
// Stop ebpf bandwidth listener
|
||||||
|
// bandwidth.ShutdownBandwithInterface()
|
||||||
return StopNfqueueInterception()
|
return StopNfqueueInterception()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue