Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added code to ensure there are no ipv4 masquerade port collions #78

Merged
merged 1 commit into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <iface>```, ```-Z, --init-xdp <iface>```, ```-B, bind-saddr-add <cidr>```,
Expand Down
13 changes: 12 additions & 1 deletion src/zfw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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)
{
Expand Down
12 changes: 11 additions & 1 deletion src/zfw_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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)
{
Expand Down
42 changes: 22 additions & 20 deletions src/zfw_tc_ingress.c
Original file line number Diff line number Diff line change
Expand Up @@ -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){
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down
74 changes: 60 additions & 14 deletions src/zfw_tc_outbound_track.c
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -557,17 +559,19 @@ 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){
bpf_map_update_elem(&masquerade_reverse_map, &key, &mv,0);
}

/*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){
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down