From ab54016dada01689af252a33234a4461cf58ca14 Mon Sep 17 00:00:00 2001 From: r-caamano Date: Tue, 1 Oct 2024 20:40:57 +0000 Subject: [PATCH] Added code to ensure there are no ipv4 masquerade port collions --- CHANGELOG.md | 7 ++++ src/zfw.c | 13 ++++++- src/zfw_monitor.c | 12 +++++- src/zfw_tc_ingress.c | 42 +++++++++++---------- src/zfw_tc_outbound_track.c | 74 ++++++++++++++++++++++++++++++------- 5 files changed, 112 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82d83fa..1ae79a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format --- ### +# [0.9.1] - 2024-10-01 + +- Added code to test if masquerade dst ip and src_port/dst_port/protocol combination is free before allocating new random + source port to ensure no collisions will occur. + +### + # [0.9.0] - 2024-09-24 - Added several new Arguments to zfw to allow for direct system call integrations with ziti-edge-tunnel ```-A --add-user-rules```, ```-H --init-tc ```, ```-Z, --init-xdp ```, ```-B, bind-saddr-add ```, diff --git a/src/zfw.c b/src/zfw.c index 292bd86..e76a3bf 100644 --- a/src/zfw.c +++ b/src/zfw.c @@ -97,6 +97,8 @@ #define MASQUERADE_ENTRY_REMOVED 33 #define REVERSE_MASQUERADE_ENTRY_ADDED 34 #define MASQUERADE_ENTRY_ADDED 35 +#define MASQUERADE_NO_FREE_TCP_SRC_PORTS_FOUND 36 +#define MASQUERADE_NO_FREE_UDP_SRC_PORTS_FOUND 37 bool ddos = false; bool add = false; @@ -259,7 +261,7 @@ char *direction_string; char *masq_interface; char check_alt[IF_NAMESIZE]; -const char *argp_program_version = "0.9.0"; +const char *argp_program_version = "0.9.1"; struct ring_buffer *ring_buffer; __u32 if_list[MAX_IF_LIST_ENTRIES]; @@ -3403,6 +3405,15 @@ static int process_events(void *ctx, void *data, size_t len) { state = "MASQUERADE_ENTRY_REMOVED"; } + else if (code == MASQUERADE_NO_FREE_TCP_SRC_PORTS_FOUND) + { + state = "MASQUERADE_NO_FREE_TCP_SRC_PORTS_FOUND"; + } + else if (code == MASQUERADE_NO_FREE_UDP_SRC_PORTS_FOUND) + { + state = "MASQUERADE_NO_FREE_UDP_SRC_PORTS_FOUND"; + } + if (state) { diff --git a/src/zfw_monitor.c b/src/zfw_monitor.c index 3ecb83f..2684a07 100644 --- a/src/zfw_monitor.c +++ b/src/zfw_monitor.c @@ -74,6 +74,8 @@ #define MASQUERADE_ENTRY_REMOVED 33 #define REVERSE_MASQUERADE_ENTRY_ADDED 34 #define MASQUERADE_ENTRY_ADDED 35 +#define MASQUERADE_NO_FREE_TCP_SRC_PORTS_FOUND 36 +#define MASQUERADE_NO_FREE_UDP_SRC_PORTS_FOUND 37 bool logging = false; bool monitor = false; @@ -85,7 +87,7 @@ char check_alt[IF_NAMESIZE]; char doc[] = "zfw_monitor -- ebpf firewall monitor tool"; const char *rb_map_path = "/sys/fs/bpf/tc/globals/rb_map"; const char *tproxy_map_path = "/sys/fs/bpf/tc/globals/zt_tproxy_map"; -const char *argp_program_version = "0.9.0"; +const char *argp_program_version = "0.9.1"; union bpf_attr rb_map; int rb_fd = -1; @@ -530,6 +532,14 @@ static int process_events(void *ctx, void *data, size_t len) { state = "MASQUERADE_ENTRY_REMOVED"; } + else if (code == MASQUERADE_NO_FREE_TCP_SRC_PORTS_FOUND) + { + state = "MASQUERADE_NO_FREE_TCP_SRC_PORTS_FOUND"; + } + else if (code == MASQUERADE_NO_FREE_UDP_SRC_PORTS_FOUND) + { + state = "MASQUERADE_NO_FREE_UDP_SRC_PORTS_FOUND"; + } if (state) { diff --git a/src/zfw_tc_ingress.c b/src/zfw_tc_ingress.c index 9a519d9..583009b 100644 --- a/src/zfw_tc_ingress.c +++ b/src/zfw_tc_ingress.c @@ -749,13 +749,15 @@ static inline struct masq_value *get_masquerade(struct masq_key key){ } /*Remove entry from masq state table*/ -static inline void del_masq(struct masq_key key){ - bpf_map_delete_elem(&masquerade_map, &key); +static inline int del_masq(struct masq_key key){ + int ret = bpf_map_delete_elem(&masquerade_map, &key); + return ret; } /*Remove entry from reverse masq state table*/ -static inline void del_reverse_masq(struct masq_reverse_key key){ - bpf_map_delete_elem(&masquerade_reverse_map, &key); +static inline int del_reverse_masq(struct masq_reverse_key key){ + int ret = bpf_map_delete_elem(&masquerade_reverse_map, &key); + return ret; } static inline struct masq_value *get_reverse_masquerade(struct masq_reverse_key key){ @@ -2111,14 +2113,14 @@ int bpf_sk_splice(struct __sk_buff *skb){ mk.__in46_u_dest.ip = iph->saddr; mk.ifindex = event.ifindex; mk.protocol = IPPROTO_TCP; - del_masq(mk); - if(local_diag->verbose){ + int dm_ret = del_masq(mk); + if(!dm_ret && local_diag->verbose){ event.tracking_code = MASQUERADE_ENTRY_REMOVED; send_event(&event); } } - del_reverse_masq(rk); - if(local_diag->verbose){ + int drm_ret = del_reverse_masq(rk); + if(!drm_ret && local_diag->verbose){ event.tracking_code = REVERSE_MASQUERADE_ENTRY_REMOVED; send_event(&event); } @@ -2151,14 +2153,14 @@ int bpf_sk_splice(struct __sk_buff *skb){ mk.__in46_u_dest.ip = iph->saddr; mk.ifindex = event.ifindex; mk.protocol = IPPROTO_TCP; - del_masq(mk); - if(local_diag->verbose){ + int dm_ret = del_masq(mk); + if(!dm_ret && local_diag->verbose){ event.tracking_code = MASQUERADE_ENTRY_REMOVED; send_event(&event); } } - del_reverse_masq(rk); - if(local_diag->verbose){ + int drm_ret = del_reverse_masq(rk); + if(!drm_ret && local_diag->verbose){ event.tracking_code = REVERSE_MASQUERADE_ENTRY_REMOVED; send_event(&event); } @@ -2321,14 +2323,14 @@ int bpf_sk_splice(struct __sk_buff *skb){ mk.__in46_u_dest.ip = iph->saddr; mk.ifindex = event.ifindex; mk.protocol = IPPROTO_UDP; - del_masq(mk); - if(local_diag->verbose){ + int dm_ret = del_masq(mk); + if(!dm_ret && local_diag->verbose){ event.tracking_code = MASQUERADE_ENTRY_REMOVED; send_event(&event); } } - del_reverse_masq(rk); - if(local_diag->verbose){ + int drm_ret = del_reverse_masq(rk); + if(!drm_ret && local_diag->verbose){ event.tracking_code = REVERSE_MASQUERADE_ENTRY_REMOVED; send_event(&event); } @@ -2374,14 +2376,14 @@ int bpf_sk_splice(struct __sk_buff *skb){ mk.__in46_u_dest.ip = iph->saddr; mk.ifindex = event.ifindex; mk.protocol = IPPROTO_UDP; - del_masq(mk); - if(local_diag->verbose){ + int dm_ret = del_masq(mk); + if(!dm_ret && local_diag->verbose){ event.tracking_code = MASQUERADE_ENTRY_REMOVED; send_event(&event); } } - del_reverse_masq(rk); - if(local_diag->verbose){ + int drm_ret = del_reverse_masq(rk); + if(!drm_ret && local_diag->verbose){ event.tracking_code = REVERSE_MASQUERADE_ENTRY_REMOVED; send_event(&event); } diff --git a/src/zfw_tc_outbound_track.c b/src/zfw_tc_outbound_track.c index 03fb070..f514831 100644 --- a/src/zfw_tc_outbound_track.c +++ b/src/zfw_tc_outbound_track.c @@ -67,6 +67,8 @@ #define MASQUERADE_ENTRY_REMOVED 33 #define REVERSE_MASQUERADE_ENTRY_ADDED 34 #define MASQUERADE_ENTRY_ADDED 35 +#define MASQUERADE_NO_FREE_TCP_SRC_PORTS_FOUND 36 +#define MASQUERADE_NO_FREE_UDP_SRC_PORTS_FOUND 37 #define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n)) struct bpf_event{ @@ -557,8 +559,9 @@ static inline struct masq_value *get_masquerade(struct masq_key key){ } /*Remove entry from masq state table*/ -static inline void del_masq(struct masq_key key){ - bpf_map_delete_elem(&masquerade_map, &key); +static inline int del_masq(struct masq_key key){ + int ret = bpf_map_delete_elem(&masquerade_map, &key); + return ret; } static inline void insert_reverse_masquerade(struct masq_value mv, struct masq_reverse_key key){ @@ -566,8 +569,9 @@ static inline void insert_reverse_masquerade(struct masq_value mv, struct masq_r } /*Remove entry from reverse masq state table*/ -static inline void del_reverse_masq(struct masq_reverse_key key){ - bpf_map_delete_elem(&masquerade_reverse_map, &key); +static inline int del_reverse_masq(struct masq_reverse_key key){ + int ret = bpf_map_delete_elem(&masquerade_reverse_map, &key); + return ret; } static inline struct masq_value *get_reverse_masquerade(struct masq_reverse_key key){ @@ -2339,7 +2343,28 @@ int bpf_sk_splice6(struct __sk_buff *skb){ rand_source_port = revv->o_sport; } else{ - rand_source_port = bpf_htons(1024 + bpf_get_prandom_u32() % (65535 -1023)); + int tcount = 0; + while(true){ + rand_source_port = bpf_htons(1024 + bpf_get_prandom_u32() % (65535 -1023)); + struct masq_key tmk = {0}; + tmk.__in46_u_dest.ip = tuple->ipv4.daddr; + tmk.dport = tuple->ipv4.dport; + tmk.sport = rand_source_port; + tmk.ifindex = skb->ifindex; + tmk.protocol = IPPROTO_TCP; + struct masq_value *tmvptr = get_masquerade(tmk); + if(!tmvptr){ + break; + } + tcount++; + if(tcount > 5000){ + if(local_diag->verbose){ + event.tracking_code = MASQUERADE_NO_FREE_TCP_SRC_PORTS_FOUND; + send_event(&event); + } + return TC_ACT_SHOT; + } + } struct masq_value rev_new_val = {0}; rev_new_val.o_sport = rand_source_port; rev_new_val.__in46_u_origin.ip = 0; @@ -2465,8 +2490,8 @@ int bpf_sk_splice6(struct __sk_buff *skb){ 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; - del_reverse_masq(rk); - if(local_diag->verbose){ + int drm_ret = del_reverse_masq(rk); + if(!drm_ret && local_diag->verbose){ event.tracking_code = REVERSE_MASQUERADE_ENTRY_REMOVED; send_event(&event); } @@ -2476,8 +2501,8 @@ int bpf_sk_splice6(struct __sk_buff *skb){ mk.__in46_u_dest.ip = iph->daddr; mk.ifindex = event.ifindex; mk.protocol = IPPROTO_TCP; - del_masq(mk); - if(local_diag->verbose){ + int dm_ret = del_masq(mk); + if(!dm_ret && local_diag->verbose){ event.tracking_code = MASQUERADE_ENTRY_REMOVED; send_event(&event); } @@ -2513,8 +2538,8 @@ int bpf_sk_splice6(struct __sk_buff *skb){ 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; - del_reverse_masq(rk); - if(local_diag->verbose){ + int drm_ret = del_reverse_masq(rk); + if(!drm_ret && local_diag->verbose){ event.tracking_code = REVERSE_MASQUERADE_ENTRY_REMOVED; send_event(&event); } @@ -2524,8 +2549,8 @@ int bpf_sk_splice6(struct __sk_buff *skb){ mk.__in46_u_dest.ip = iph->daddr; mk.ifindex = event.ifindex; mk.protocol = IPPROTO_TCP; - del_masq(mk); - if(local_diag->verbose){ + int dm_ret = del_masq(mk); + if(!dm_ret && local_diag->verbose){ event.tracking_code = MASQUERADE_ENTRY_REMOVED; send_event(&event); } @@ -2590,7 +2615,28 @@ int bpf_sk_splice6(struct __sk_buff *skb){ rand_source_port = revv->o_sport; } else{ - rand_source_port = bpf_htons(1024 + bpf_get_prandom_u32() % (65535 -1023)); + int tcount = 0; + while(true){ + rand_source_port = bpf_htons(1024 + bpf_get_prandom_u32() % (65535 -1023)); + struct masq_key tmk = {0}; + tmk.__in46_u_dest.ip = tuple->ipv4.daddr; + tmk.dport = tuple->ipv4.dport; + tmk.sport = rand_source_port; + tmk.ifindex = skb->ifindex; + tmk.protocol = IPPROTO_UDP; + struct masq_value *tmvptr = get_masquerade(tmk); + if(!tmvptr){ + break; + } + tcount++; + if(tcount > 5000){ + if(local_diag->verbose){ + event.tracking_code = MASQUERADE_NO_FREE_UDP_SRC_PORTS_FOUND; + send_event(&event); + } + return TC_ACT_SHOT; + } + } struct masq_value rev_new_val = {0}; rev_new_val.o_sport = rand_source_port; rev_new_val.__in46_u_origin.ip = 0;