Restructure project and organize code.
This commit is contained in:
6
src/common/all.h
Normal file
6
src/common/all.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/config.h>
|
||||
#include <common/constants.h>
|
||||
#include <common/int_types.h>
|
||||
#include <common/types.h>
|
||||
12
src/common/config.h
Normal file
12
src/common/config.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
// Feel free to comment this out if you don't want the `blocked` entry on the stats map to be incremented every single time a packet is dropped from the source IP being on the blocked map. Commenting this line out should increase performance when blocking malicious traffic.
|
||||
#define DOSTATSONBLOCKMAP
|
||||
|
||||
// When this is defined, a check will occur inside the IPv4 and IPv6 filters. For IPv6 packets, if no IPv6 source/destination IP addresses are set, but there is an IPv4 address, it will ignore the filter. The same goes for IPv4, if there is no IPv4 source/destination IP addresses set, if an IPv6 address is set, it will ignore the filter.
|
||||
#define ALLOWSINGLEIPV4V6
|
||||
|
||||
// If uncommented, rate limits for clients are determined using the source IP, port, and protocol instead of just the source IP.
|
||||
// This allows for more precise rate limits (connection-specific instead of a single source IP).
|
||||
// I decided not to include the destination IP/port because the source IP, port, and protocol should be represent a unique connection.
|
||||
#define USE_FLOW_RL
|
||||
7
src/common/constants.h
Normal file
7
src/common/constants.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#define MAX_PCKT_LENGTH 65535
|
||||
#define MAX_FILTERS 60
|
||||
#define MAX_TRACK_IPS 100000
|
||||
#define MAX_CPUS 256
|
||||
#define NANO_TO_SEC 1000000000
|
||||
17
src/common/int_types.h
Normal file
17
src/common/int_types.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
typedef __uint128_t u128;
|
||||
typedef __u64 u64;
|
||||
typedef __u32 u32;
|
||||
typedef __u16 u16;
|
||||
typedef __u8 u8;
|
||||
|
||||
typedef __s64 s64;
|
||||
typedef __s32 s32;
|
||||
typedef __s16 s16;
|
||||
|
||||
typedef __be64 be64;
|
||||
typedef __be32 be32;
|
||||
typedef __be16 be16;
|
||||
134
src/common/types.h
Normal file
134
src/common/types.h
Normal file
@@ -0,0 +1,134 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/int_types.h>
|
||||
|
||||
struct tcpopts
|
||||
{
|
||||
unsigned int enabled : 1;
|
||||
|
||||
unsigned int do_sport : 1;
|
||||
u16 sport;
|
||||
|
||||
unsigned int do_dport : 1;
|
||||
u16 dport;
|
||||
|
||||
// TCP flags.
|
||||
unsigned int do_urg : 1;
|
||||
unsigned int urg : 1;
|
||||
|
||||
unsigned int do_ack : 1;
|
||||
unsigned int ack : 1;
|
||||
|
||||
unsigned int do_rst : 1;
|
||||
unsigned int rst : 1;
|
||||
|
||||
unsigned int do_psh : 1;
|
||||
unsigned int psh : 1;
|
||||
|
||||
unsigned int do_syn : 1;
|
||||
unsigned int syn : 1;
|
||||
|
||||
unsigned int do_fin : 1;
|
||||
unsigned int fin : 1;
|
||||
|
||||
unsigned int do_ece : 1;
|
||||
unsigned int ece : 1;
|
||||
|
||||
unsigned int do_cwr : 1;
|
||||
unsigned int cwr : 1;
|
||||
};
|
||||
|
||||
struct udpopts
|
||||
{
|
||||
unsigned int enabled : 1;
|
||||
|
||||
unsigned int do_sport : 1;
|
||||
u16 sport;
|
||||
|
||||
unsigned int do_dport : 1;
|
||||
u16 dport;
|
||||
};
|
||||
|
||||
struct icmpopts
|
||||
{
|
||||
unsigned int enabled : 1;
|
||||
|
||||
unsigned int do_code : 1;
|
||||
u8 code;
|
||||
|
||||
unsigned int do_type : 1;
|
||||
u8 type;
|
||||
};
|
||||
|
||||
struct filter
|
||||
{
|
||||
u8 id;
|
||||
|
||||
unsigned int enabled : 1;
|
||||
|
||||
u8 action;
|
||||
|
||||
u32 src_ip;
|
||||
u8 src_cidr;
|
||||
|
||||
u32 dst_ip;
|
||||
u8 dst_cidr;
|
||||
|
||||
u32 src_ip6[4];
|
||||
u32 dst_ip6[4];
|
||||
|
||||
unsigned int do_min_ttl : 1;
|
||||
u8 min_ttl;
|
||||
|
||||
unsigned int do_max_ttl : 1;
|
||||
u8 max_ttl;
|
||||
|
||||
unsigned int do_min_len : 1;
|
||||
u16 min_len;
|
||||
|
||||
unsigned int do_max_len : 1;
|
||||
u16 max_len;
|
||||
|
||||
unsigned int do_tos : 1;
|
||||
u8 tos;
|
||||
|
||||
unsigned int do_pps : 1;
|
||||
__u64 pps;
|
||||
|
||||
unsigned int do_bps : 1;
|
||||
__u64 bps;
|
||||
|
||||
__u64 blocktime;
|
||||
|
||||
struct tcpopts tcpopts;
|
||||
struct udpopts udpopts;
|
||||
struct icmpopts icmpopts;
|
||||
} __attribute__((__aligned__(8)));
|
||||
|
||||
struct stats
|
||||
{
|
||||
__u64 allowed;
|
||||
__u64 dropped;
|
||||
__u64 passed;
|
||||
};
|
||||
|
||||
struct ip_stats
|
||||
{
|
||||
__u64 pps;
|
||||
__u64 bps;
|
||||
__u64 next_update;
|
||||
};
|
||||
|
||||
struct flow
|
||||
{
|
||||
u32 ip;
|
||||
u16 port;
|
||||
u8 protocol;
|
||||
};
|
||||
|
||||
struct flow6
|
||||
{
|
||||
u128 ip;
|
||||
u16 port;
|
||||
u8 protocol;
|
||||
};
|
||||
@@ -20,12 +20,14 @@
|
||||
#include <libbpf.h>
|
||||
#include <xdp/libxdp.h>
|
||||
|
||||
#include <xdpfw.h>
|
||||
#include <config.h>
|
||||
#include <cmdline.h>
|
||||
#include <common/all.h>
|
||||
|
||||
#include <loader/utils/cmdline.h>
|
||||
#include <loader/utils/config.h>
|
||||
#include <loader/utils/helpers.h>
|
||||
|
||||
// Other variables.
|
||||
static __u8 cont = 1;
|
||||
static u8 cont = 1;
|
||||
static int filtersmap = -1;
|
||||
static int statsmap = -1;
|
||||
|
||||
@@ -44,15 +46,15 @@ void SignalHndl(int tmp)
|
||||
void UpdateFilters(struct config *cfg)
|
||||
{
|
||||
// Loop through all filters and delete the map. We do this in the case rules were edited and were put out of order since the key doesn't uniquely map to a specific rule.
|
||||
for (__u8 i = 0; i < MAX_FILTERS; i++)
|
||||
for (u8 i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
__u32 key = i;
|
||||
u32 key = i;
|
||||
|
||||
bpf_map_delete_elem(filtersmap, &key);
|
||||
}
|
||||
|
||||
// Add a filter to the filter maps.
|
||||
for (__u32 i = 0; i < MAX_FILTERS; i++)
|
||||
for (u32 i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
// Check if we have a valid ID.
|
||||
if (cfg->filters[i].id < 1)
|
||||
@@ -96,7 +98,7 @@ int UpdateConfig(struct config *cfg, char *cfgfile)
|
||||
|
||||
SetCfgDefaults(cfg);
|
||||
|
||||
for (__u16 i = 0; i < MAX_FILTERS; i++)
|
||||
for (u16 i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
cfg->filters[i] = (struct filter) {0};
|
||||
}
|
||||
@@ -178,11 +180,11 @@ struct xdp_program *LoadBpfObj(const char *filename)
|
||||
*
|
||||
* @return 0 on success and 1 on error.
|
||||
*/
|
||||
int AttachXdp(struct xdp_program *prog, int ifidx, __u8 detach, struct cmdline *cmd)
|
||||
int AttachXdp(struct xdp_program *prog, int ifidx, u8 detach, struct cmdline *cmd)
|
||||
{
|
||||
int err;
|
||||
|
||||
__u32 mode = XDP_MODE_NATIVE;
|
||||
u32 mode = XDP_MODE_NATIVE;
|
||||
char *smode;
|
||||
|
||||
smode = "DRV/native";
|
||||
@@ -199,7 +201,7 @@ int AttachXdp(struct xdp_program *prog, int ifidx, __u8 detach, struct cmdline *
|
||||
mode = XDP_MODE_SKB;
|
||||
}
|
||||
|
||||
__u8 exit = 0;
|
||||
u8 exit = 0;
|
||||
|
||||
while (!exit)
|
||||
{
|
||||
@@ -427,7 +429,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// XDP variables.
|
||||
const char *filename = "/etc/xdpfw/xdpfw_kern.o";
|
||||
const char *filename = "/etc/xdpfw/xdp_prog.o";
|
||||
|
||||
// Load BPF object.
|
||||
struct xdp_program *prog = LoadBpfObj(filename);
|
||||
@@ -518,7 +520,7 @@ int main(int argc, char *argv[])
|
||||
// Update stats.
|
||||
if (!cfg.nostats)
|
||||
{
|
||||
__u32 key = 0;
|
||||
u32 key = 0;
|
||||
struct stats stats[MAX_CPUS];
|
||||
//memset(stats, 0, sizeof(struct stats) * MAX_CPUS);
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <libconfig.h>
|
||||
#include <string.h>
|
||||
#include <linux/types.h>
|
||||
#include <loader/utils/config.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <xdpfw.h>
|
||||
#include <config.h>
|
||||
#include <utils.h>
|
||||
#include <loader/utils/helpers.h>
|
||||
|
||||
FILE *file;
|
||||
|
||||
@@ -26,7 +18,7 @@ void SetCfgDefaults(struct config *cfg)
|
||||
cfg->nostats = 0;
|
||||
cfg->stdout_update_time = 1000;
|
||||
|
||||
for (__u16 i = 0; i < MAX_FILTERS; i++)
|
||||
for (u16 i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
cfg->filters[i].id = 0;
|
||||
cfg->filters[i].enabled = 0;
|
||||
@@ -34,7 +26,7 @@ void SetCfgDefaults(struct config *cfg)
|
||||
cfg->filters[i].src_ip = 0;
|
||||
cfg->filters[i].dst_ip = 0;
|
||||
|
||||
for (__u8 j = 0; j < 4; j++)
|
||||
for (u8 j = 0; j < 4; j++)
|
||||
{
|
||||
cfg->filters[i].src_ip6[j] = 0;
|
||||
cfg->filters[i].dst_ip6[j] = 0;
|
||||
@@ -197,7 +189,7 @@ int ReadCfg(struct config *cfg)
|
||||
// Set filter count.
|
||||
int filters = 0;
|
||||
|
||||
for (__u8 i = 0; i < config_setting_length(setting); i++)
|
||||
for (u8 i = 0; i < config_setting_length(setting); i++)
|
||||
{
|
||||
config_setting_t* filter = config_setting_get_elem(setting, i);
|
||||
|
||||
@@ -259,7 +251,7 @@ int ReadCfg(struct config *cfg)
|
||||
|
||||
inet_pton(AF_INET6, sip6, &in);
|
||||
|
||||
for (__u8 j = 0; j < 4; j++)
|
||||
for (u8 j = 0; j < 4; j++)
|
||||
{
|
||||
cfg->filters[i].src_ip6[j] = in.__in6_u.__u6_addr32[j];
|
||||
}
|
||||
@@ -274,7 +266,7 @@ int ReadCfg(struct config *cfg)
|
||||
|
||||
inet_pton(AF_INET6, dip6, &in);
|
||||
|
||||
for (__u8 j = 0; j < 4; j++)
|
||||
for (u8 j = 0; j < 4; j++)
|
||||
{
|
||||
cfg->filters[i].dst_ip6[j] = in.__in6_u.__u6_addr32[j];
|
||||
}
|
||||
@@ -285,7 +277,7 @@ int ReadCfg(struct config *cfg)
|
||||
|
||||
if (config_setting_lookup_int(filter, "min_ttl", &min_ttl))
|
||||
{
|
||||
cfg->filters[i].min_ttl = (__u8)min_ttl;
|
||||
cfg->filters[i].min_ttl = (u8)min_ttl;
|
||||
cfg->filters[i].do_min_ttl = 1;
|
||||
}
|
||||
|
||||
@@ -294,7 +286,7 @@ int ReadCfg(struct config *cfg)
|
||||
|
||||
if (config_setting_lookup_int(filter, "max_ttl", &max_ttl))
|
||||
{
|
||||
cfg->filters[i].max_ttl = (__u8)max_ttl;
|
||||
cfg->filters[i].max_ttl = (u8)max_ttl;
|
||||
cfg->filters[i].do_max_ttl = 1;
|
||||
}
|
||||
|
||||
@@ -321,7 +313,7 @@ int ReadCfg(struct config *cfg)
|
||||
|
||||
if (config_setting_lookup_int(filter, "tos", &tos))
|
||||
{
|
||||
cfg->filters[i].tos = (__u8)tos;
|
||||
cfg->filters[i].tos = (u8)tos;
|
||||
cfg->filters[i].do_tos = 1;
|
||||
}
|
||||
|
||||
@@ -369,7 +361,7 @@ int ReadCfg(struct config *cfg)
|
||||
|
||||
if (config_setting_lookup_int64(filter, "tcp_sport", &tcpsport))
|
||||
{
|
||||
cfg->filters[i].tcpopts.sport = (__u16)tcpsport;
|
||||
cfg->filters[i].tcpopts.sport = (u16)tcpsport;
|
||||
cfg->filters[i].tcpopts.do_sport = 1;
|
||||
}
|
||||
|
||||
@@ -378,7 +370,7 @@ int ReadCfg(struct config *cfg)
|
||||
|
||||
if (config_setting_lookup_int64(filter, "tcp_dport", &tcpdport))
|
||||
{
|
||||
cfg->filters[i].tcpopts.dport = (__u16)tcpdport;
|
||||
cfg->filters[i].tcpopts.dport = (u16)tcpdport;
|
||||
cfg->filters[i].tcpopts.do_dport = 1;
|
||||
}
|
||||
|
||||
@@ -469,7 +461,7 @@ int ReadCfg(struct config *cfg)
|
||||
|
||||
if (config_setting_lookup_int64(filter, "udp_sport", &udpsport))
|
||||
{
|
||||
cfg->filters[i].udpopts.sport = (__u16)udpsport;
|
||||
cfg->filters[i].udpopts.sport = (u16)udpsport;
|
||||
cfg->filters[i].udpopts.do_sport = 1;
|
||||
}
|
||||
|
||||
@@ -478,7 +470,7 @@ int ReadCfg(struct config *cfg)
|
||||
|
||||
if (config_setting_lookup_int64(filter, "udp_dport", &udpdport))
|
||||
{
|
||||
cfg->filters[i].udpopts.dport = (__u16)udpdport;
|
||||
cfg->filters[i].udpopts.dport = (u16)udpdport;
|
||||
cfg->filters[i].udpopts.do_dport = 1;
|
||||
}
|
||||
|
||||
@@ -496,7 +488,7 @@ int ReadCfg(struct config *cfg)
|
||||
|
||||
if (config_setting_lookup_int(filter, "icmp_code", &icmpcode))
|
||||
{
|
||||
cfg->filters[i].icmpopts.code = (__u8)icmpcode;
|
||||
cfg->filters[i].icmpopts.code = (u8)icmpcode;
|
||||
cfg->filters[i].icmpopts.do_code = 1;
|
||||
}
|
||||
|
||||
@@ -505,7 +497,7 @@ int ReadCfg(struct config *cfg)
|
||||
|
||||
if (config_setting_lookup_int(filter, "icmp_type", &icmptype))
|
||||
{
|
||||
cfg->filters[i].icmpopts.type = (__u8)icmptype;
|
||||
cfg->filters[i].icmpopts.type = (u8)icmptype;
|
||||
cfg->filters[i].icmpopts.do_type = 1;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/all.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <libconfig.h>
|
||||
#include <string.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "xdpfw.h"
|
||||
#include <arpa/inet.h>
|
||||
|
||||
struct config
|
||||
{
|
||||
char *interface;
|
||||
__u16 updatetime;
|
||||
u16 updatetime;
|
||||
unsigned int nostats : 1;
|
||||
int stdout_update_time;
|
||||
struct filter filters[MAX_FILTERS];
|
||||
@@ -1,16 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct ip
|
||||
{
|
||||
__u32 ip;
|
||||
__u32 cidr;
|
||||
};
|
||||
#include <loader/utils/helpers.h>
|
||||
|
||||
/**
|
||||
* Parses an IP string with CIDR support. Stores IP in network byte order in ip.ip and CIDR in ip.cidr.
|
||||
16
src/loader/utils/helpers.h
Normal file
16
src/loader/utils/helpers.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/all.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct ip
|
||||
{
|
||||
u32 ip;
|
||||
u32 cidr;
|
||||
};
|
||||
|
||||
struct ip ParseIp(const char *ip);
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/bpf_common.h>
|
||||
|
||||
#include <bpf_helpers.h>
|
||||
#include <xdp/xdp_helpers.h>
|
||||
#include <xdp/prog_dispatcher.h>
|
||||
@@ -8,13 +8,12 @@
|
||||
#include <linux/in.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
#include <xdp/helpers.h>
|
||||
#include <common/all.h>
|
||||
|
||||
#include <xdpfw.h>
|
||||
#include <xdp/utils/rl.h>
|
||||
#include <xdp/utils/helpers.h>
|
||||
|
||||
#include <xdp/maps.h>
|
||||
#include <xdp/rl.h>
|
||||
#include <xdp/utils.h>
|
||||
#include <xdp/utils/maps.h>
|
||||
|
||||
SEC("xdp_prog")
|
||||
int xdp_prog_main(struct xdp_md *ctx)
|
||||
@@ -38,13 +37,13 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
return XDP_PASS;
|
||||
}
|
||||
|
||||
__u8 action = 0;
|
||||
u8 action = 0;
|
||||
__u64 blocktime = 1;
|
||||
|
||||
// Initialize IP headers.
|
||||
struct iphdr *iph = NULL;
|
||||
struct ipv6hdr *iph6 = NULL;
|
||||
__u128 src_ip6 = 0;
|
||||
u128 src_ip6 = 0;
|
||||
|
||||
// Set IPv4 and IPv6 common variables.
|
||||
if (eth->h_proto == htons(ETH_P_IPV6))
|
||||
@@ -75,7 +74,7 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
}
|
||||
|
||||
// Get stats map.
|
||||
__u32 key = 0;
|
||||
u32 key = 0;
|
||||
struct stats *stats = bpf_map_lookup_elem(&stats_map, &key);
|
||||
|
||||
__u64 now = bpf_ktime_get_ns();
|
||||
@@ -122,7 +121,7 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
}
|
||||
|
||||
// Retrieve total packet length.
|
||||
__u16 pkt_len = data_end - data;
|
||||
u16 pkt_len = data_end - data;
|
||||
|
||||
// Parse layer-4 headers and determine source port and protocol.
|
||||
struct tcphdr *tcph = NULL;
|
||||
@@ -130,8 +129,8 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
struct icmphdr *icmph = NULL;
|
||||
struct icmp6hdr *icmp6h = NULL;
|
||||
|
||||
__u16 src_port = 0;
|
||||
__u8 protocol = 0;
|
||||
u16 src_port = 0;
|
||||
u8 protocol = 0;
|
||||
|
||||
if (iph6)
|
||||
{
|
||||
@@ -241,9 +240,9 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
UpdateIpStats(&pps, &bps, iph->saddr, src_port, protocol, pkt_len, now);
|
||||
}
|
||||
|
||||
for (__u8 i = 0; i < MAX_FILTERS; i++)
|
||||
for (u8 i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
__u32 key = i;
|
||||
u32 key = i;
|
||||
|
||||
struct filter *filter = bpf_map_lookup_elem(&filters_map, &key);
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include <xdpfw.h>
|
||||
|
||||
#include <xdp/maps.h>
|
||||
#include <xdp/helpers.h>
|
||||
|
||||
#ifndef memcpy
|
||||
#define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n))
|
||||
#endif
|
||||
#include <xdp/utils/helpers.h>
|
||||
|
||||
/**
|
||||
* Checks if an IP is within a specific CIDR range.
|
||||
@@ -18,7 +9,7 @@
|
||||
*
|
||||
* @return 1 on yes, 0 on no.
|
||||
*/
|
||||
static __always_inline __u8 IsIpInRange(__u32 src_ip, __u32 net_ip, __u8 cidr)
|
||||
static __always_inline u8 IsIpInRange(u32 src_ip, u32 net_ip, u8 cidr)
|
||||
{
|
||||
return !((src_ip ^ net_ip) & htonl(0xFFFFFFFFu << (32 - cidr)));
|
||||
}
|
||||
33
src/xdp/utils/helpers.h
Normal file
33
src/xdp/utils/helpers.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/all.h>
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/bpf_common.h>
|
||||
|
||||
#include <bpf_helpers.h>
|
||||
#include <xdp/xdp_helpers.h>
|
||||
#include <xdp/prog_dispatcher.h>
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define htons(x) ((__be16)___constant_swab16((x)))
|
||||
#define ntohs(x) ((__be16)___constant_swab16((x)))
|
||||
#define htonl(x) ((__be32)___constant_swab32((x)))
|
||||
#define ntohl(x) ((__be32)___constant_swab32((x)))
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define htons(x) (x)
|
||||
#define ntohs(X) (x)
|
||||
#define htonl(x) (x)
|
||||
#define ntohl(x) (x)
|
||||
#endif
|
||||
|
||||
#ifndef memcpy
|
||||
#define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n))
|
||||
#endif
|
||||
|
||||
static __always_inline u8 IsIpInRange(u32 src_ip, u32 net_ip, u8 cidr);
|
||||
|
||||
#include "helpers.c"
|
||||
@@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <xdpfw.h>
|
||||
#include <common/int_types.h>
|
||||
#include <common/types.h>
|
||||
|
||||
#include <xdp/helpers.h>
|
||||
#include <xdp/utils/helpers.h>
|
||||
|
||||
struct
|
||||
{
|
||||
@@ -14,7 +15,7 @@ struct
|
||||
{
|
||||
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
|
||||
__uint(max_entries, MAX_FILTERS);
|
||||
__type(key, __u32);
|
||||
__type(key, u32);
|
||||
__type(value, struct filter);
|
||||
} filters_map SEC(".maps");
|
||||
|
||||
@@ -22,7 +23,7 @@ struct
|
||||
{
|
||||
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
|
||||
__uint(max_entries, 1);
|
||||
__type(key, __u32);
|
||||
__type(key, u32);
|
||||
__type(value, struct stats);
|
||||
} stats_map SEC(".maps");
|
||||
|
||||
@@ -33,7 +34,7 @@ struct
|
||||
#ifdef USE_FLOW_RL
|
||||
__type(key, struct flow);
|
||||
#else
|
||||
__type(key, __u32);
|
||||
__type(key, u32);
|
||||
#endif
|
||||
__type(value, struct ip_stats);
|
||||
} ip_stats_map SEC(".maps");
|
||||
@@ -42,7 +43,7 @@ struct
|
||||
{
|
||||
__uint(type, BPF_MAP_TYPE_LRU_HASH);
|
||||
__uint(max_entries, MAX_TRACK_IPS);
|
||||
__type(key, __u32);
|
||||
__type(key, u32);
|
||||
__type(value, __u64);
|
||||
} ip_blacklist_map SEC(".maps");
|
||||
|
||||
@@ -53,7 +54,7 @@ struct
|
||||
#ifdef USE_FLOW_RL
|
||||
__type(key, struct flow6);
|
||||
#else
|
||||
__type(key, __u128);
|
||||
__type(key, u128);
|
||||
#endif
|
||||
__type(value, struct ip_stats);
|
||||
} ip6_stats_map SEC(".maps");
|
||||
@@ -62,6 +63,6 @@ struct
|
||||
{
|
||||
__uint(type, BPF_MAP_TYPE_LRU_HASH);
|
||||
__uint(max_entries, MAX_TRACK_IPS);
|
||||
__type(key, __u128);
|
||||
__type(key, u128);
|
||||
__type(value, __u64);
|
||||
} ip6_blacklist_map SEC(".maps");
|
||||
@@ -1,9 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include <xdpfw.h>
|
||||
|
||||
#include <xdp/maps.h>
|
||||
#include <xdp/helpers.h>
|
||||
#include <xdp/utils/rl.h>
|
||||
|
||||
/**
|
||||
* Updates IPv4 client stats.
|
||||
@@ -18,7 +13,7 @@
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static __always_inline void UpdateIpStats(__u64 *pps, __u64 *bps, __u32 ip, __u16 port, __u8 protocol, __u16 pkt_len, __u64 now)
|
||||
static __always_inline void UpdateIpStats(__u64 *pps, __u64 *bps, u32 ip, u16 port, u8 protocol, u16 pkt_len, __u64 now)
|
||||
{
|
||||
#ifdef USE_FLOW_RL
|
||||
struct flow key = {0};
|
||||
@@ -83,7 +78,7 @@ static __always_inline void UpdateIpStats(__u64 *pps, __u64 *bps, __u32 ip, __u1
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static __always_inline void UpdateIp6Stats(__u64 *pps, __u64 *bps, __u128 *ip, __u16 port, __u8 protocol, __u16 pkt_len, __u64 now)
|
||||
static __always_inline void UpdateIp6Stats(__u64 *pps, __u64 *bps, u128 *ip, u16 port, u8 protocol, u16 pkt_len, __u64 now)
|
||||
{
|
||||
#ifdef USE_FLOW_RL
|
||||
struct flow6 key = {0};
|
||||
12
src/xdp/utils/rl.h
Normal file
12
src/xdp/utils/rl.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/all.h>
|
||||
|
||||
#include <xdp/utils/helpers.h>
|
||||
|
||||
#include <xdp/utils/maps.h>
|
||||
|
||||
static __always_inline void UpdateIpStats(__u64 *pps, __u64 *bps, u32 ip, u16 port, u8 protocol, u16 pkt_len, __u64 now);
|
||||
static __always_inline void UpdateIp6Stats(__u64 *pps, __u64 *bps, u128 *ip, u16 port, u8 protocol, u16 pkt_len, __u64 now);
|
||||
|
||||
#include "rl.c"
|
||||
172
src/xdpfw.h
172
src/xdpfw.h
@@ -1,172 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define MAX_PCKT_LENGTH 65535
|
||||
#define MAX_FILTERS 60
|
||||
#define MAX_TRACK_IPS 100000
|
||||
#define MAX_CPUS 256
|
||||
#define NANO_TO_SEC 1000000000
|
||||
|
||||
#define __u128 __uint128_t
|
||||
|
||||
// Additional options for XDP program.
|
||||
//#define DEBUG
|
||||
|
||||
// Feel free to comment this out if you don't want the `blocked` entry on the stats map to be incremented every single time a packet is dropped from the source IP being on the blocked map. Commenting this line out should increase performance when blocking malicious traffic.
|
||||
#define DOSTATSONBLOCKMAP
|
||||
|
||||
// When this is defined, a check will occur inside the IPv4 and IPv6 filters. For IPv6 packets, if no IPv6 source/destination IP addresses are set, but there is an IPv4 address, it will ignore the filter. The same goes for IPv4, if there is no IPv4 source/destination IP addresses set, if an IPv6 address is set, it will ignore the filter.
|
||||
#define ALLOWSINGLEIPV4V6
|
||||
|
||||
// If uncommented, rate limits for clients are determined using the source IP, port, and protocol instead of just the source IP.
|
||||
// This allows for more precise rate limits (connection-specific instead of a single source IP).
|
||||
// I decided not to include the destination IP/port because the source IP, port, and protocol should be represent a unique connection.
|
||||
#define USE_FLOW_RL
|
||||
|
||||
#ifdef __BPF__
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define htons(x) ((__be16)___constant_swab16((x)))
|
||||
#define ntohs(x) ((__be16)___constant_swab16((x)))
|
||||
#define htonl(x) ((__be32)___constant_swab32((x)))
|
||||
#define ntohl(x) ((__be32)___constant_swab32((x)))
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define htons(x) (x)
|
||||
#define ntohs(X) (x)
|
||||
#define htonl(x) (x)
|
||||
#define ntohl(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct tcpopts
|
||||
{
|
||||
unsigned int enabled : 1;
|
||||
|
||||
unsigned int do_sport : 1;
|
||||
__u16 sport;
|
||||
|
||||
unsigned int do_dport : 1;
|
||||
__u16 dport;
|
||||
|
||||
// TCP flags.
|
||||
unsigned int do_urg : 1;
|
||||
unsigned int urg : 1;
|
||||
|
||||
unsigned int do_ack : 1;
|
||||
unsigned int ack : 1;
|
||||
|
||||
unsigned int do_rst : 1;
|
||||
unsigned int rst : 1;
|
||||
|
||||
unsigned int do_psh : 1;
|
||||
unsigned int psh : 1;
|
||||
|
||||
unsigned int do_syn : 1;
|
||||
unsigned int syn : 1;
|
||||
|
||||
unsigned int do_fin : 1;
|
||||
unsigned int fin : 1;
|
||||
|
||||
unsigned int do_ece : 1;
|
||||
unsigned int ece : 1;
|
||||
|
||||
unsigned int do_cwr : 1;
|
||||
unsigned int cwr : 1;
|
||||
};
|
||||
|
||||
struct udpopts
|
||||
{
|
||||
unsigned int enabled : 1;
|
||||
|
||||
unsigned int do_sport : 1;
|
||||
__u16 sport;
|
||||
|
||||
unsigned int do_dport : 1;
|
||||
__u16 dport;
|
||||
};
|
||||
|
||||
struct icmpopts
|
||||
{
|
||||
unsigned int enabled : 1;
|
||||
|
||||
unsigned int do_code : 1;
|
||||
__u8 code;
|
||||
|
||||
unsigned int do_type : 1;
|
||||
__u8 type;
|
||||
};
|
||||
|
||||
struct filter
|
||||
{
|
||||
__u8 id;
|
||||
|
||||
unsigned int enabled : 1;
|
||||
|
||||
__u8 action;
|
||||
|
||||
__u32 src_ip;
|
||||
__u8 src_cidr;
|
||||
|
||||
__u32 dst_ip;
|
||||
__u8 dst_cidr;
|
||||
|
||||
__u32 src_ip6[4];
|
||||
__u32 dst_ip6[4];
|
||||
|
||||
unsigned int do_min_ttl : 1;
|
||||
__u8 min_ttl;
|
||||
|
||||
unsigned int do_max_ttl : 1;
|
||||
__u8 max_ttl;
|
||||
|
||||
unsigned int do_min_len : 1;
|
||||
__u16 min_len;
|
||||
|
||||
unsigned int do_max_len : 1;
|
||||
__u16 max_len;
|
||||
|
||||
unsigned int do_tos : 1;
|
||||
int8_t tos;
|
||||
|
||||
unsigned int do_pps : 1;
|
||||
__u64 pps;
|
||||
|
||||
unsigned int do_bps : 1;
|
||||
__u64 bps;
|
||||
|
||||
__u64 blocktime;
|
||||
|
||||
struct tcpopts tcpopts;
|
||||
struct udpopts udpopts;
|
||||
struct icmpopts icmpopts;
|
||||
} __attribute__((__aligned__(8)));
|
||||
|
||||
struct stats
|
||||
{
|
||||
__u64 allowed;
|
||||
__u64 dropped;
|
||||
__u64 passed;
|
||||
};
|
||||
|
||||
struct ip_stats
|
||||
{
|
||||
__u64 pps;
|
||||
__u64 bps;
|
||||
__u64 next_update;
|
||||
};
|
||||
|
||||
struct flow
|
||||
{
|
||||
__u32 ip;
|
||||
__u16 port;
|
||||
__u8 protocol;
|
||||
};
|
||||
|
||||
struct flow6
|
||||
{
|
||||
__u128 ip;
|
||||
__u16 port;
|
||||
__u8 protocol;
|
||||
};
|
||||
Reference in New Issue
Block a user