drpanwe icon

udp_flood_blocker.bpf.c

drpanwe | PRO | 01/22/25 10:30:05 AM UTC | 0 ⭐ | 14001 👁️ | Never ⏰ | [eBPF]
C |

2.17 KB

|

Source Code

|

0 👍

/

0 👎

// udp_flood_blocker.bpf.c
// Compile with: clang -O2 -target bpf -c udp_flood_blocker.bpf.c -o udp_flood_blocker.bpf.o
 
#define KBUILD_MODNAME "udp_flood_blocker"
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/udp.h>
 
/*
  Map #1: udp_count
  - Type: PERCPU_ARRAY
  - Holds a single key (0) storing a 64-bit counter of UDP packets.
*/
struct {
    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
    __uint(max_entries, 1);
    __type(key, __u32);
    __type(value, __u64);
} udp_count SEC(".maps");
 
/*
  Map #2: block_state
  - Type: ARRAY
  - Holds a single key (0) storing a 32-bit "block" flag (0 = allow, 1 = drop).
*/
struct {
    __uint(type, BPF_MAP_TYPE_ARRAY);
    __uint(max_entries, 1);
    __type(key, __u32);
    __type(value, __u32);
} block_state SEC(".maps");
 
// XDP hook function: detect UDP and optionally block
SEC("xdp")
int detect_and_block_udp(struct xdp_md *ctx)
{
    void *data_end = (void *)(long)ctx->data_end;
    void *data     = (void *)(long)ctx->data;
 
    // parse Ethernet header
    struct ethhdr *eth = data;
    if ((void *)(eth + 1) > data_end) {
        return XDP_PASS; // packet too small/malformed
    }
 
    // check if it's IPv4
    if (bpf_ntohs(eth->h_proto) == ETH_P_IP) {
        struct iphdr *iph = (struct iphdr *)(eth + 1);
        if ((void *)(iph + 1) > data_end) {
            return XDP_PASS;
        }
 
        // check if it's UDP
        if (iph->protocol == IPPROTO_UDP) {
            // 1) Check block_state
            __u32 zero_key = 0;
            __u32 *block_val = bpf_map_lookup_elem(&block_state, &zero_key);
            if (block_val && *block_val == 1) {
                // If we are in block mode, drop all UDP
                return XDP_DROP;
            }
 
            // 2) Not blocked => increment the global UDP counter
            __u64 *cnt_val = bpf_map_lookup_elem(&udp_count, &zero_key);
            if (cnt_val) {
                __sync_fetch_and_add(cnt_val, 1);
            }
        }
    }
 
    // pass non-UDP or non-IPv4 packets
    return XDP_PASS;
}
 
char _license[] SEC("license") = "GPL";
 

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎