Skip to content

Commit

Permalink
eBPF packet translation tracker
Browse files Browse the repository at this point in the history
Signed-off-by: Mohamed Mahmoud <mmahmoud@redhat.com>
  • Loading branch information
msherif1234 committed Oct 25, 2024
1 parent d5792b0 commit cc18498
Show file tree
Hide file tree
Showing 25 changed files with 454 additions and 66 deletions.
1 change: 1 addition & 0 deletions bpf/configs.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ volatile const u8 enable_flows_filtering = 0;
volatile const u16 dns_port = 0;
volatile const u8 enable_network_events_monitoring = 0;
volatile const u8 network_events_monitoring_groupid = 0;
volatile const u8 enable_pkt_transformation_tracking = 0;
#endif //__CONFIGS_H__
5 changes: 5 additions & 0 deletions bpf/flows.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@
*/
#include "network_events_monitoring.h"

/*
* Defines packets transformation tracker
*/
#include "pkt_transformation.h"

static inline int flow_monitor(struct __sk_buff *skb, u8 direction) {
// If sampling is defined, will only parse 1 out of "sampling" flows
if (sampling > 1 && (bpf_get_prandom_u32() % sampling) != 0) {
Expand Down
13 changes: 7 additions & 6 deletions bpf/headers/vmlinux_amd64.h
Original file line number Diff line number Diff line change
Expand Up @@ -22484,10 +22484,17 @@ union nf_conntrack_proto {

struct nf_ct_ext;

struct nf_conntrack_zone {
u16 id;
u8 flags;
u8 dir;
};

struct nf_conn {
struct nf_conntrack ct_general;
spinlock_t lock;
u32 timeout;
struct nf_conntrack_zone zone;
struct nf_conntrack_tuple_hash tuplehash[2];
long unsigned int status;
possible_net_t ct_net;
Expand All @@ -22499,12 +22506,6 @@ struct nf_conn {
union nf_conntrack_proto proto;
};

struct nf_conntrack_zone {
u16 id;
u8 flags;
u8 dir;
};

struct xt_action_param;

struct xt_mtchk_param;
Expand Down
13 changes: 7 additions & 6 deletions bpf/headers/vmlinux_arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -22582,10 +22582,17 @@ union nf_conntrack_proto {

struct nf_ct_ext;

struct nf_conntrack_zone {
u16 id;
u8 flags;
u8 dir;
};

struct nf_conn {
struct nf_conntrack ct_general;
spinlock_t lock;
u32 timeout;
struct nf_conntrack_zone zone;
struct nf_conntrack_tuple_hash tuplehash[2];
long unsigned int status;
possible_net_t ct_net;
Expand All @@ -22597,12 +22604,6 @@ struct nf_conn {
union nf_conntrack_proto proto;
};

struct nf_conntrack_zone {
u16 id;
u8 flags;
u8 dir;
};

struct icmphdr {
__u8 type;
__u8 code;
Expand Down
13 changes: 7 additions & 6 deletions bpf/headers/vmlinux_ppc64le.h
Original file line number Diff line number Diff line change
Expand Up @@ -67125,10 +67125,17 @@ union nf_conntrack_proto {

struct nf_ct_ext;

struct nf_conntrack_zone {
u16 id;
u8 flags;
u8 dir;
};

struct nf_conn {
struct nf_conntrack ct_general;
spinlock_t lock;
u32 timeout;
struct nf_conntrack_zone zone;
struct nf_conntrack_tuple_hash tuplehash[2];
long unsigned int status;
possible_net_t ct_net;
Expand Down Expand Up @@ -133097,12 +133104,6 @@ struct nf_hook_entries_rcu_head {
void *allocation;
};

struct nf_conntrack_zone {
u16 id;
u8 flags;
u8 dir;
};

struct nf_conntrack_tuple;

struct nf_ct_hook {
Expand Down
146 changes: 146 additions & 0 deletions bpf/pkt_transformation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* Packets Transformations tracker eBPF hooks.
*/

#ifndef __PKT_TRANSFORMATION_H__
#define __PKT_TRANSFORMATION_H__

#include "utils.h"

#define s6_addr in6_u.u6_addr8

static inline void parse_tuple(struct nf_conntrack_tuple *t, struct translated_flow_t *flow,
u16 zone_id, u16 family, bool invert) {
if (invert) {
flow->dport = bpf_ntohs(t->src.u.all);
flow->sport = bpf_ntohs(t->dst.u.all);

switch (family) {
case AF_INET:
__builtin_memcpy(flow->saddr, ip4in6, sizeof(ip4in6));
__builtin_memcpy(flow->daddr, ip4in6, sizeof(ip4in6));
bpf_probe_read(flow->daddr + sizeof(ip4in6), sizeof(u32), &t->src.u3.in.s_addr);
bpf_probe_read(flow->saddr + sizeof(ip4in6), sizeof(u32), &t->dst.u3.in.s_addr);
break;

case AF_INET6:
bpf_probe_read(flow->daddr, IP_MAX_LEN, &t->src.u3.in6.s6_addr);
bpf_probe_read(flow->saddr, IP_MAX_LEN, &t->dst.u3.in6.s6_addr);
break;
}
} else {
flow->dport = bpf_ntohs(t->dst.u.all);
flow->sport = bpf_ntohs(t->src.u.all);

switch (family) {
case AF_INET:
__builtin_memcpy(flow->saddr, ip4in6, sizeof(ip4in6));
__builtin_memcpy(flow->daddr, ip4in6, sizeof(ip4in6));
bpf_probe_read(flow->daddr + sizeof(ip4in6), sizeof(u32), &t->dst.u3.in.s_addr);
bpf_probe_read(flow->saddr + sizeof(ip4in6), sizeof(u32), &t->src.u3.in.s_addr);
break;

case AF_INET6:
bpf_probe_read(flow->daddr, IP_MAX_LEN, &t->dst.u3.in6.s6_addr);
bpf_probe_read(flow->saddr, IP_MAX_LEN, &t->src.u3.in6.s6_addr);
break;
}
}
flow->zone_id = zone_id;
}

static inline long translate_lookup_and_update_flow(flow_id *id, u16 flags,
struct nf_conntrack_tuple *orig_t,
struct nf_conntrack_tuple *reply_t, u64 len,
u16 zone_id, u16 family) {
long ret = 0;
u64 current_time = bpf_ktime_get_ns();
struct translated_flow_t orig;

parse_tuple(orig_t, &orig, zone_id, family, false);

// update id with original flow info
__builtin_memcpy(id->src_ip, orig.saddr, IP_MAX_LEN);
__builtin_memcpy(id->dst_ip, orig.daddr, IP_MAX_LEN);
id->src_port = orig.sport;
id->dst_port = orig.dport;

flow_metrics *aggregate_flow = bpf_map_lookup_elem(&aggregated_flows, id);
if (aggregate_flow != NULL) {
aggregate_flow->end_mono_time_ts = current_time;
parse_tuple(reply_t, &aggregate_flow->translated_flow, zone_id, family, true);
ret = bpf_map_update_elem(&aggregated_flows, id, aggregate_flow, BPF_EXIST);
if (trace_messages && ret != 0) {
bpf_printk("error packet translation updating flow %d\n", ret);
}
}

return ret;
}

static inline int trace_nat_manip_pkt(struct nf_conn *ct, struct sk_buff *skb) {
struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
u16 family = 0, flags = 0, zone_id = 0;
u8 dscp = 0, protocol = 0;
long ret = 0;
u64 len = 0;
flow_id id;

if (!enable_pkt_transformation_tracking) {
return 0;
}
__builtin_memset(&id, 0, sizeof(id));

bpf_probe_read(&tuplehash, sizeof(tuplehash), &ct->tuplehash);

bpf_probe_read(&zone_id, sizeof(zone_id), &ct->zone.id);
bpf_probe_read(&zone_id, sizeof(zone_id), &ct->zone.id);

struct nf_conntrack_tuple *orig_tuple = &tuplehash[IP_CT_DIR_ORIGINAL].tuple;
struct nf_conntrack_tuple *reply_tuple = &tuplehash[IP_CT_DIR_REPLY].tuple;

len = BPF_CORE_READ(skb, len);
id.if_index = BPF_CORE_READ(skb, skb_iif);
// read L2 info
core_fill_in_l2(skb, &id, &family);

// read L3 info
core_fill_in_l3(skb, &id, family, &protocol, &dscp);

// read L4 info
switch (protocol) {
case IPPROTO_TCP:
core_fill_in_tcp(skb, &id, &flags);
break;
case IPPROTO_UDP:
core_fill_in_udp(skb, &id);
break;
case IPPROTO_SCTP:
core_fill_in_sctp(skb, &id);
break;
case IPPROTO_ICMP:
core_fill_in_icmpv4(skb, &id);
break;
case IPPROTO_ICMPV6:
core_fill_in_icmpv6(skb, &id);
break;
default:
fill_in_others_protocol(&id, protocol);
}

bpf_probe_read(&zone_id, sizeof(zone_id), &ct->zone.id);
ret =
translate_lookup_and_update_flow(&id, flags, orig_tuple, reply_tuple, len, zone_id, family);

return ret;
}

SEC("kprobe/nf_nat_manip_pkt")
int BPF_KPROBE(track_nat_manip_pkt) {
struct sk_buff *skb = (struct sk_buff *)PT_REGS_PARM1(ctx);
struct nf_conn *ct = (struct nf_conn *)PT_REGS_PARM2(ctx);

return trace_nat_manip_pkt(ct, skb);
}

#endif /* __PKT_TRANSFORMATION_H__ */
10 changes: 10 additions & 0 deletions bpf/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ typedef struct flow_metrics_t {
u64 flow_rtt;
u8 network_events_idx;
u8 network_events[MAX_NETWORK_EVENTS][MAX_EVENT_MD];
struct translated_flow_t {
u8 saddr[IP_MAX_LEN];
u8 daddr[IP_MAX_LEN];
u16 sport;
u16 dport;
u16 zone_id;
} __attribute__((packed)) translated_flow;
} __attribute__((packed)) flow_metrics;

// Force emitting struct pkt_drops into the ELF.
Expand Down Expand Up @@ -241,4 +248,7 @@ struct filter_value_t {
// Force emitting struct filter_value_t into the ELF.
const struct filter_value_t *unused9 __attribute__((unused));

// Force emitting struct translated_flow_t into the ELF.
const struct translated_flow_t *unused11 __attribute__((unused));

#endif /* __TYPES_H__ */
1 change: 1 addition & 0 deletions pkg/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ func FlowsAgent(cfg *Config) (*Flows, error) {
EnableNetworkEventsMonitoring: cfg.EnableNetworkEventsMonitoring,
NetworkEventsMonitoringGroupID: cfg.NetworkEventsMonitoringGroupID,
EnableFlowFilter: cfg.EnableFlowFilter,
EnablePktTransformation: cfg.EnablePktTransformationTracking,
FilterConfig: &tracer.FilterConfig{
FilterAction: cfg.FilterAction,
FilterDirection: cfg.FilterDirection,
Expand Down
2 changes: 2 additions & 0 deletions pkg/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ type Config struct {
EnableNetworkEventsMonitoring bool `env:"ENABLE_NETWORK_EVENTS_MONITORING" envDefault:"false"`
// NetworkEventsMonitoringGroupID to allow ebpf hook to process samples for specific groupID and ignore the rest
NetworkEventsMonitoringGroupID int `env:"NETWORK_EVENTS_MONITORING_GROUP_ID" envDefault:"10"`
// EnablePktTransformationTracking allow tracking packets after transformation for example NAT, default is false.
EnablePktTransformationTracking bool `env:"ENABLE_PKT_TRANSFORMATION" envDefault:"false"`

/* Deprecated configs are listed below this line
* See manageDeprecatedConfigs function for details
Expand Down
8 changes: 8 additions & 0 deletions pkg/decode/decode_protobuf.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,14 @@ func RecordToMap(fr *model.Record) config.GenericMap {
}
out["NetworkEvents"] = metadata
}

if fr.Metrics.TranslatedFlow.ZoneId != 0 {
out["ZoneId"] = fr.Metrics.TranslatedFlow.ZoneId
out["XlatSrcPort"] = fr.Metrics.TranslatedFlow.Sport
out["XlatDstPort"] = fr.Metrics.TranslatedFlow.Dport
out["XlatSrcAddr"] = model.IP(fr.Metrics.TranslatedFlow.Saddr).String()
out["XlatDstAddr"] = model.IP(fr.Metrics.TranslatedFlow.Daddr).String()
}
return out
}

Expand Down
12 changes: 12 additions & 0 deletions pkg/ebpf/bpf_arm64_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified pkg/ebpf/bpf_arm64_bpfel.o
Binary file not shown.
Loading

0 comments on commit cc18498

Please sign in to comment.