github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/examples/fentry/main.go (about) 1 // This program demonstrates attaching a fentry eBPF program to 2 // tcp_connect. It prints the command/IPs/ports information 3 // once the host sent a TCP SYN packet to a destination. 4 // It supports IPv4 at this example. 5 // 6 // Sample output: 7 // 8 // examples# go run -exec sudo ./fentry 9 // 2021/11/06 17:51:15 Comm Src addr Port -> Dest addr Port 10 // 2021/11/06 17:51:25 wget 10.0.2.15 49850 -> 142.250.72.228 443 11 // 2021/11/06 17:51:46 ssh 10.0.2.15 58854 -> 10.0.2.1 22 12 // 2021/11/06 18:13:15 curl 10.0.2.15 54268 -> 104.21.1.217 80 13 14 package main 15 16 import ( 17 "bytes" 18 "encoding/binary" 19 "errors" 20 "log" 21 "net" 22 "os" 23 "os/signal" 24 "syscall" 25 26 "github.com/cilium/ebpf/link" 27 "github.com/cilium/ebpf/ringbuf" 28 "github.com/cilium/ebpf/rlimit" 29 ) 30 31 //go:generate go run github.com/cilium/ebpf/cmd/bpf2go -type event bpf fentry.c -- -I../headers 32 33 func main() { 34 stopper := make(chan os.Signal, 1) 35 signal.Notify(stopper, os.Interrupt, syscall.SIGTERM) 36 37 // Allow the current process to lock memory for eBPF resources. 38 if err := rlimit.RemoveMemlock(); err != nil { 39 log.Fatal(err) 40 } 41 42 // Load pre-compiled programs and maps into the kernel. 43 objs := bpfObjects{} 44 if err := loadBpfObjects(&objs, nil); err != nil { 45 log.Fatalf("loading objects: %v", err) 46 } 47 defer objs.Close() 48 49 link, err := link.AttachTracing(link.TracingOptions{ 50 Program: objs.bpfPrograms.TcpConnect, 51 }) 52 if err != nil { 53 log.Fatal(err) 54 } 55 defer link.Close() 56 57 rd, err := ringbuf.NewReader(objs.bpfMaps.Events) 58 if err != nil { 59 log.Fatalf("opening ringbuf reader: %s", err) 60 } 61 defer rd.Close() 62 63 go func() { 64 <-stopper 65 66 if err := rd.Close(); err != nil { 67 log.Fatalf("closing ringbuf reader: %s", err) 68 } 69 }() 70 71 log.Printf("%-16s %-15s %-6s -> %-15s %-6s", 72 "Comm", 73 "Src addr", 74 "Port", 75 "Dest addr", 76 "Port", 77 ) 78 79 // bpfEvent is generated by bpf2go. 80 var event bpfEvent 81 for { 82 record, err := rd.Read() 83 if err != nil { 84 if errors.Is(err, ringbuf.ErrClosed) { 85 log.Println("received signal, exiting..") 86 return 87 } 88 log.Printf("reading from reader: %s", err) 89 continue 90 } 91 92 // Parse the ringbuf event entry into a bpfEvent structure. 93 if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.BigEndian, &event); err != nil { 94 log.Printf("parsing ringbuf event: %s", err) 95 continue 96 } 97 98 log.Printf("%-16s %-15s %-6d -> %-15s %-6d", 99 event.Comm, 100 intToIP(event.Saddr), 101 event.Sport, 102 intToIP(event.Daddr), 103 event.Dport, 104 ) 105 } 106 } 107 108 // intToIP converts IPv4 number to net.IP 109 func intToIP(ipNum uint32) net.IP { 110 ip := make(net.IP, 4) 111 binary.BigEndian.PutUint32(ip, ipNum) 112 return ip 113 }