From 4b4cbe3d041cf9951f56f4faaa20e541968000e1 Mon Sep 17 00:00:00 2001 From: r-caamano Date: Fri, 6 Sep 2024 13:52:43 +0000 Subject: [PATCH] refactor l4 csum calc for tcp/udp masquerade --- CHANGELOG.md | 5 +++ src/zfw.c | 2 +- src/zfw_monitor.c | 2 +- src/zfw_tc_ingress.c | 60 ++++++++++++++++-------------------- src/zfw_tc_outbound_track.c | 61 ++++++++++++++++--------------------- 5 files changed, 60 insertions(+), 70 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12f9b54..90efd6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). --- +--- +### +# [0.8.17] - 2024-09-06 +- Refactor of L4 csum ipv4 + ### # [0.8.16] - 2024-09-02 - Fixed incorrect waitpid success/failure conditional checks in zfw.c and zfw_tunnel_wrapper.c. This did not cause an operational issue but would not diff --git a/src/zfw.c b/src/zfw.c index 32deec3..55a3ace 100644 --- a/src/zfw.c +++ b/src/zfw.c @@ -246,7 +246,7 @@ char *direction_string; char *masq_interface; char check_alt[IF_NAMESIZE]; -const char *argp_program_version = "0.8.16"; +const char *argp_program_version = "0.8.17"; struct ring_buffer *ring_buffer; __u32 if_list[MAX_IF_LIST_ENTRIES]; diff --git a/src/zfw_monitor.c b/src/zfw_monitor.c index 3f3b629..7615672 100644 --- a/src/zfw_monitor.c +++ b/src/zfw_monitor.c @@ -85,7 +85,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.8.16"; +const char *argp_program_version = "0.8.17"; union bpf_attr rb_map; int rb_fd = -1; diff --git a/src/zfw_tc_ingress.c b/src/zfw_tc_ingress.c index 87a5307..cae74e0 100644 --- a/src/zfw_tc_ingress.c +++ b/src/zfw_tc_ingress.c @@ -1897,25 +1897,19 @@ int bpf_sk_splice(struct __sk_buff *skb){ } /*Calculate l4 Checksum*/ int flags = BPF_F_PSEUDO_HDR; - bpf_l4_csum_replace(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + offsetof(struct tcphdr, check), 0, l3_sum, flags); - iph = (struct iphdr *)(skb->data + sizeof(*eth)); - if ((unsigned long)(iph + 1) > (unsigned long)skb->data_end){ - return TC_ACT_SHOT; - } - tuple = (struct bpf_sock_tuple *)(void*)(long)&iph->saddr; - if(!tuple){ - return TC_ACT_SHOT; - } - tuple_len = sizeof(tuple->ipv4); - if ((unsigned long)tuple + tuple_len > (unsigned long)skb->data_end){ - return TC_ACT_SHOT; - } - tcph = (struct tcphdr *)((unsigned long)iph + sizeof(*iph)); - if ((unsigned long)(tcph + 1) > (unsigned long)skb->data_end){ - return TC_ACT_SHOT; - } + struct l4_change_fields{ + __u32 daddr; + __u16 dport; + }; + struct l4_change_fields old_fields = {0}; + struct l4_change_fields new_fields = {0}; + old_fields.daddr = local_ip4->ipaddr[0]; + old_fields.dport = mk.sport; + new_fields.daddr = mv->__in46_u_origin.ip; + new_fields.dport = mv->o_sport; + __u32 l4_sum = bpf_csum_diff((__u32 *)&old_fields, sizeof(old_fields), (__u32 *)&new_fields, sizeof(new_fields), 0); tcph->dest = mv->o_sport; - bpf_l4_csum_replace(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + offsetof(struct tcphdr, check), mk.sport , mv->o_sport, flags | 2); + bpf_l4_csum_replace(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + offsetof(struct tcphdr, check), 0, l4_sum, flags); iph = (struct iphdr *)(skb->data + sizeof(*eth)); if ((unsigned long)(iph + 1) > (unsigned long)skb->data_end){ return TC_ACT_SHOT; @@ -1931,7 +1925,7 @@ int bpf_sk_splice(struct __sk_buff *skb){ tcph = (struct tcphdr *)((unsigned long)iph + sizeof(*iph)); if ((unsigned long)(tcph + 1) > (unsigned long)skb->data_end){ return TC_ACT_SHOT; - } + } } } tcp_state_key.__in46_u_dst.ip = tuple->ipv4.saddr; @@ -2121,7 +2115,19 @@ int bpf_sk_splice(struct __sk_buff *skb){ /*Calculate l4 Checksum*/ if(udph->check != 0){ int flags = BPF_F_PSEUDO_HDR; - bpf_l4_csum_replace(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + offsetof(struct udphdr, check), 0, l3_sum, flags); + struct l4_change_fields{ + __u32 daddr; + __u16 dport; + }; + struct l4_change_fields old_fields = {0}; + struct l4_change_fields new_fields = {0}; + old_fields.daddr = local_ip4->ipaddr[0]; + old_fields.dport = mk.sport; + new_fields.daddr = mv->__in46_u_origin.ip; + new_fields.dport = mv->o_sport; + __u32 l4_sum = bpf_csum_diff((__u32 *)&old_fields, sizeof(old_fields), (__u32 *)&new_fields, sizeof(new_fields), 0); + udph->dest = mv->o_sport; + bpf_l4_csum_replace(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + offsetof(struct udphdr, check), 0, l4_sum, flags); iph = (struct iphdr *)(skb->data + sizeof(*eth)); if ((unsigned long)(iph + 1) > (unsigned long)skb->data_end){ return TC_ACT_SHOT; @@ -2138,20 +2144,6 @@ int bpf_sk_splice(struct __sk_buff *skb){ if ((unsigned long)(udph + 1) > (unsigned long)skb->data_end){ return TC_ACT_SHOT; } - udph->dest = mv->o_sport; - bpf_l4_csum_replace(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + offsetof(struct udphdr, check), mk.sport , mv->o_sport, flags | 2); - iph = (struct iphdr *)(skb->data + sizeof(*eth)); - if ((unsigned long)(iph + 1) > (unsigned long)skb->data_end){ - return TC_ACT_SHOT; - } - tuple = (struct bpf_sock_tuple *)(void*)(long)&iph->saddr; - if(!tuple){ - return TC_ACT_SHOT; - } - tuple_len = sizeof(tuple->ipv4); - if ((unsigned long)tuple + tuple_len > (unsigned long)skb->data_end){ - return TC_ACT_SHOT; - } }else{ udph->dest = mv->o_sport; } diff --git a/src/zfw_tc_outbound_track.c b/src/zfw_tc_outbound_track.c index 8c58084..0fc48c3 100644 --- a/src/zfw_tc_outbound_track.c +++ b/src/zfw_tc_outbound_track.c @@ -2374,25 +2374,19 @@ int bpf_sk_splice6(struct __sk_buff *skb){ } /*Calculate l4 Checksum*/ int flags = BPF_F_PSEUDO_HDR; - bpf_l4_csum_replace(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + offsetof(struct tcphdr, check), 0, l3_sum, flags); - iph = (struct iphdr *)(skb->data + sizeof(*eth)); - if ((unsigned long)(iph + 1) > (unsigned long)skb->data_end){ - return TC_ACT_SHOT; - } - tuple = (struct bpf_sock_tuple *)(void*)(long)&iph->saddr; - if(!tuple){ - return TC_ACT_SHOT; - } - tuple_len = sizeof(tuple->ipv4); - if ((unsigned long)tuple + tuple_len > (unsigned long)skb->data_end){ - return TC_ACT_SHOT; - } - tcph = (struct tcphdr *)((unsigned long)iph + sizeof(*iph)); - if ((unsigned long)(tcph + 1) > (unsigned long)skb->data_end){ - return TC_ACT_SHOT; - } + struct l4_change_fields{ + __u32 saddr; + __u16 sport; + }; + struct l4_change_fields old_fields = {0}; + struct l4_change_fields new_fields = {0}; + old_fields.saddr = mv.__in46_u_origin.ip; + old_fields.sport = tcph->source; + new_fields.saddr = local_ip4->ipaddr[0]; + new_fields.sport = rand_source_port; + __u32 l4_sum = bpf_csum_diff((__u32 *)&old_fields, sizeof(old_fields), (__u32 *)&new_fields, sizeof(new_fields), 0); tcph->source = rand_source_port; - bpf_l4_csum_replace(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + offsetof(struct tcphdr, check), mv.o_sport , rand_source_port, flags | 2); + bpf_l4_csum_replace(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + offsetof(struct tcphdr, check), 0, l4_sum, flags); iph = (struct iphdr *)(skb->data + sizeof(*eth)); if ((unsigned long)(iph + 1) > (unsigned long)skb->data_end){ return TC_ACT_SHOT; @@ -2408,7 +2402,7 @@ int bpf_sk_splice6(struct __sk_buff *skb){ tcph = (struct tcphdr *)((unsigned long)iph + sizeof(*iph)); if ((unsigned long)(tcph + 1) > (unsigned long)skb->data_end){ return TC_ACT_SHOT; - } + } } unsigned long long tstamp = bpf_ktime_get_ns(); struct tcp_state *tstate; @@ -2630,7 +2624,20 @@ int bpf_sk_splice6(struct __sk_buff *skb){ /*Calculate l4 Checksum if checksum not equal to zero*/ if(udph->check != 0){ int flags = BPF_F_PSEUDO_HDR; - bpf_l4_csum_replace(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + offsetof(struct udphdr, check), 0, l3_sum, flags); + struct l4_change_fields{ + __u32 saddr; + __u16 sport; + }; + struct l4_change_fields old_fields = {0}; + struct l4_change_fields new_fields = {0}; + old_fields.saddr = mv.__in46_u_origin.ip; + old_fields.sport = udph->source; + new_fields.saddr = local_ip4->ipaddr[0]; + new_fields.sport = rand_source_port; + udph->source = rand_source_port; + __u32 l4_sum = bpf_csum_diff((__u32 *)&old_fields, sizeof(old_fields), (__u32 *)&new_fields, sizeof(new_fields), 0); + udph->source = rand_source_port; + bpf_l4_csum_replace(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + offsetof(struct udphdr, check), 0, l4_sum, flags); iph = (struct iphdr *)(skb->data + sizeof(*eth)); if ((unsigned long)(iph + 1) > (unsigned long)skb->data_end){ return TC_ACT_SHOT; @@ -2647,20 +2654,6 @@ int bpf_sk_splice6(struct __sk_buff *skb){ if ((unsigned long)(udph + 1) > (unsigned long)skb->data_end){ return TC_ACT_SHOT; } - udph->source = rand_source_port; - bpf_l4_csum_replace(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + offsetof(struct udphdr, check), mv.o_sport , rand_source_port, flags | 2); - iph = (struct iphdr *)(skb->data + sizeof(*eth)); - if ((unsigned long)(iph + 1) > (unsigned long)skb->data_end){ - return TC_ACT_SHOT; - } - tuple = (struct bpf_sock_tuple *)(void*)(long)&iph->saddr; - if(!tuple){ - return TC_ACT_SHOT; - } - tuple_len = sizeof(tuple->ipv4); - if ((unsigned long)tuple + tuple_len > (unsigned long)skb->data_end){ - return TC_ACT_SHOT; - } }else{ udph->source = rand_source_port; }