diff --git a/src/common/config.h b/src/common/config.h index ba0af7b..e9217b2 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -49,4 +49,8 @@ #define MAX_RL_FLOW 100000 // Maximum entries in block map. -#define MAX_BLOCK 100000 \ No newline at end of file +#define MAX_BLOCK 100000 + +// Enables IPv6. +// If you're not using IPv6, this will speed up performance of the XDP program. +#define ENABLE_IPV6 \ No newline at end of file diff --git a/src/common/types.h b/src/common/types.h index 0267412..e66011d 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -10,8 +10,10 @@ struct filter_ip u32 dst_ip; u8 dst_cidr; +#ifdef ENABLE_IPV6 u32 src_ip6[4]; u32 dst_ip6[4]; +#endif unsigned int do_min_ttl : 1; u8 min_ttl; diff --git a/src/loader/prog.c b/src/loader/prog.c index 2d8d2d6..71b15e6 100644 --- a/src/loader/prog.c +++ b/src/loader/prog.c @@ -321,7 +321,7 @@ int main(int argc, char *argv[]) { log_msg(&cfg, 3, 0, "BPF map 'map_block' pinned to '%s/map_block'.", XDP_MAP_PIN_DIR); } - +#ifdef ENABLE_IPV6 if ((ret = pin_bpf_map(obj, XDP_MAP_PIN_DIR, "map_block6")) != 0) { log_msg(&cfg, 1, 0, "[WARNING] Failed to pin 'map_block6' to file system (%d)...", ret); @@ -330,6 +330,7 @@ int main(int argc, char *argv[]) { log_msg(&cfg, 3, 0, "BPF map 'map_block6' pinned to '%s/map_block6'.", XDP_MAP_PIN_DIR); } +#endif #ifdef ENABLE_IP_RANGE_DROP // Pin the IPv4 range drop map. diff --git a/src/loader/utils/xdp.c b/src/loader/utils/xdp.c index 3c9e51f..d11054f 100644 --- a/src/loader/utils/xdp.c +++ b/src/loader/utils/xdp.c @@ -304,7 +304,8 @@ int update_filter(int map_filters, filter_rule_cfg_t* filter_cfg, int idx) filter.ip.dst_ip = ip_range.ip; filter.ip.dst_cidr = ip_range.cidr; } - + +#ifdef ENABLE_IPV6 if (filter_cfg->ip.src_ip6) { struct in6_addr in; @@ -322,6 +323,7 @@ int update_filter(int map_filters, filter_rule_cfg_t* filter_cfg, int idx) memcpy(filter.ip.dst_ip6, in.__in6_u.__u6_addr32, 4); } +#endif if (filter_cfg->ip.min_ttl > -1) { diff --git a/src/xdp/prog.c b/src/xdp/prog.c index 1de558d..2dbf92a 100644 --- a/src/xdp/prog.c +++ b/src/xdp/prog.c @@ -46,7 +46,11 @@ int xdp_prog_main(struct xdp_md *ctx) } // Check Ethernet protocol. +#ifdef ENABLE_IPV6 if (unlikely(eth->h_proto != htons(ETH_P_IP) && eth->h_proto != htons(ETH_P_IPV6))) +#else + if (unlikely(eth->h_proto != htons(ETH_P_IP))) +#endif { inc_pkt_stats(stats, STATS_TYPE_PASSED); @@ -59,7 +63,19 @@ int xdp_prog_main(struct xdp_md *ctx) u128 src_ip6 = 0; // Set IPv4 and IPv6 common variables. - if (eth->h_proto == htons(ETH_P_IPV6)) + if (eth->h_proto == htons(ETH_P_IP)) + { + iph = data + sizeof(struct ethhdr); + + if (unlikely(iph + 1 > (struct iphdr *)data_end)) + { + inc_pkt_stats(stats, STATS_TYPE_DROPPED); + + return XDP_DROP; + } + } +#ifdef ENABLE_IPV6 + else { iph6 = data + sizeof(struct ethhdr); @@ -72,17 +88,7 @@ int xdp_prog_main(struct xdp_md *ctx) memcpy(&src_ip6, iph6->saddr.in6_u.u6_addr32, sizeof(src_ip6)); } - else - { - iph = data + sizeof(struct ethhdr); - - if (unlikely(iph + 1 > (struct iphdr *)data_end)) - { - inc_pkt_stats(stats, STATS_TYPE_DROPPED); - - return XDP_DROP; - } - } +#endif // We only want to process TCP, UDP, and ICMP packets. if ((iph6 && iph6->nexthdr != IPPROTO_UDP && iph6->nexthdr != IPPROTO_TCP && iph6->nexthdr != IPPROTO_ICMP) && (iph && iph->protocol != IPPROTO_UDP && iph->protocol != IPPROTO_TCP && iph->protocol != IPPROTO_ICMP)) @@ -98,28 +104,32 @@ int xdp_prog_main(struct xdp_md *ctx) // Check block map. u64 *blocked = NULL; - if (iph6) - { - blocked = bpf_map_lookup_elem(&map_block6, &src_ip6); - } - else if (iph) + if (iph) { blocked = bpf_map_lookup_elem(&map_block, &iph->saddr); } +#ifdef ENABLE_IPV6 + else + { + blocked = bpf_map_lookup_elem(&map_block6, &src_ip6); + } +#endif if (blocked != NULL) { if (*blocked > 0 && now > *blocked) { // Remove element from map. - if (iph6) - { - bpf_map_delete_elem(&map_block6, &src_ip6); - } - else if (iph) + if (iph) { bpf_map_delete_elem(&map_block, &iph->saddr); } +#ifdef ENABLE_IPV6 + else + { + bpf_map_delete_elem(&map_block6, &src_ip6); + } +#endif } else { @@ -162,68 +172,7 @@ int xdp_prog_main(struct xdp_md *ctx) u8 protocol = 0; - if (iph6) - { - protocol = iph6->nexthdr; - - switch (iph6->nexthdr) - { - case IPPROTO_TCP: - // Scan TCP header. - tcph = data + sizeof(struct ethhdr) + sizeof(struct ipv6hdr); - - // Check TCP header. - if (unlikely(tcph + 1 > (struct tcphdr *)data_end)) - { - inc_pkt_stats(stats, STATS_TYPE_DROPPED); - - return XDP_DROP; - } - - src_port = tcph->source; - -#ifdef ENABLE_FILTER_LOGGING - dst_port = tcph->dest; -#endif - - break; - - case IPPROTO_UDP: - // Scan UDP header. - udph = data + sizeof(struct ethhdr) + sizeof(struct ipv6hdr); - - // Check TCP header. - if (unlikely(udph + 1 > (struct udphdr *)data_end)) - { - inc_pkt_stats(stats, STATS_TYPE_DROPPED); - - return XDP_DROP; - } - - src_port = udph->source; - -#ifdef ENABLE_FILTER_LOGGING - dst_port = udph->dest; -#endif - - break; - - case IPPROTO_ICMPV6: - // Scan ICMPv6 header. - icmp6h = data + sizeof(struct ethhdr) + sizeof(struct ipv6hdr); - - // Check ICMPv6 header. - if (unlikely(icmp6h + 1 > (struct icmp6hdr *)data_end)) - { - inc_pkt_stats(stats, STATS_TYPE_DROPPED); - - return XDP_DROP; - } - - break; - } - } - else if (iph) + if (iph) { protocol = iph->protocol; @@ -284,6 +233,69 @@ int xdp_prog_main(struct xdp_md *ctx) break; } } +#ifdef ENABLE_IPV6 + else if (iph6) + { + protocol = iph6->nexthdr; + + switch (iph6->nexthdr) + { + case IPPROTO_TCP: + // Scan TCP header. + tcph = data + sizeof(struct ethhdr) + sizeof(struct ipv6hdr); + + // Check TCP header. + if (unlikely(tcph + 1 > (struct tcphdr *)data_end)) + { + inc_pkt_stats(stats, STATS_TYPE_DROPPED); + + return XDP_DROP; + } + + src_port = tcph->source; + +#ifdef ENABLE_FILTER_LOGGING + dst_port = tcph->dest; +#endif + + break; + + case IPPROTO_UDP: + // Scan UDP header. + udph = data + sizeof(struct ethhdr) + sizeof(struct ipv6hdr); + + // Check TCP header. + if (unlikely(udph + 1 > (struct udphdr *)data_end)) + { + inc_pkt_stats(stats, STATS_TYPE_DROPPED); + + return XDP_DROP; + } + + src_port = udph->source; + +#ifdef ENABLE_FILTER_LOGGING + dst_port = udph->dest; +#endif + + break; + + case IPPROTO_ICMPV6: + // Scan ICMPv6 header. + icmp6h = data + sizeof(struct ethhdr) + sizeof(struct ipv6hdr); + + // Check ICMPv6 header. + if (unlikely(icmp6h + 1 > (struct icmp6hdr *)data_end)) + { + inc_pkt_stats(stats, STATS_TYPE_DROPPED); + + return XDP_DROP; + } + + break; + } + } +#endif #ifdef ENABLE_FILTERS // Update client stats (PPS/BPS). @@ -304,6 +316,7 @@ int xdp_prog_main(struct xdp_md *ctx) update_flow_stats(&flow_pps, &flow_bps, iph->saddr, src_port, protocol, pkt_len, now); #endif } +#ifdef ENABLE_IPV6 else if (iph6) { #ifdef ENABLE_RL_IP @@ -315,6 +328,7 @@ int xdp_prog_main(struct xdp_md *ctx) #endif } #endif +#endif #endif int action = 0; @@ -358,8 +372,76 @@ int xdp_prog_main(struct xdp_md *ctx) } #endif - // Do specific IPv6. - if (iph6) + // Match IP settings. + if (iph) + { + // Source address. + if (filter->ip.src_ip) + { + if (filter->ip.src_cidr == 32 && iph->saddr != filter->ip.src_ip) + { + continue; + } + + if (!is_ip_in_range(iph->saddr, filter->ip.src_ip, filter->ip.src_cidr)) + { + continue; + } + } + + // Destination address. + if (filter->ip.dst_ip) + { + if (filter->ip.dst_cidr == 32 && iph->daddr != filter->ip.dst_ip) + { + continue; + } + + if (!is_ip_in_range(iph->daddr, filter->ip.dst_ip, filter->ip.dst_cidr)) + { + continue; + } + } + +#if defined(ENABLE_IPV6) && defined(ALLOW_SINGLE_IP_V4_V6) + if ((filter->ip.src_ip6[0] != 0 || filter->ip.src_ip6[1] != 0 || filter->ip.src_ip6[2] != 0 || filter->ip.src_ip6[3] != 0) || (filter->ip.dst_ip6[0] != 0 || filter->ip.dst_ip6[1] != 0 || filter->ip.dst_ip6[2] != 0 || filter->ip.dst_ip6[3] != 0)) + { + continue; + } +#endif + + // TOS. + if (filter->ip.do_tos && filter->ip.tos != iph->tos) + { + continue; + } + + // Max TTL. + if (filter->ip.do_max_ttl && filter->ip.max_ttl < iph->ttl) + { + continue; + } + + // Min TTL. + if (filter->ip.do_min_ttl && filter->ip.min_ttl > iph->ttl) + { + continue; + } + + // Max packet length. + if (filter->ip.do_max_len && filter->ip.max_len < pkt_len) + { + continue; + } + + // Min packet length. + if (filter->ip.do_min_len && filter->ip.min_len > pkt_len) + { + continue; + } + } +#ifdef ENABLE_IPV6 + else if (iph6) { // Source address. if (filter->ip.src_ip6[0] != 0 && (iph6->saddr.in6_u.u6_addr32[0] != filter->ip.src_ip6[0] || iph6->saddr.in6_u.u6_addr32[1] != filter->ip.src_ip6[1] || iph6->saddr.in6_u.u6_addr32[2] != filter->ip.src_ip6[2] || iph6->saddr.in6_u.u6_addr32[3] != filter->ip.src_ip6[3])) @@ -404,75 +486,9 @@ int xdp_prog_main(struct xdp_md *ctx) continue; } } - else if (iph) - { - // Source address. - if (filter->ip.src_ip) - { - if (filter->ip.src_cidr == 32 && iph->saddr != filter->ip.src_ip) - { - continue; - } - - if (!is_ip_in_range(iph->saddr, filter->ip.src_ip, filter->ip.src_cidr)) - { - continue; - } - } - - // Destination address. - if (filter->ip.dst_ip) - { - if (filter->ip.dst_cidr == 32 && iph->daddr != filter->ip.dst_ip) - { - continue; - } - - if (!is_ip_in_range(iph->daddr, filter->ip.dst_ip, filter->ip.dst_cidr)) - { - continue; - } - } - -#ifdef ALLOW_SINGLE_IP_V4_V6 - if ((filter->ip.src_ip6[0] != 0 || filter->ip.src_ip6[1] != 0 || filter->ip.src_ip6[2] != 0 || filter->ip.src_ip6[3] != 0) || (filter->ip.dst_ip6[0] != 0 || filter->ip.dst_ip6[1] != 0 || filter->ip.dst_ip6[2] != 0 || filter->ip.dst_ip6[3] != 0)) - { - continue; - } #endif - // TOS. - if (filter->ip.do_tos && filter->ip.tos != iph->tos) - { - continue; - } - - // Max TTL. - if (filter->ip.do_max_ttl && filter->ip.max_ttl < iph->ttl) - { - continue; - } - - // Min TTL. - if (filter->ip.do_min_ttl && filter->ip.min_ttl > iph->ttl) - { - continue; - } - - // Max packet length. - if (filter->ip.do_max_len && filter->ip.max_len < pkt_len) - { - continue; - } - - // Min packet length. - if (filter->ip.do_min_len && filter->ip.min_len > pkt_len) - { - continue; - } - } - - // Do TCP options. + // Check TCP matches. if (filter->tcp.enabled) { if (!tcph) @@ -550,6 +566,7 @@ int xdp_prog_main(struct xdp_md *ctx) continue; } } + // Check UDP matches. else if (filter->udp.enabled) { if (!udph) @@ -595,6 +612,7 @@ int xdp_prog_main(struct xdp_md *ctx) continue; } } +#ifdef ENABLE_IPV6 else if (icmp6h) { // Code. @@ -609,10 +627,7 @@ int xdp_prog_main(struct xdp_md *ctx) continue; } } - else - { - continue; - } +#endif } #ifdef ENABLE_FILTER_LOGGING @@ -643,14 +658,16 @@ matched: { u64 new_time = now + (block_time * NANO_TO_SEC); - if (iph6) - { - bpf_map_update_elem(&map_block6, &src_ip6, &new_time, BPF_ANY); - } - else if (iph) + if (iph) { bpf_map_update_elem(&map_block, &iph->saddr, &new_time, BPF_ANY); } +#ifdef ENABLE_IPV6 + else + { + bpf_map_update_elem(&map_block6, &src_ip6, &new_time, BPF_ANY); + } +#endif } inc_pkt_stats(stats, STATS_TYPE_DROPPED); diff --git a/src/xdp/utils/logging.c b/src/xdp/utils/logging.c index aa7590b..c76f315 100644 --- a/src/xdp/utils/logging.c +++ b/src/xdp/utils/logging.c @@ -36,11 +36,14 @@ static __always_inline int log_filter_msg(struct iphdr* iph, struct ipv6hdr* iph { e->src_ip = iph->saddr; e->dst_ip = iph->daddr; - } else if (iph6) + } +#ifdef ENABLE_IPV6 + else if (iph6) { memcpy(&e->src_ip6, iph6->saddr.in6_u.u6_addr32, 4); memcpy(&e->dst_ip6, iph6->daddr.in6_u.u6_addr32, 4); } +#endif e->src_port = src_port; e->dst_port = dst_port; diff --git a/src/xdp/utils/maps.h b/src/xdp/utils/maps.h index ab3773e..db45a18 100644 --- a/src/xdp/utils/maps.h +++ b/src/xdp/utils/maps.h @@ -21,6 +21,7 @@ struct __type(value, u64); } map_block SEC(".maps"); +#ifdef ENABLE_IPV6 struct { __uint(type, BPF_MAP_TYPE_LRU_HASH); @@ -28,6 +29,7 @@ struct __type(key, u128); __type(value, u64); } map_block6 SEC(".maps"); +#endif #ifdef ENABLE_IP_RANGE_DROP struct @@ -50,6 +52,7 @@ struct __type(value, cl_stats_t); } map_ip_stats SEC(".maps"); +#ifdef ENABLE_IPV6 struct { __uint(type, BPF_MAP_TYPE_LRU_HASH); @@ -58,6 +61,7 @@ struct __type(value, cl_stats_t); } map_ip6_stats SEC(".maps"); #endif +#endif #ifdef ENABLE_RL_FLOW struct @@ -68,6 +72,7 @@ struct __type(value, cl_stats_t); } map_flow_stats SEC(".maps"); +#ifdef ENABLE_IPV6 struct { __uint(type, BPF_MAP_TYPE_LRU_HASH); @@ -76,6 +81,7 @@ struct __type(value, cl_stats_t); } map_flow6_stats SEC(".maps"); #endif +#endif struct { diff --git a/src/xdp/utils/rl.c b/src/xdp/utils/rl.c index 50d169f..c267620 100644 --- a/src/xdp/utils/rl.c +++ b/src/xdp/utils/rl.c @@ -55,6 +55,7 @@ static __always_inline int update_ip_stats(u64 *pps, u64 *bps, u32 ip, u16 pkt_l return 0; } +#ifdef ENABLE_IPV6 /** * Updates source IPv6 address stats. * @@ -107,6 +108,7 @@ static __always_inline int update_ip6_stats(u64 *pps, u64 *bps, u128 *ip, u16 pk return 0; } #endif +#endif #ifdef ENABLE_RL_FLOW /** @@ -168,6 +170,7 @@ static __always_inline int update_flow_stats(u64 *pps, u64 *bps, u32 ip, u16 por return 0; } +#ifdef ENABLE_IPV6 /** * Updates IPv6 flow stats. * @@ -227,4 +230,5 @@ static __always_inline int update_flow6_stats(u64 *pps, u64 *bps, u128 *ip, u16 return 0; } #endif +#endif #endif \ No newline at end of file