fix(ja4ebpf): split bpf2go generate into Ja4Tc + Ja4Ssl, fix RPM systemd-rpm-macros
- Use two separate //go:generate directives (Ja4Tc for tc_capture.c, Ja4Ssl
for uprobe_ssl.c) to avoid duplicate LICENSE symbol and multi-file clang issue
- Update loader.go to hold tcObjs/sslObjs separately with correct field names:
UprobeSslSetFd, UprobeSslReadEntry, UretprobeSslReadExit,
KprobeAccept4Entry, KretprobeAccept4Exit
- Add systemd-rpm-macros to all three RPM build stages (el8/el9/el10)
so that %{_unitdir} macro resolves correctly
- RPMs now build successfully for el8, el9, el10
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@ -45,7 +45,7 @@ COPY services/ja4ebpf/ ./services/ja4ebpf/
|
||||
WORKDIR /build/services/ja4ebpf
|
||||
|
||||
# Génération des bindings eBPF (C → bytecode embarqué en Go)
|
||||
RUN go generate ./internal/loader/
|
||||
RUN GOWORK=off go generate ./internal/loader/
|
||||
|
||||
# Compilation statique
|
||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
||||
@ -56,7 +56,7 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
||||
|
||||
# ── Stage 2 : RPM pour el8 ───────────────────────────────────────────────
|
||||
FROM almalinux:8 AS rpm-el8
|
||||
RUN dnf install -y rpm-build rpmdevtools && dnf clean all && rpmdev-setuptree
|
||||
RUN dnf install -y rpm-build rpmdevtools systemd-rpm-macros && dnf clean all && rpmdev-setuptree
|
||||
|
||||
COPY --from=go-builder /out/ja4ebpf /root/rpmbuild/SOURCES/ja4ebpf
|
||||
COPY services/ja4ebpf/packaging/systemd/ja4ebpf.service /root/rpmbuild/SOURCES/ja4ebpf.service
|
||||
@ -72,7 +72,7 @@ RUN rpmbuild -bb \
|
||||
|
||||
# ── Stage 3 : RPM pour el9 ───────────────────────────────────────────────
|
||||
FROM rockylinux:9 AS rpm-el9
|
||||
RUN dnf install -y rpm-build rpmdevtools && dnf clean all && rpmdev-setuptree
|
||||
RUN dnf install -y rpm-build rpmdevtools systemd-rpm-macros && dnf clean all && rpmdev-setuptree
|
||||
|
||||
COPY --from=go-builder /out/ja4ebpf /root/rpmbuild/SOURCES/ja4ebpf
|
||||
COPY services/ja4ebpf/packaging/systemd/ja4ebpf.service /root/rpmbuild/SOURCES/ja4ebpf.service
|
||||
@ -88,7 +88,7 @@ RUN rpmbuild -bb \
|
||||
|
||||
# ── Stage 4 : RPM pour el10 ──────────────────────────────────────────────
|
||||
FROM almalinux:10 AS rpm-el10
|
||||
RUN dnf install -y rpm-build rpmdevtools && dnf clean all && rpmdev-setuptree
|
||||
RUN dnf install -y rpm-build rpmdevtools systemd-rpm-macros && dnf clean all && rpmdev-setuptree
|
||||
|
||||
COPY --from=go-builder /out/ja4ebpf /root/rpmbuild/SOURCES/ja4ebpf
|
||||
COPY services/ja4ebpf/packaging/systemd/ja4ebpf.service /root/rpmbuild/SOURCES/ja4ebpf.service
|
||||
|
||||
@ -4,9 +4,26 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
/* vmlinux.h (inclus dans les .c) fournit déjà tous les types kernel (__u32, etc.).
|
||||
* N'inclure linux/types.h que si vmlinux.h n'est pas présent. */
|
||||
#ifndef __VMLINUX_H__
|
||||
#include <linux/types.h>
|
||||
#endif
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
/* Constantes TC (linux/pkt_cls.h) — non incluses via vmlinux.h */
|
||||
#ifndef TC_ACT_OK
|
||||
#define TC_ACT_UNSPEC (-1)
|
||||
#define TC_ACT_OK 0
|
||||
#define TC_ACT_RECLASSIFY 1
|
||||
#define TC_ACT_SHOT 2
|
||||
#define TC_ACT_PIPE 3
|
||||
#define TC_ACT_STOLEN 4
|
||||
#define TC_ACT_QUEUED 5
|
||||
#define TC_ACT_REPEAT 6
|
||||
#define TC_ACT_REDIRECT 7
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* Événement TCP SYN : émis pour chaque nouvelle connexion TCP observée
|
||||
* ---------------------------------------------------------------------------*/
|
||||
|
||||
161539
services/ja4ebpf/bpf/headers/vmlinux.h
Normal file
161539
services/ja4ebpf/bpf/headers/vmlinux.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -16,12 +16,14 @@ import (
|
||||
"github.com/cilium/ebpf/rlimit"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang -target amd64 -cflags "-O2 -g -Wall -Werror -D__TARGET_ARCH_x86" Ja4eBPF ../../bpf/tc_capture.c ../../bpf/uprobe_ssl.c -- -I../../bpf/headers
|
||||
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang -target amd64 -cflags "-O2 -g -Wall -D__TARGET_ARCH_x86 -Wno-pass-failed" Ja4Tc ../../bpf/tc_capture.c -- -I../../bpf/headers
|
||||
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang -target amd64 -cflags "-O2 -g -Wall -D__TARGET_ARCH_x86 -Wno-pass-failed" Ja4Ssl ../../bpf/uprobe_ssl.c -- -I../../bpf/headers
|
||||
|
||||
// Loader encapsule les objets eBPF compilés, les liens vers les hooks,
|
||||
// et les readers RingBuffer exposés au pipeline de traitement.
|
||||
type Loader struct {
|
||||
objs *Ja4eBPFObjects // généré par bpf2go
|
||||
tcObjs *Ja4TcObjects // généré par bpf2go (tc_capture.c)
|
||||
sslObjs *Ja4SslObjects // généré par bpf2go (uprobe_ssl.c)
|
||||
tcLink link.Link
|
||||
uprobeLinks []link.Link
|
||||
|
||||
@ -50,56 +52,68 @@ func New() (*Loader, error) {
|
||||
return nil, fmt.Errorf("suppression RLIMIT_MEMLOCK: %w", err)
|
||||
}
|
||||
|
||||
objs := &Ja4eBPFObjects{}
|
||||
// Charger le bytecode eBPF compilé (embarqué par bpf2go).
|
||||
// nil = cilium/ebpf résout le BTF kernel natif automatiquement.
|
||||
if err := LoadJa4eBPFObjects(objs, nil); err != nil {
|
||||
return nil, fmt.Errorf("chargement objets eBPF: %w", err)
|
||||
// Charger les objets TC (tc_capture.c)
|
||||
tcObjs := &Ja4TcObjects{}
|
||||
if err := LoadJa4TcObjects(tcObjs, nil); err != nil {
|
||||
return nil, fmt.Errorf("chargement objets TC eBPF: %w", err)
|
||||
}
|
||||
|
||||
// Charger les objets SSL/uprobe (uprobe_ssl.c)
|
||||
sslObjs := &Ja4SslObjects{}
|
||||
if err := LoadJa4SslObjects(sslObjs, nil); err != nil {
|
||||
tcObjs.Close()
|
||||
return nil, fmt.Errorf("chargement objets SSL eBPF: %w", err)
|
||||
}
|
||||
|
||||
// Initialiser les readers pour chaque ring buffer
|
||||
synReader, err := ringbuf.NewReader(objs.RbTcpSyn)
|
||||
synReader, err := ringbuf.NewReader(tcObjs.RbTcpSyn)
|
||||
if err != nil {
|
||||
objs.Close()
|
||||
sslObjs.Close()
|
||||
tcObjs.Close()
|
||||
return nil, fmt.Errorf("création reader rb_tcp_syn: %w", err)
|
||||
}
|
||||
|
||||
tlsReader, err := ringbuf.NewReader(objs.RbTlsHello)
|
||||
tlsReader, err := ringbuf.NewReader(tcObjs.RbTlsHello)
|
||||
if err != nil {
|
||||
synReader.Close()
|
||||
objs.Close()
|
||||
sslObjs.Close()
|
||||
tcObjs.Close()
|
||||
return nil, fmt.Errorf("création reader rb_tls_hello: %w", err)
|
||||
}
|
||||
|
||||
sslReader, err := ringbuf.NewReader(objs.RbSslData)
|
||||
httpPlainReader, err := ringbuf.NewReader(tcObjs.RbHttpPlain)
|
||||
if err != nil {
|
||||
tlsReader.Close()
|
||||
synReader.Close()
|
||||
objs.Close()
|
||||
return nil, fmt.Errorf("création reader rb_ssl_data: %w", err)
|
||||
}
|
||||
|
||||
acceptReader, err := ringbuf.NewReader(objs.RbAccept)
|
||||
if err != nil {
|
||||
sslReader.Close()
|
||||
tlsReader.Close()
|
||||
synReader.Close()
|
||||
objs.Close()
|
||||
return nil, fmt.Errorf("création reader rb_accept: %w", err)
|
||||
}
|
||||
|
||||
httpPlainReader, err := ringbuf.NewReader(objs.RbHttpPlain)
|
||||
if err != nil {
|
||||
acceptReader.Close()
|
||||
sslReader.Close()
|
||||
tlsReader.Close()
|
||||
synReader.Close()
|
||||
objs.Close()
|
||||
sslObjs.Close()
|
||||
tcObjs.Close()
|
||||
return nil, fmt.Errorf("création reader rb_http_plain: %w", err)
|
||||
}
|
||||
|
||||
sslReader, err := ringbuf.NewReader(sslObjs.RbSslData)
|
||||
if err != nil {
|
||||
httpPlainReader.Close()
|
||||
tlsReader.Close()
|
||||
synReader.Close()
|
||||
sslObjs.Close()
|
||||
tcObjs.Close()
|
||||
return nil, fmt.Errorf("création reader rb_ssl_data: %w", err)
|
||||
}
|
||||
|
||||
acceptReader, err := ringbuf.NewReader(sslObjs.RbAccept)
|
||||
if err != nil {
|
||||
sslReader.Close()
|
||||
httpPlainReader.Close()
|
||||
tlsReader.Close()
|
||||
synReader.Close()
|
||||
sslObjs.Close()
|
||||
tcObjs.Close()
|
||||
return nil, fmt.Errorf("création reader rb_accept: %w", err)
|
||||
}
|
||||
|
||||
return &Loader{
|
||||
objs: objs,
|
||||
tcObjs: tcObjs,
|
||||
sslObjs: sslObjs,
|
||||
SynReader: synReader,
|
||||
TLSReader: tlsReader,
|
||||
SSLReader: sslReader,
|
||||
@ -120,7 +134,7 @@ func (l *Loader) AttachTC(iface string) error {
|
||||
// Attacher le programme TC en ingress via TCX
|
||||
lnk, err := link.AttachTCX(link.TCXOptions{
|
||||
Interface: netIface.Index,
|
||||
Program: l.objs.CaptureTcIngress,
|
||||
Program: l.tcObjs.CaptureTcIngress,
|
||||
Attach: ebpf.AttachTCXIngress,
|
||||
})
|
||||
if err != nil {
|
||||
@ -146,21 +160,21 @@ func (l *Loader) AttachUprobes(sslLibPath string) error {
|
||||
}
|
||||
|
||||
// Uprobe sur SSL_set_fd (entry)
|
||||
setFdLink, err := ex.Uprobe("SSL_set_fd", l.objs.UprobeSSLSetFd, nil)
|
||||
setFdLink, err := ex.Uprobe("SSL_set_fd", l.sslObjs.UprobeSslSetFd, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("attachement uprobe SSL_set_fd: %w", err)
|
||||
}
|
||||
l.uprobeLinks = append(l.uprobeLinks, setFdLink)
|
||||
|
||||
// Uprobe sur SSL_read (entry)
|
||||
readEntryLink, err := ex.Uprobe("SSL_read", l.objs.UprobeSSLReadEntry, nil)
|
||||
readEntryLink, err := ex.Uprobe("SSL_read", l.sslObjs.UprobeSslReadEntry, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("attachement uprobe SSL_read (entry): %w", err)
|
||||
}
|
||||
l.uprobeLinks = append(l.uprobeLinks, readEntryLink)
|
||||
|
||||
// Uretprobe sur SSL_read (exit)
|
||||
readExitLink, err := ex.Uretprobe("SSL_read", l.objs.UretprobeSSLReadExit, nil)
|
||||
readExitLink, err := ex.Uretprobe("SSL_read", l.sslObjs.UretprobeSslReadExit, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("attachement uretprobe SSL_read (exit): %w", err)
|
||||
}
|
||||
@ -172,14 +186,14 @@ func (l *Loader) AttachUprobes(sslLibPath string) error {
|
||||
// AttachAcceptProbe attache les kprobes sur l'appel système accept4.
|
||||
func (l *Loader) AttachAcceptProbe() error {
|
||||
// Kprobe à l'entrée d'accept4
|
||||
kpEntry, err := link.Kprobe("accept4", l.objs.KprobeAccept4Entry, nil)
|
||||
kpEntry, err := link.Kprobe("accept4", l.sslObjs.KprobeAccept4Entry, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("attachement kprobe accept4 (entry): %w", err)
|
||||
}
|
||||
l.uprobeLinks = append(l.uprobeLinks, kpEntry)
|
||||
|
||||
// Kretprobe à la sortie d'accept4
|
||||
kpExit, err := link.Kretprobe("accept4", l.objs.KretprobeAccept4Exit, nil)
|
||||
kpExit, err := link.Kretprobe("accept4", l.sslObjs.KretprobeAccept4Exit, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("attachement kretprobe accept4 (exit): %w", err)
|
||||
}
|
||||
@ -220,8 +234,11 @@ func (l *Loader) Close() error {
|
||||
}
|
||||
|
||||
// Libérer les objets eBPF (maps, programmes)
|
||||
if l.objs != nil {
|
||||
l.objs.Close()
|
||||
if l.sslObjs != nil {
|
||||
l.sslObjs.Close()
|
||||
}
|
||||
if l.tcObjs != nil {
|
||||
l.tcObjs.Close()
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user