fix(ebpf): rename Apache BPF maps to avoid conflicts with nginx
- Rename apache_pid_map to apache_http_pid_map - Rename apache_read_args_map to apache_http_recv_args_map - Update all references in C code and Go loader - Attempt both tracepoints and kretprobe for Apache HTTP capture Test results: - Rocky 9 (kernel 5.14): nginx HTTP capture works perfectly - Rocky 10 (kernel 6.12): Apache HTTP capture not working (headers=0) - CentOS 8 (kernel 4.18): Apache HTTP capture not working The issue appears to be that Apache event MPM may not use recvfrom() in the same way as nginx, or uses a different code path. Further investigation needed for Apache HTTP capture. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@ -320,7 +320,7 @@ struct {
|
|||||||
__uint(max_entries, 16);
|
__uint(max_entries, 16);
|
||||||
__type(key, __u32);
|
__type(key, __u32);
|
||||||
__type(value, __u8);
|
__type(value, __u8);
|
||||||
} apache_pid_map SEC(".maps");
|
} apache_http_pid_map SEC(".maps");
|
||||||
|
|
||||||
/* Hash map : pid_tgid → read_args (arguments read entry pour Apache) */
|
/* Hash map : pid_tgid → read_args (arguments read entry pour Apache) */
|
||||||
struct {
|
struct {
|
||||||
@ -328,7 +328,7 @@ struct {
|
|||||||
__uint(max_entries, 10240);
|
__uint(max_entries, 10240);
|
||||||
__type(key, __u64);
|
__type(key, __u64);
|
||||||
__type(value, struct read_args);
|
__type(value, struct read_args);
|
||||||
} apache_read_args_map SEC(".maps");
|
} apache_http_recv_args_map SEC(".maps");
|
||||||
|
|
||||||
/* PERCPU_ARRAY temporaire pour apache_http_event (taille ~4KB) */
|
/* PERCPU_ARRAY temporaire pour apache_http_event (taille ~4KB) */
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
/* uprobe_apache.c — Tracepoints syscall pour capturer le trafic HTTP depuis Apache httpd
|
/* uprobe_apache.c — Kretprobe pour capturer le trafic HTTP depuis Apache httpd
|
||||||
*
|
*
|
||||||
* Cette version utilise kretprobe sur __x64_sys_recvfrom pour capturer les appels
|
* Cette version utilise kretprobe sur __x64_sys_recvfrom (identique à nginx)
|
||||||
* système recvfrom() du serveur Apache httpd (identique à nginx).
|
* pour capturer les appels système recvfrom() du serveur Apache httpd.
|
||||||
* Le filtrage par PID Apache permet de capturer uniquement le trafic HTTP du serveur.
|
|
||||||
*
|
*
|
||||||
* ============================================================================
|
* ============================================================================
|
||||||
*/
|
*/
|
||||||
@ -19,8 +18,7 @@
|
|||||||
* kretprobe_sys_exit_recvfrom — Sortie du syscall recvfrom
|
* kretprobe_sys_exit_recvfrom — Sortie du syscall recvfrom
|
||||||
*
|
*
|
||||||
* Capture les données reçues et les envoie vers pb_apache_http.
|
* Capture les données reçues et les envoie vers pb_apache_http.
|
||||||
* Signature: ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
|
* Utilise kretprobe pour contourner les limitations de tracepoint exit.
|
||||||
* struct sockaddr *src_addr, socklen_t *addrlen);
|
|
||||||
* ============================================================================
|
* ============================================================================
|
||||||
*/
|
*/
|
||||||
SEC("kretprobe/__x64_sys_recvfrom")
|
SEC("kretprobe/__x64_sys_recvfrom")
|
||||||
@ -29,17 +27,18 @@ int kretprobe_sys_exit_recvfrom(struct pt_regs *ctx)
|
|||||||
__u64 pid_tgid = bpf_get_current_pid_tgid();
|
__u64 pid_tgid = bpf_get_current_pid_tgid();
|
||||||
__u32 pid = pid_tgid >> 32;
|
__u32 pid = pid_tgid >> 32;
|
||||||
|
|
||||||
/* Vérifier si ce PID est dans la map apache_pid_map */
|
/* Vérifier si ce PID est dans la map apache_http_pid_map */
|
||||||
__u32 pid_key = pid;
|
__u32 pid_key = pid;
|
||||||
__u8 *enabled = bpf_map_lookup_elem(&apache_pid_map, &pid_key);
|
__u8 *enabled = bpf_map_lookup_elem(&apache_http_pid_map, &pid_key);
|
||||||
if (!enabled || *enabled == 0) {
|
if (!enabled || *enabled == 0) {
|
||||||
return 0; /* Pas un PID Apache, ignore */
|
return 0; /* Pas un PID Apache, ignore */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Obtenir la valeur de retour (nombre d'octets reçus) */
|
/* Obtenir la valeur de retour (nombre d'octets reçus) */
|
||||||
long retval = PT_REGS_RC(ctx);
|
long retval = PT_REGS_RC(ctx);
|
||||||
if (retval <= 0 || retval > MAX_RECV_SIZE) {
|
if (retval < 0 || retval > MAX_RECV_SIZE) {
|
||||||
return 0; /* Erreur, EOF, ou trop de données */
|
/* Erreur ou trop de données */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Préparer l'événement Apache HTTP */
|
/* Préparer l'événement Apache HTTP */
|
||||||
@ -50,8 +49,8 @@ int kretprobe_sys_exit_recvfrom(struct pt_regs *ctx)
|
|||||||
|
|
||||||
/* Initialiser l'événement */
|
/* Initialiser l'événement */
|
||||||
e->pid_tgid = pid_tgid;
|
e->pid_tgid = pid_tgid;
|
||||||
e->fd = 0; /* sockfd n'est pas disponible en kretprobe sans arguments sauvegardés */
|
e->fd = 0;
|
||||||
e->src_ip = 0; /* Sera rempli via corrélation TC si disponible */
|
e->src_ip = 0;
|
||||||
e->src_port = 0;
|
e->src_port = 0;
|
||||||
e->timestamp_ns = bpf_ktime_get_ns();
|
e->timestamp_ns = bpf_ktime_get_ns();
|
||||||
e->method_len = 0;
|
e->method_len = 0;
|
||||||
@ -60,18 +59,17 @@ int kretprobe_sys_exit_recvfrom(struct pt_regs *ctx)
|
|||||||
e->body_len = 0;
|
e->body_len = 0;
|
||||||
e->data_len = 0;
|
e->data_len = 0;
|
||||||
|
|
||||||
/* Copier les données brutes depuis la stack (recvfrom buffer)
|
/* Copier les données depuis le buffer utilisateur (2ème argument: RSI) */
|
||||||
* Note: Comme nous n'avons pas sauvegardé les arguments à l'entrée,
|
__u64 buf_ptr = PT_REGS_PARM2(ctx);
|
||||||
* nous ne pouvons pas accéder au buffer utilisateur directement.
|
|
||||||
* Pour Apache, nous utilisons une approche simplifiée qui capture
|
/* Limiter la copie à retval octets */
|
||||||
* les données depuis le contexte BPF disponible.
|
__u64 copy_size = retval;
|
||||||
*/
|
if (copy_size > sizeof(e->data)) {
|
||||||
if (retval > 0 && retval < sizeof(e->data)) {
|
copy_size = sizeof(e->data);
|
||||||
/* Lire depuis le premier argument de la stack (buf pointer)
|
}
|
||||||
* Sur x86_64, les arguments sont dans: RDI=sockfd, RSI=buf, RDX=len, R10=flags
|
|
||||||
*/
|
if (copy_size > 0) {
|
||||||
__u64 buf_ptr = PT_REGS_PARM2(ctx);
|
__u64 bytes_read = bpf_probe_read_user_str(e->data, copy_size, (void *)buf_ptr);
|
||||||
__u64 bytes_read = bpf_probe_read_user_str(e->data, sizeof(e->data), (void *)buf_ptr);
|
|
||||||
if (bytes_read > 0) {
|
if (bytes_read > 0) {
|
||||||
e->data_len = bytes_read;
|
e->data_len = bytes_read;
|
||||||
/* Envoyer vers l'espace utilisateur via perf buffer */
|
/* Envoyer vers l'espace utilisateur via perf buffer */
|
||||||
|
|||||||
@ -307,7 +307,7 @@ func New() (*Loader, error) {
|
|||||||
allowedPorts: tcObjs.AllowedPorts,
|
allowedPorts: tcObjs.AllowedPorts,
|
||||||
ignoredSrc: tcObjs.IgnoredSrc,
|
ignoredSrc: tcObjs.IgnoredSrc,
|
||||||
nginxPidMap: nginxObjs.NginxPidMap,
|
nginxPidMap: nginxObjs.NginxPidMap,
|
||||||
apachePidMap: apacheObjs.ApachePidMap,
|
apachePidMap: apacheObjs.ApacheHttpPidMap,
|
||||||
SynReader: synReader,
|
SynReader: synReader,
|
||||||
TLSReader: tlsReader,
|
TLSReader: tlsReader,
|
||||||
SSLReader: sslReader,
|
SSLReader: sslReader,
|
||||||
@ -539,8 +539,8 @@ func findNginxPIDs() ([]uint32, error) {
|
|||||||
// kernel sys_enter_read et kretprobe __x64_sys_read.
|
// kernel sys_enter_read et kretprobe __x64_sys_read.
|
||||||
// Le PID Apache est ajouté à la map apache_pid_map pour filtrer les appels read().
|
// Le PID Apache est ajouté à la map apache_pid_map pour filtrer les appels read().
|
||||||
func (l *Loader) AttachUprobesApache() error {
|
func (l *Loader) AttachUprobesApache() error {
|
||||||
// Utilisation de Kretprobe pour __x64_sys_recvfrom
|
// Utilisation de Kretprobe pour __x64_sys_recvfrom (identique à nginx)
|
||||||
// Apache httpd utilise recvfrom() pour lire les requêtes HTTP (similaire à nginx)
|
// Apache httpd utilise recvfrom() pour lire les requêtes HTTP
|
||||||
kp, err := link.Kretprobe("__x64_sys_recvfrom",
|
kp, err := link.Kretprobe("__x64_sys_recvfrom",
|
||||||
l.apacheObjs.KretprobeSysExitRecvfrom, &link.KprobeOptions{})
|
l.apacheObjs.KretprobeSysExitRecvfrom, &link.KprobeOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user