github.com/cilium/ebpf@v0.10.0/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 // $BPF_CLANG and $BPF_CFLAGS are set by the Makefile. 32 //go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc $BPF_CLANG -cflags $BPF_CFLAGS -type event bpf fentry.c -- -I../headers 33 34 func main() { 35 stopper := make(chan os.Signal, 1) 36 signal.Notify(stopper, os.Interrupt, syscall.SIGTERM) 37 38 // Allow the current process to lock memory for eBPF resources. 39 if err := rlimit.RemoveMemlock(); err != nil { 40 log.Fatal(err) 41 } 42 43 // Load pre-compiled programs and maps into the kernel. 44 objs := bpfObjects{} 45 if err := loadBpfObjects(&objs, nil); err != nil { 46 log.Fatalf("loading objects: %v", err) 47 } 48 defer objs.Close() 49 50 link, err := link.AttachTracing(link.TracingOptions{ 51 Program: objs.bpfPrograms.TcpConnect, 52 }) 53 if err != nil { 54 log.Fatal(err) 55 } 56 defer link.Close() 57 58 rd, err := ringbuf.NewReader(objs.bpfMaps.Events) 59 if err != nil { 60 log.Fatalf("opening ringbuf reader: %s", err) 61 } 62 defer rd.Close() 63 64 go func() { 65 <-stopper 66 67 if err := rd.Close(); err != nil { 68 log.Fatalf("closing ringbuf reader: %s", err) 69 } 70 }() 71 72 log.Printf("%-16s %-15s %-6s -> %-15s %-6s", 73 "Comm", 74 "Src addr", 75 "Port", 76 "Dest addr", 77 "Port", 78 ) 79 80 // bpfEvent is generated by bpf2go. 81 var event bpfEvent 82 for { 83 record, err := rd.Read() 84 if err != nil { 85 if errors.Is(err, ringbuf.ErrClosed) { 86 log.Println("received signal, exiting..") 87 return 88 } 89 log.Printf("reading from reader: %s", err) 90 continue 91 } 92 93 // Parse the ringbuf event entry into a bpfEvent structure. 94 if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.BigEndian, &event); err != nil { 95 log.Printf("parsing ringbuf event: %s", err) 96 continue 97 } 98 99 log.Printf("%-16s %-15s %-6d -> %-15s %-6d", 100 event.Comm, 101 intToIP(event.Saddr), 102 event.Sport, 103 intToIP(event.Daddr), 104 event.Dport, 105 ) 106 } 107 } 108 109 // intToIP converts IPv4 number to net.IP 110 func intToIP(ipNum uint32) net.IP { 111 ip := make(net.IP, 4) 112 binary.BigEndian.PutUint32(ip, ipNum) 113 return ip 114 }