socket.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. package tracer
  2. import (
  3. "fmt"
  4. "github.com/cilium/ebpf"
  5. "github.com/cilium/ebpf/btf"
  6. "k8s.io/klog/v2"
  7. "net"
  8. "os"
  9. "runtime"
  10. "syscall"
  11. "time"
  12. )
  13. func init() {
  14. enable_ebpf_protocol(PROTO_HTTP1)
  15. enable_ebpf_protocol(PROTO_HTTP2)
  16. enable_ebpf_protocol(PROTO_TLS_HTTP1)
  17. enable_ebpf_protocol(PROTO_TLS_HTTP2)
  18. enable_ebpf_protocol(PROTO_DUBBO)
  19. enable_ebpf_protocol(PROTO_SOFARPC)
  20. enable_ebpf_protocol(PROTO_MYSQL)
  21. enable_ebpf_protocol(PROTO_POSTGRESQL)
  22. enable_ebpf_protocol(PROTO_REDIS)
  23. enable_ebpf_protocol(PROTO_KAFKA)
  24. enable_ebpf_protocol(PROTO_MQTT)
  25. enable_ebpf_protocol(PROTO_DNS)
  26. }
  27. func MapInit(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions) {
  28. set_offset_map(collectionSpec, opts)
  29. set_conf_map_default(collectionSpec, opts)
  30. //offsetData := make([]any, runtime.NumCPU())
  31. //for i := range offsetData {
  32. // offsetData[i] = testStruct{
  33. // test_id: 99999,
  34. // }
  35. //}
  36. //if bpf_table_set_value(collectionSpec, opts, "test_heap", offsetData) != ETR_OK {}
  37. //insert_output_prog_to_map(collectionSpec, opts)
  38. }
  39. func MapInsert(collection *ebpf.Collection) {
  40. insert_output_prog_to_map(collection)
  41. insert_adapt_kern_uid_to_map(collection)
  42. // Update go offsets to eBPF "proc_info_map"
  43. //update_proc_info_to_map(collection)
  44. // Update protocol filter array
  45. update_protocol_filter_array(collection)
  46. }
  47. func insert_output_prog_to_map(collection *ebpf.Collection) {
  48. // jmp for tracepoints
  49. __insert_output_prog_to_map(collection, MAP_PROGS_JMP_TP_NAME, PROG_DATA_SUBMIT_NAME_FOR_TP, PROG_DATA_SUBMIT_TP_IDX)
  50. __insert_output_prog_to_map(collection, MAP_PROGS_JMP_TP_NAME, PROG_OUTPUT_DATA_NAME_FOR_TP, PROG_OUTPUT_DATA_TP_IDX)
  51. __insert_output_prog_to_map(collection, MAP_PROGS_JMP_TP_NAME, PROG_IO_EVENT_NAME_FOR_TP, PROG_IO_EVENT_TP_IDX)
  52. // jmp for kprobe/uprobe
  53. __insert_output_prog_to_map(collection, MAP_PROGS_JMP_KP_NAME, PROG_DATA_SUBMIT_NAME_FOR_KP, PROG_DATA_SUBMIT_KP_IDX)
  54. __insert_output_prog_to_map(collection, MAP_PROGS_JMP_KP_NAME, PROG_OUTPUT_DATA_NAME_FOR_KP, PROG_OUTPUT_DATA_KP_IDX)
  55. }
  56. func __insert_output_prog_to_map(collection *ebpf.Collection, mapName string, progName string, key uint32) {
  57. // find in programs
  58. prog, ok := collection.Programs[progName]
  59. fmt.Println(prog, ok)
  60. if ok {
  61. progFd := prog.FD()
  62. code, err := bpf_table_set_value(collection, mapName, key, uint32(progFd))
  63. if err != nil {
  64. klog.Error(err, code)
  65. }
  66. }
  67. }
  68. func update_protocol_filter_array(collection *ebpf.Collection) {
  69. for i := 0; i < PROTO_NUM; i++ {
  70. code, err := bpf_table_set_value(collection, MAP_PROTO_FILTER_NAME, uint32(i), EbpfConfigProtocolFilter[i])
  71. if err != nil || code != ETR_OK {
  72. klog.Error(err, code)
  73. }
  74. }
  75. }
  76. //func update_allow_port_bitmap(collection *ebpf.Collection) {
  77. // for i := 0; i < PROTO_NUM; i++ {
  78. // if bpf_table_set_value(collection, MAP_ALLOW_PORT_BITMAP_NAME, 0, &allow_port_bitmap) != ETR_OK {
  79. // fmt.Println("no")
  80. // } else {
  81. // fmt.Println("ok")
  82. // }
  83. // }
  84. //}
  85. func insert_adapt_kern_uid_to_map(collection *ebpf.Collection) {
  86. pid := os.Getpid()
  87. tid := syscall.Gettid()
  88. adaptKernUID := uint64(pid)<<32 | uint64(tid)
  89. code, err := bpf_table_set_value(collection, MAP_ADAPT_KERN_UID_NAME, 0, uint32(adaptKernUID))
  90. if err != nil || code != ETR_OK {
  91. klog.Error(err, code)
  92. }
  93. }
  94. func enable_ebpf_protocol(protocol int) {
  95. if protocol < PROTO_NUM {
  96. EbpfConfigProtocolFilter[protocol] = 1
  97. }
  98. }
  99. func Offset() {
  100. listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", offsetInferServerAddr, offsetInferServerPort))
  101. if err != nil {
  102. fmt.Errorf("failed to create server listener: %v", err)
  103. return
  104. }
  105. if err := kernelOffsetInferServer(listener); err != nil {
  106. fmt.Printf("Error in kernel_offset_infer_server: %v\n", err)
  107. }
  108. if err := kernelOffsetInferClient(); err != nil {
  109. fmt.Printf("Error in kernel_offset_infer_client: %v\n", err)
  110. }
  111. defer listener.Close()
  112. }
  113. func set_offset_map(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions) {
  114. // 解析BTF数据
  115. if update_offset_map_from_btf_vmlinux(collectionSpec, opts) != ETR_OK {
  116. klog.Infof("[eBPF Kernel Adapt] Set offsets map from btf_vmlinux, not support.\n")
  117. if update_offset_map_default(collectionSpec, opts) != ETR_OK {
  118. klog.Infof("Fatal error, failed to update default offset\n")
  119. }
  120. } else {
  121. klog.Infof("[eBPF Kernel Adapt] Set offsets map from btf_vmlinux, success.\n")
  122. }
  123. }
  124. func set_conf_map_default(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions) {
  125. uidBase := uint64(time.Now().UnixNano()/int64(time.Millisecond)) & 0xffffffffffffff
  126. numCPU := runtime.NumCPU()
  127. tConf := make([]any, numCPU)
  128. for i := range tConf {
  129. socketID := uint64(i)<<56 | uint64(uidBase)
  130. tracerConf := traceConf{
  131. SocketID: socketID,
  132. CoroutineTraceID: socketID,
  133. ThreadTraceID: socketID,
  134. DataLimitMax: 4096,
  135. GoTracingTimeout: 120,
  136. IOEventCollectMode: 1,
  137. IOEventMinimalDuartion: 1000000,
  138. }
  139. tConf[i] = tracerConf
  140. }
  141. if bpf_table_pre_set_value(collectionSpec, opts, MAP_TRACE_CONF_NAME, tConf) != ETR_OK {
  142. klog.Infof("[eBPF Kernel Adapt] Set config map from btf_vmlinux, not support.\n")
  143. } else {
  144. klog.Infof("[eBPF Kernel Adapt] Set config map from btf_vmlinux, success.\n")
  145. }
  146. }
  147. // 解析BTF数据
  148. func update_offset_map_from_btf_vmlinux(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions) int {
  149. btfSpec, err := btf.LoadKernelSpec()
  150. if err != nil || btfSpec == nil {
  151. return ETR_NOTSUPP
  152. }
  153. copied_seq_offs := kernel_struct_field_offset(btfSpec, "tcp_sock", "copied_seq")
  154. write_seq_offs := kernel_struct_field_offset(btfSpec, "tcp_sock", "write_seq")
  155. files_offs := kernel_struct_field_offset(btfSpec, "task_struct", "files")
  156. sk_flags_offs := kernel_struct_field_offset(btfSpec, "sock", "__sk_flags_offset")
  157. if sk_flags_offs == ETR_NOTEXIST {
  158. sk_flags_offs = kernel_struct_field_offset(btfSpec, "sock", "sk_pacing_shift")
  159. if sk_flags_offs > 0 {
  160. sk_flags_offs -= 1
  161. }
  162. }
  163. struct_files_struct_fdt_offset := kernel_struct_field_offset(btfSpec, "files_struct", "fdt")
  164. struct_files_private_data_offset := kernel_struct_field_offset(btfSpec, "file", "private_data")
  165. struct_file_f_inode_offset := kernel_struct_field_offset(btfSpec, "file", "f_inode")
  166. struct_inode_i_mode_offset := kernel_struct_field_offset(btfSpec, "inode", "i_mode")
  167. struct_file_dentry_offset_1 := kernel_struct_field_offset(btfSpec, "file", "f_path")
  168. struct_file_dentry_offset_2 := kernel_struct_field_offset(btfSpec, "path", "dentry")
  169. if struct_file_dentry_offset_1 < 0 ||
  170. struct_file_dentry_offset_2 < 0 {
  171. return ETR_NOTSUPP
  172. }
  173. struct_file_dentry_offset := struct_file_dentry_offset_1 + struct_file_dentry_offset_2
  174. struct_dentry_name_offset_1 := kernel_struct_field_offset(btfSpec, "dentry", "d_name")
  175. struct_dentry_name_offset_2 := kernel_struct_field_offset(btfSpec, "qstr", "name")
  176. if struct_dentry_name_offset_1 < 0 ||
  177. struct_dentry_name_offset_2 < 0 {
  178. return ETR_NOTSUPP
  179. }
  180. struct_dentry_name_offset := struct_dentry_name_offset_1 + struct_dentry_name_offset_2
  181. struct_sock_family_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_family")
  182. struct_sock_saddr_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_rcv_saddr")
  183. struct_sock_daddr_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_daddr")
  184. struct_sock_ip6saddr_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_v6_rcv_saddr")
  185. struct_sock_ip6daddr_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_v6_daddr")
  186. struct_sock_dport_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_dport")
  187. struct_sock_sport_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_num")
  188. struct_sock_skc_state_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_state")
  189. struct_sock_common_ipv6only_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_flags")
  190. klog.Infof("Offsets from BTF vmlinux:\n")
  191. klog.Infof(" copied_seq_offs: 0x%x\n", copied_seq_offs)
  192. klog.Infof(" write_seq_offs: 0x%x\n", write_seq_offs)
  193. klog.Infof(" files_offs: 0x%x\n", files_offs)
  194. klog.Infof(" sk_flags_offs: 0x%x\n", sk_flags_offs)
  195. klog.Infof(" struct_files_struct_fdt_offset: 0x%x\n", struct_files_struct_fdt_offset)
  196. klog.Infof(" struct_files_private_data_offset: 0x%x\n", struct_files_private_data_offset)
  197. klog.Infof(" struct_file_f_inode_offset: 0x%x\n", struct_file_f_inode_offset)
  198. klog.Infof(" struct_inode_i_mode_offset: 0x%x\n", struct_inode_i_mode_offset)
  199. klog.Infof(" struct_file_dentry_offset: 0x%x\n", struct_file_dentry_offset)
  200. klog.Infof(" struct_dentry_name_offset: 0x%x\n", struct_dentry_name_offset)
  201. klog.Infof(" struct_sock_family_offset: 0x%x\n", struct_sock_family_offset)
  202. klog.Infof(" struct_sock_saddr_offset: 0x%x\n", struct_sock_saddr_offset)
  203. klog.Infof(" struct_sock_daddr_offset: 0x%x\n", struct_sock_daddr_offset)
  204. klog.Infof(" struct_sock_ip6saddr_offset: 0x%x\n", struct_sock_ip6saddr_offset)
  205. klog.Infof(" struct_sock_ip6daddr_offset: 0x%x\n", struct_sock_ip6daddr_offset)
  206. klog.Infof(" struct_sock_dport_offset: 0x%x\n", struct_sock_dport_offset)
  207. klog.Infof(" struct_sock_sport_offset: 0x%x\n", struct_sock_sport_offset)
  208. klog.Infof(" struct_sock_skc_state_offset: 0x%x\n", struct_sock_skc_state_offset)
  209. klog.Infof(" struct_sock_common_ipv6only_offset: 0x%x\n", struct_sock_common_ipv6only_offset)
  210. if copied_seq_offs < 0 || write_seq_offs < 0 || files_offs < 0 ||
  211. sk_flags_offs < 0 || struct_files_struct_fdt_offset < 0 ||
  212. struct_files_private_data_offset < 0 ||
  213. struct_file_f_inode_offset < 0 || struct_inode_i_mode_offset < 0 ||
  214. struct_inode_i_mode_offset < 0 || struct_file_dentry_offset < 0 ||
  215. struct_dentry_name_offset < 0 || struct_sock_family_offset < 0 ||
  216. struct_sock_saddr_offset < 0 || struct_sock_daddr_offset < 0 ||
  217. struct_sock_ip6saddr_offset < 0 ||
  218. struct_sock_ip6daddr_offset < 0 || struct_sock_dport_offset < 0 ||
  219. struct_sock_sport_offset < 0 || struct_sock_skc_state_offset < 0 ||
  220. struct_sock_common_ipv6only_offset < 0 {
  221. return ETR_NOTSUPP
  222. }
  223. offset := bpfOffsetParam{}
  224. offset.Ready = 1
  225. offset.TaskFilesOffset = uint32(files_offs)
  226. offset.SockFlagsOffset = uint32(sk_flags_offs)
  227. offset.TcpSockCopiedSeqOffset = uint32(copied_seq_offs)
  228. offset.TcpSockWriteSeqOffset = uint32(write_seq_offs)
  229. offset.StructFilesStructFdtOffset = uint32(struct_files_struct_fdt_offset)
  230. offset.StructFilesPrivateDataOffset = uint32(struct_files_private_data_offset)
  231. offset.StructFileFInodeOffset = uint32(struct_file_f_inode_offset)
  232. offset.StructInodeIModeOffset = uint32(struct_inode_i_mode_offset)
  233. offset.StructFileDentryOffset = uint32(struct_file_dentry_offset)
  234. offset.StructDentryNameOffset = uint32(struct_dentry_name_offset)
  235. offset.StructSockFamilyOffset = uint32(struct_sock_family_offset)
  236. offset.StructSockSaddrOffset = uint32(struct_sock_saddr_offset)
  237. offset.StructSockDaddrOffset = uint32(struct_sock_daddr_offset)
  238. offset.StructSockIp6saddrOffset = uint32(struct_sock_ip6saddr_offset)
  239. offset.StructSockIp6daddrOffset = uint32(struct_sock_ip6daddr_offset)
  240. offset.StructSockDportOffset = uint32(struct_sock_dport_offset)
  241. offset.StructSockSportOffset = uint32(struct_sock_sport_offset)
  242. offset.StructSockSkcStateOffset = uint32(struct_sock_skc_state_offset)
  243. offset.StructSockCommonIpv6onlyOffset = uint32(struct_sock_common_ipv6only_offset)
  244. if update_offsets_table(collectionSpec, opts, offset) != ETR_OK {
  245. return ETR_UPDATE_MAP_FAILD
  246. }
  247. return ETR_OK
  248. }
  249. func update_offset_map_default(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions) int {
  250. offset := bpfOffsetParam{}
  251. offset.StructFilesStructFdtOffset = 0x20
  252. offset.StructFilesPrivateDataOffset = 0xc8
  253. offset.StructFileFInodeOffset = 0x20
  254. offset.StructInodeIModeOffset = 0x00
  255. offset.StructFileDentryOffset = 0x18
  256. offset.StructDentryNameOffset = 0x28
  257. offset.StructSockFamilyOffset = 0x10
  258. offset.StructSockSaddrOffset = 0x4
  259. offset.StructSockDaddrOffset = 0x0
  260. offset.StructSockIp6saddrOffset = 0x48
  261. offset.StructSockIp6daddrOffset = 0x38
  262. offset.StructSockDportOffset = 0xc
  263. offset.StructSockSportOffset = 0xe
  264. offset.StructSockSkcStateOffset = 0x12
  265. offset.StructSockCommonIpv6onlyOffset = 0x13
  266. if update_offsets_table(collectionSpec, opts, offset) != ETR_OK {
  267. return ETR_UPDATE_MAP_FAILD
  268. }
  269. return ETR_OK
  270. }
  271. func update_offsets_table(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions, offset bpfOffsetParam) int {
  272. numCPU := runtime.NumCPU()
  273. offsetData := make([]any, numCPU)
  274. for i := range offsetData {
  275. offsetData[i] = offset
  276. }
  277. if bpf_table_pre_set_value(collectionSpec, opts, MAP_MEMBERS_OFFSET_NAME, offsetData) != ETR_OK {
  278. return ETR_UPDATE_MAP_FAILD
  279. }
  280. return ETR_OK
  281. }
  282. func SetConstants(collectionSpec *ebpf.CollectionSpec) {
  283. consts := map[string]interface{}{
  284. "buckets_ptr_pos": int64(16),
  285. "ctx_ptr_pos": int64(232),
  286. "headers_ptr_pos": int64(56),
  287. "host_pos": int64(128),
  288. "request_host_pos": int64(128),
  289. "is_registers_abi": true,
  290. "method_ptr_pos": int64(0),
  291. "path_ptr_pos": int64(56),
  292. "proto_pos": int64(24),
  293. "remote_addr_pos": int64(176),
  294. "req_ptr_pos": int64(8),
  295. "status_code_pos": int64(120),
  296. "url_ptr_pos": int64(16),
  297. // todo in process
  298. "total_cpus": int64(2),
  299. "start_addr": int64(139867793264640),
  300. "end_addr": int64(139867793330176),
  301. }
  302. err := collectionSpec.RewriteConstants(consts)
  303. fmt.Println("err----------------", err)
  304. fmt.Println("err", consts)
  305. }