feat(ja4ebpf): add SSL_write uprobe, HPACK decoder, and AcceptCache for session correlation
Add uprobe_ssl_write_entry/uretprobe_ssl_write_exit to capture server HTTP
responses via SSL_write with direction=1. Implement full HPACK decoder
(RFC 7541 static table, multi-byte integers, literal representations) for
HTTP/2 header extraction. Add AcceptCache mapping {tgid,fd}→SessionKey
from accept4 events as authoritative source for SSL correlation when BPF
ssl_conn_map has src_ip=0. Add ip_total_length to tcp_syn_event BPF struct.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@ -174,6 +174,81 @@ int uretprobe_ssl_read_exit(struct pt_regs *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* uprobe_ssl_write_entry — Entrée de SSL_write(SSL *ssl, const void *buf, int num)
|
||||
*
|
||||
* Sauvegarde les arguments pour l'uretprobe correspondant.
|
||||
* Réutilise ssl_args_map (même format que SSL_read — un seul thread à la fois).
|
||||
* ===========================================================================*/
|
||||
SEC("uprobe/SSL_write")
|
||||
int uprobe_ssl_write_entry(struct pt_regs *ctx)
|
||||
{
|
||||
__u64 pid_tgid = bpf_get_current_pid_tgid();
|
||||
|
||||
struct ssl_read_args args = {};
|
||||
args.ssl_ptr = (__u64)PT_REGS_PARM1(ctx);
|
||||
args.buf_ptr = (__u64)PT_REGS_PARM2(ctx);
|
||||
args.num = (__u32)PT_REGS_PARM3(ctx);
|
||||
|
||||
bpf_map_update_elem(&ssl_args_map, &pid_tgid, &args, BPF_ANY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* uretprobe_ssl_write_exit — Retour de SSL_write
|
||||
*
|
||||
* Lit le buffer de réponse et l'émet via perf_event_output avec direction=1.
|
||||
* Les données sont les réponses HTTP du serveur (status, headers, body).
|
||||
* ===========================================================================*/
|
||||
SEC("uretprobe/SSL_write")
|
||||
int uretprobe_ssl_write_exit(struct pt_regs *ctx)
|
||||
{
|
||||
__u64 pid_tgid = bpf_get_current_pid_tgid();
|
||||
|
||||
struct ssl_read_args *args = bpf_map_lookup_elem(&ssl_args_map, &pid_tgid);
|
||||
if (!args)
|
||||
return 0;
|
||||
|
||||
long retval = PT_REGS_RC(ctx);
|
||||
if (retval <= 0) {
|
||||
bpf_map_delete_elem(&ssl_args_map, &pid_tgid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__u32 zero = 0;
|
||||
struct ssl_data_event *evt = bpf_map_lookup_elem(&__ssl_buf, &zero);
|
||||
if (!evt) {
|
||||
bpf_map_delete_elem(&ssl_args_map, &pid_tgid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
evt->pid_tgid = pid_tgid;
|
||||
evt->direction = 1; /* écriture = serveur vers client */
|
||||
evt->timestamp_ns = bpf_ktime_get_ns();
|
||||
|
||||
__u32 data_len = (retval > MAX_SSL_DATA) ? MAX_SSL_DATA : (__u32)retval;
|
||||
evt->data_len = data_len;
|
||||
|
||||
bpf_probe_read_user(evt->data, data_len & (MAX_SSL_DATA - 1), (void *)args->buf_ptr);
|
||||
|
||||
struct ssl_conn_info *conn = bpf_map_lookup_elem(&ssl_conn_map, &args->ssl_ptr);
|
||||
if (conn) {
|
||||
evt->fd = conn->fd;
|
||||
evt->src_ip = conn->src_ip;
|
||||
evt->src_port = conn->src_port;
|
||||
} else {
|
||||
evt->fd = 0;
|
||||
evt->src_ip = 0;
|
||||
evt->src_port = 0;
|
||||
}
|
||||
|
||||
bpf_perf_event_output(ctx, &pb_ssl_data, BPF_F_CURRENT_CPU,
|
||||
evt, sizeof(*evt));
|
||||
bpf_map_delete_elem(&ssl_args_map, &pid_tgid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* kprobe_accept4_entry — Entrée de accept4 via tracepoint syscalls
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user