/* uprobe_apache.c — Tracepoints syscall pour capturer le trafic HTTP depuis Apache httpd * * Cette version utilise les tracepoints kernel syscalls/sys_enter_read et * kretprobe sur __x64_sys_read pour capturer les appels système read() du serveur Apache. * Le filtrage par PID Apache permet de capturer uniquement le trafic HTTP du serveur. * * ============================================================================ */ #include "vmlinux.h" #include #include #include "bpf_types.h" /* Taille maximale d'une capture read() */ #define MAX_READ_SIZE 4096 /* ============================================================================ * tracepoint_sys_enter_read — Entrée du syscall read * * Sauvegarde les arguments si le PID correspond à Apache. * Signature: ssize_t read(int fd, void *buf, size_t count); * ============================================================================ */ SEC("tp/syscalls/sys_enter_read") int tp_sys_enter_read(struct trace_event_raw_sys_enter *ctx) { __u64 pid_tgid = bpf_get_current_pid_tgid(); __u32 pid = pid_tgid >> 32; /* Vérifier si ce PID est dans la map apache_pid_map */ __u32 pid_key = pid; __u8 *enabled = bpf_map_lookup_elem(&apache_pid_map, &pid_key); if (!enabled || *enabled == 0) { return 0; /* Pas un PID Apache, ignore */ } /* Sauvegarder les arguments pour l'exit tracepoint */ struct read_args args = {}; args.fd = (__s32)ctx->args[0]; /* fd */ args.buf_ptr = (__u64)ctx->args[1]; /* buf */ args.count = (__u64)ctx->args[2]; /* count */ bpf_map_update_elem(&apache_read_args_map, &pid_tgid, &args, BPF_ANY); return 0; } /* ============================================================================ * kretprobe_sys_exit_read — Sortie du syscall read * * Capture les données lues et les envoie vers pb_apache_http. * Utilise kretprobe pour contourner les limitations de tracepoint exit. * ============================================================================ */ SEC("kretprobe/__x64_sys_read") int kretprobe_sys_exit_read(struct pt_regs *ctx) { __u64 pid_tgid = bpf_get_current_pid_tgid(); /* Récupérer les arguments sauvegardés */ struct read_args *args = bpf_map_lookup_elem(&apache_read_args_map, &pid_tgid); if (!args) { return 0; /* Pas d'arguments correspondants */ } /* Obtenir la valeur de retour (nombre d'octets lus) */ long retval = PT_REGS_RC(ctx); if (retval <= 0 || retval > MAX_READ_SIZE) { /* Erreur, EOF, ou trop de données - nettoyer et sortir */ bpf_map_delete_elem(&apache_read_args_map, &pid_tgid); return 0; } /* Taille à copier (minimum entre retval et la taille disponible) */ __u64 copy_size = retval; if (copy_size > args->count) { copy_size = args->count; } /* Préparer l'événement Apache HTTP */ struct apache_http_event *e = bpf_map_lookup_elem(&__apache_buf, &pid_tgid); if (!e) { bpf_map_delete_elem(&apache_read_args_map, &pid_tgid); return 0; } /* Initialiser l'événement */ __builtin_memset(e, 0, sizeof(*e)); e->pid_tgid = pid_tgid; e->fd = args->fd; e->timestamp_ns = bpf_ktime_get_ns(); /* Récupérer les infos de connexion depuis fd_conn_map */ struct ssl_conn_info *conn_info = bpf_map_lookup_elem(&fd_conn_map, &args->fd); if (conn_info) { e->src_ip = conn_info->src_ip; e->src_port = conn_info->src_port; } /* Copier les données HTTP depuis l'espace utilisateur */ __u64 bytes_read = bpf_probe_read_user_str(e->data, sizeof(e->data), (void *)args->buf_ptr); if (bytes_read > 0) { e->data_len = bytes_read; /* Envoyer vers l'espace utilisateur via perf buffer */ bpf_perf_event_output(ctx, &pb_apache_http, BPF_F_CURRENT_CPU, e, sizeof(*e)); } /* Nettoyer */ bpf_map_delete_elem(&apache_read_args_map, &pid_tgid); return 0; } char LICENSE[] SEC("license") = "GPL";