From 79147e6554c71d99ede54e6b5c4a65dbc1d78439 Mon Sep 17 00:00:00 2001 From: r-caamano Date: Wed, 28 Aug 2024 14:48:53 +0000 Subject: [PATCH] Added logging for IPv4 Masquerade, updated CHANGELOG --- CHANGELOG.md | 4 ++- src/zfw.c | 36 +++++++++++++++++++++ src/zfw_monitor.c | 36 +++++++++++++++++++++ src/zfw_tc_ingress.c | 51 +++++++++++++++++++++-------- src/zfw_tc_outbound_track.c | 64 +++++++++++++++++++++++++++++++++---- 5 files changed, 171 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c89773..5ed7296 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,9 @@ All notable changes to this project will be documented in this file. The format ### # [0.8.15] - 2024-08-26 - Refactored all startup scripts to default InternalInterfaces to have outbound tracking enabled -- Refactored masquerade to use dynamic PAT vs static PAT +- Refactored IPv4 masquerade to use dynamic PAT vs static PAT and added RB logging +- Fixed issue where if IPv4 udp checksum was 0 masquerade erroneously attempted to recalculate the checksum + ### diff --git a/src/zfw.c b/src/zfw.c index 3942934..ded555a 100644 --- a/src/zfw.c +++ b/src/zfw.c @@ -93,6 +93,10 @@ #define CLIENT_INITIATED_ICMP_ECHO 29 #define IP6_HEADER_TOO_BIG 30 #define IPV6_TUPLE_TOO_BIG 31 +#define REVERSE_MASQUERADE_ENTRY_REMOVED 32 +#define MASQUERADE_ENTRY_REMOVED 33 +#define REVERSE_MASQUERADE_ENTRY_ADDED 34 +#define MASQUERADE_ENTRY_ADDED 35 bool ddos = false; bool add = false; @@ -3110,6 +3114,22 @@ static int process_events(void *ctx, void *data, size_t len) { state = "MATCHED_DROP_FILTER"; } + else if (code == REVERSE_MASQUERADE_ENTRY_ADDED) + { + state = "REVERSE_MASQUERADE_ENTRY_ADDED"; + } + else if (code == REVERSE_MASQUERADE_ENTRY_REMOVED) + { + state = "REVERSE_MASQUERADE_ENTRY_REMOVED"; + } + else if (code == MASQUERADE_ENTRY_ADDED) + { + state = "MASQUERADE_ENTRY_ADDED"; + } + else if (code == MASQUERADE_ENTRY_REMOVED) + { + state = "MASQUERADE_ENTRY_REMOVED"; + } if (state) { @@ -3448,6 +3468,22 @@ static int process_events(void *ctx, void *data, size_t len) { state = "MATCHED_DROP_FILTER"; } + else if (code == REVERSE_MASQUERADE_ENTRY_ADDED) + { + state = "REVERSE_MASQUERADE_ENTRY_ADDED"; + } + else if (code == REVERSE_MASQUERADE_ENTRY_REMOVED) + { + state = "REVERSE_MASQUERADE_ENTRY_REMOVED"; + } + else if (code == MASQUERADE_ENTRY_ADDED) + { + state = "MASQUERADE_ENTRY_ADDED"; + } + else if (code == MASQUERADE_ENTRY_REMOVED) + { + state = "MASQUERADE_ENTRY_REMOVED"; + } if (state) diff --git a/src/zfw_monitor.c b/src/zfw_monitor.c index 33ee3c4..9d9806d 100644 --- a/src/zfw_monitor.c +++ b/src/zfw_monitor.c @@ -70,6 +70,10 @@ #define CLIENT_INITIATED_ICMP_ECHO 29 #define IP6_HEADER_TOO_BIG 30 #define IPV6_TUPLE_TOO_BIG 31 +#define REVERSE_MASQUERADE_ENTRY_REMOVED 32 +#define MASQUERADE_ENTRY_REMOVED 33 +#define REVERSE_MASQUERADE_ENTRY_ADDED 34 +#define MASQUERADE_ENTRY_ADDED 35 bool logging = false; bool monitor = false; @@ -510,6 +514,22 @@ static int process_events(void *ctx, void *data, size_t len) { state = "MATCHED_DROP_FILTER"; } + else if (code == REVERSE_MASQUERADE_ENTRY_ADDED) + { + state = "REVERSE_MASQUERADE_ENTRY_ADDED"; + } + else if (code == REVERSE_MASQUERADE_ENTRY_REMOVED) + { + state = "REVERSE_MASQUERADE_ENTRY_REMOVED"; + } + else if (code == MASQUERADE_ENTRY_ADDED) + { + state = "MASQUERADE_ENTRY_ADDED"; + } + else if (code == MASQUERADE_ENTRY_REMOVED) + { + state = "MASQUERADE_ENTRY_REMOVED"; + } if (state) { @@ -848,6 +868,22 @@ static int process_events(void *ctx, void *data, size_t len) { state = "MATCHED_DROP_FILTER"; } + else if (code == REVERSE_MASQUERADE_ENTRY_ADDED) + { + state = "REVERSE_MASQUERADE_ENTRY_ADDED"; + } + else if (code == REVERSE_MASQUERADE_ENTRY_REMOVED) + { + state = "REVERSE_MASQUERADE_ENTRY_REMOVED"; + } + else if (code == MASQUERADE_ENTRY_ADDED) + { + state = "MASQUERADE_ENTRY_ADDED"; + } + else if (code == MASQUERADE_ENTRY_REMOVED) + { + state = "MASQUERADE_ENTRY_REMOVED"; + } if (state) diff --git a/src/zfw_tc_ingress.c b/src/zfw_tc_ingress.c index 1289354..97af5a4 100644 --- a/src/zfw_tc_ingress.c +++ b/src/zfw_tc_ingress.c @@ -78,6 +78,8 @@ #define ICMP_MATCHED_ACTIVE_STATE 28 #define IP6_HEADER_TOO_BIG 30 #define IPV6_TUPLE_TOO_BIG 31 +#define REVERSE_MASQUERADE_ENTRY_REMOVED 32 +#define MASQUERADE_ENTRY_REMOVED 33 #ifndef memcpy #define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n)) #endif @@ -1964,11 +1966,11 @@ int bpf_sk_splice(struct __sk_buff *skb){ else if(tcph->rst){ if(local_diag->masquerade){ struct masq_reverse_key rk = {0}; - rk.dport = tcp_state_key.sport; - rk.sport = tcp_state_key.dport; + rk.dport = tcp_state_key.dport; + rk.sport = tcp_state_key.sport; rk.ifindex = event.ifindex; - rk.__in46_u_dest.ip = tcp_state_key.__in46_u_src.ip; - rk.__in46_u_src.ip = tcp_state_key.__in46_u_dst.ip; + rk.__in46_u_dest.ip = tcp_state_key.__in46_u_dst.ip; + rk.__in46_u_src.ip = tcp_state_key.__in46_u_src.ip; rk.protocol = IPPROTO_TCP; struct masq_value *rv = get_reverse_masquerade(rk); if(rv){ @@ -1979,8 +1981,16 @@ int bpf_sk_splice(struct __sk_buff *skb){ mk.ifindex = event.ifindex; mk.protocol = IPPROTO_TCP; del_masq(mk); + if(local_diag->verbose){ + event.tracking_code = MASQUERADE_ENTRY_REMOVED; + send_event(&event); + } } del_reverse_masq(rk); + if(local_diag->verbose){ + event.tracking_code = REVERSE_MASQUERADE_ENTRY_REMOVED; + send_event(&event); + } } del_tcp(tcp_state_key); tstate = get_tcp(tcp_state_key); @@ -1996,11 +2006,11 @@ int bpf_sk_splice(struct __sk_buff *skb){ if((tstate->est) && (tstate->sfin == 1) && (tstate->cfin == 1) && (bpf_htonl(tcph->ack_seq) == (bpf_htonl(tstate->cfseq) + 1))){ if(local_diag->masquerade){ struct masq_reverse_key rk = {0}; - rk.dport = tcp_state_key.sport; - rk.sport = tcp_state_key.dport; + rk.dport = tcp_state_key.dport; + rk.sport = tcp_state_key.sport; rk.ifindex = event.ifindex; - rk.__in46_u_dest.ip = tcp_state_key.__in46_u_src.ip; - rk.__in46_u_src.ip = tcp_state_key.__in46_u_dst.ip; + rk.__in46_u_dest.ip = tcp_state_key.__in46_u_dst.ip; + rk.__in46_u_src.ip = tcp_state_key.__in46_u_src.ip; rk.protocol = IPPROTO_TCP; struct masq_value *rv = get_reverse_masquerade(rk); if(rv){ @@ -2011,8 +2021,16 @@ int bpf_sk_splice(struct __sk_buff *skb){ mk.ifindex = event.ifindex; mk.protocol = IPPROTO_TCP; del_masq(mk); + if(local_diag->verbose){ + event.tracking_code = MASQUERADE_ENTRY_REMOVED; + send_event(&event); + } } del_reverse_masq(rk); + if(local_diag->verbose){ + event.tracking_code = REVERSE_MASQUERADE_ENTRY_REMOVED; + send_event(&event); + } } del_tcp(tcp_state_key); tstate = get_tcp(tcp_state_key); @@ -2022,7 +2040,6 @@ int bpf_sk_splice(struct __sk_buff *skb){ send_event(&event); } } - } else if((tstate->est) && (tstate->cfin == 1) && (bpf_htonl(tcph->ack_seq) == (bpf_htonl(tstate->cfseq) + 1))){ tstate->sfack = 1; @@ -2159,11 +2176,11 @@ int bpf_sk_splice(struct __sk_buff *skb){ return TC_ACT_SHOT; } struct masq_reverse_key rk = {0}; - rk.dport = udp_state_key.sport; - rk.sport = udp_state_key.dport; + rk.dport = udp_state_key.dport; + rk.sport = udp_state_key.sport; rk.ifindex = event.ifindex; - rk.__in46_u_dest.ip = udp_state_key.__in46_u_src.ip; - rk.__in46_u_src.ip = udp_state_key.__in46_u_dst.ip; + rk.__in46_u_dest.ip = udp_state_key.__in46_u_dst.ip; + rk.__in46_u_src.ip = udp_state_key.__in46_u_src.ip; rk.protocol = IPPROTO_UDP; struct masq_value *rv = get_reverse_masquerade(rk); if(rv){ @@ -2174,8 +2191,16 @@ int bpf_sk_splice(struct __sk_buff *skb){ mk.ifindex = event.ifindex; mk.protocol = IPPROTO_UDP; del_masq(mk); + if(local_diag->verbose){ + event.tracking_code = MASQUERADE_ENTRY_REMOVED; + send_event(&event); + } } del_reverse_masq(rk); + if(local_diag->verbose){ + event.tracking_code = REVERSE_MASQUERADE_ENTRY_REMOVED; + send_event(&event); + } } del_udp(udp_state_key); ustate = get_udp(udp_state_key); diff --git a/src/zfw_tc_outbound_track.c b/src/zfw_tc_outbound_track.c index f0ecdf4..226e6ff 100644 --- a/src/zfw_tc_outbound_track.c +++ b/src/zfw_tc_outbound_track.c @@ -63,6 +63,10 @@ #define CLIENT_INITIATED_ICMP_ECHO 29 #define IP6_HEADER_TOO_BIG 30 #define IPV6_TUPLE_TOO_BIG 31 +#define REVERSE_MASQUERADE_ENTRY_REMOVED 32 +#define MASQUERADE_ENTRY_REMOVED 33 +#define REVERSE_MASQUERADE_ENTRY_ADDED 34 +#define MASQUERADE_ENTRY_ADDED 35 #define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n)) struct bpf_event{ @@ -543,6 +547,12 @@ static inline void insert_masquerade(struct masq_value mv, struct masq_key key){ bpf_map_update_elem(&masquerade_map, &key, &mv,0); } +static inline struct masq_value *get_masquerade(struct masq_key key){ + struct masq_value *mv; + mv = bpf_map_lookup_elem(&masquerade_map, &key); + return mv; +} + /*Remove entry from masq state table*/ static inline void del_masq(struct masq_key key){ bpf_map_delete_elem(&masquerade_map, &key); @@ -2318,18 +2328,31 @@ int bpf_sk_splice6(struct __sk_buff *skb){ rev_new_val.o_sport = rand_source_port; rev_new_val.__in46_u_origin.ip = 0; insert_reverse_masquerade(rev_new_val,revk); + if(local_diag->verbose){ + event.tracking_code = REVERSE_MASQUERADE_ENTRY_ADDED; + send_event(&event); + } } __u32 l3_sum = bpf_csum_diff((__u32 *)&tuple->ipv4.saddr, sizeof(tuple->ipv4.saddr), (__u32 *)&local_ip4->ipaddr[0], sizeof(local_ip4->ipaddr[0]), 0); struct masq_value mv = {0}; - mv.__in46_u_origin.ip = tuple->ipv4.saddr; - mv.o_sport = tuple->ipv4.sport; struct masq_key mk = {0}; mk.__in46_u_dest.ip = tuple->ipv4.daddr; mk.dport = tuple->ipv4.dport; mk.sport = rand_source_port; mk.ifindex = skb->ifindex; mk.protocol = IPPROTO_TCP; - insert_masquerade(mv, mk); + struct masq_value *mvptr = get_masquerade(mk); + if(!mvptr){ + mv.__in46_u_origin.ip = tuple->ipv4.saddr; + mv.o_sport = tuple->ipv4.sport; + insert_masquerade(mv, mk); + if(local_diag->verbose){ + event.tracking_code = MASQUERADE_ENTRY_ADDED; + send_event(&event); + } + }else{ + mv = *mvptr; + } iph->saddr = local_ip4->ipaddr[0]; /*Calculate l3 Checksum*/ bpf_l3_csum_replace(skb, sizeof(struct ethhdr) + offsetof(struct iphdr, check), 0, l3_sum, 0); @@ -2433,6 +2456,10 @@ int bpf_sk_splice6(struct __sk_buff *skb){ rk.__in46_u_src.ip = tcp_state_key.__in46_u_src.ip; rk.protocol = IPPROTO_TCP; del_reverse_masq(rk); + if(local_diag->verbose){ + event.tracking_code = REVERSE_MASQUERADE_ENTRY_REMOVED; + send_event(&event); + } struct masq_key mk = {0}; mk.dport = tcph->dest; mk.sport = tcph->source; @@ -2440,6 +2467,10 @@ int bpf_sk_splice6(struct __sk_buff *skb){ mk.ifindex = event.ifindex; mk.protocol = IPPROTO_TCP; del_masq(mk); + if(local_diag->verbose){ + event.tracking_code = MASQUERADE_ENTRY_REMOVED; + send_event(&event); + } } del_tcp(tcp_state_key); tstate = get_tcp(tcp_state_key); @@ -2473,6 +2504,10 @@ int bpf_sk_splice6(struct __sk_buff *skb){ rk.__in46_u_src.ip = tcp_state_key.__in46_u_src.ip; rk.protocol = IPPROTO_TCP; del_reverse_masq(rk); + if(local_diag->verbose){ + event.tracking_code = REVERSE_MASQUERADE_ENTRY_REMOVED; + send_event(&event); + } struct masq_key mk = {0}; mk.dport = tcph->dest; mk.sport = tcph->source; @@ -2480,6 +2515,10 @@ int bpf_sk_splice6(struct __sk_buff *skb){ mk.ifindex = event.ifindex; mk.protocol = IPPROTO_TCP; del_masq(mk); + if(local_diag->verbose){ + event.tracking_code = MASQUERADE_ENTRY_REMOVED; + send_event(&event); + } } del_tcp(tcp_state_key); tstate = get_tcp(tcp_state_key); @@ -2544,18 +2583,31 @@ int bpf_sk_splice6(struct __sk_buff *skb){ rev_new_val.o_sport = rand_source_port; rev_new_val.__in46_u_origin.ip = 0; insert_reverse_masquerade(rev_new_val,revk); + if(local_diag->verbose){ + event.tracking_code = REVERSE_MASQUERADE_ENTRY_ADDED; + send_event(&event); + } } __u32 l3_sum = bpf_csum_diff((__u32 *)&tuple->ipv4.saddr, sizeof(tuple->ipv4.saddr), (__u32 *)&local_ip4->ipaddr[0], sizeof(local_ip4->ipaddr[0]), 0); struct masq_value mv = {0}; - mv.__in46_u_origin.ip = tuple->ipv4.saddr; - mv.o_sport = tuple->ipv4.sport; struct masq_key mk = {0}; mk.__in46_u_dest.ip = tuple->ipv4.daddr; mk.dport = tuple->ipv4.dport; mk.sport = rand_source_port; mk.ifindex = skb->ifindex; mk.protocol = IPPROTO_UDP; - insert_masquerade(mv, mk); + struct masq_value *mvptr = get_masquerade(mk); + if(!mvptr){ + mv.__in46_u_origin.ip = tuple->ipv4.saddr; + mv.o_sport = tuple->ipv4.sport; + insert_masquerade(mv, mk); + if(local_diag->verbose){ + event.tracking_code = MASQUERADE_ENTRY_ADDED; + send_event(&event); + } + }else{ + mv = *mvptr; + } iph->saddr = local_ip4->ipaddr[0]; /*Calculate l3 Checksum*/ bpf_l3_csum_replace(skb, sizeof(struct ethhdr) + offsetof(struct iphdr, check), 0, l3_sum, 0);