Improved config and added additional functionality.

This commit is contained in:
Christian Deacon
2020-05-05 23:58:34 +00:00
parent 5a2589b178
commit f88a52f792
3 changed files with 122 additions and 50 deletions

View File

@@ -17,21 +17,44 @@ void SetConfigDefaults(struct config_map *cfg)
for (uint16_t i = 0; i < MAX_FILTERS; i++) for (uint16_t i = 0; i < MAX_FILTERS; i++)
{ {
cfg->filters[i].id = 0;
cfg->filters[i].enabled = 0; cfg->filters[i].enabled = 0;
cfg->filters[i].action = 0; cfg->filters[i].action = 0;
cfg->filters[i].srcIP = 0; cfg->filters[i].srcIP = 0;
cfg->filters[i].dstIP = 0; cfg->filters[i].dstIP = 0;
cfg->filters[i].min_id = 0;
cfg->filters[i].max_id = 4294967295; cfg->filters[i].do_min_len = 0;
cfg->filters[i].min_len = 0; cfg->filters[i].min_len = 0;
cfg->filters[i].do_max_len = 0;
cfg->filters[i].max_len = 65535; cfg->filters[i].max_len = 65535;
cfg->filters[i].do_min_ttl = 0;
cfg->filters[i].min_ttl = 0; cfg->filters[i].min_ttl = 0;
cfg->filters[i].do_max_ttl = 0;
cfg->filters[i].max_ttl = 255; cfg->filters[i].max_ttl = 255;
cfg->filters[i].do_tos = 0;
cfg->filters[i].tos = 0; cfg->filters[i].tos = 0;
cfg->filters[i].tcpopts.enabled = 0; cfg->filters[i].tcpopts.enabled = 0;
cfg->filters[i].tcpopts.do_dport = 0;
cfg->filters[i].tcpopts.do_dport = 0;
cfg->filters[i].tcpopts.do_urg = 0;
cfg->filters[i].tcpopts.do_ack = 0;
cfg->filters[i].tcpopts.do_rst = 0;
cfg->filters[i].tcpopts.do_psh = 0;
cfg->filters[i].tcpopts.do_syn = 0;
cfg->filters[i].tcpopts.do_fin = 0;
cfg->filters[i].udpopts.enabled = 0; cfg->filters[i].udpopts.enabled = 0;
cfg->filters[i].udpopts.do_sport = 0;
cfg->filters[i].udpopts.do_dport = 0;
cfg->filters[i].icmpopts.enabled = 0; cfg->filters[i].icmpopts.enabled = 0;
cfg->filters[i].icmpopts.do_code = 0;
cfg->filters[i].icmpopts.do_type = 0;
for (uint16_t j = 0; j < MAX_PCKT_LENGTH - 1; j++) for (uint16_t j = 0; j < MAX_PCKT_LENGTH - 1; j++)
{ {
@@ -184,6 +207,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int(filter, "min_ttl", &min_ttl)) if (config_setting_lookup_int(filter, "min_ttl", &min_ttl))
{ {
cfg->filters[i].min_ttl = (uint8_t)min_ttl; cfg->filters[i].min_ttl = (uint8_t)min_ttl;
cfg->filters[i].do_min_ttl = 1;
} }
// Maximum TTL (not required). // Maximum TTL (not required).
@@ -192,6 +216,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int(filter, "max_ttl", &max_ttl)) if (config_setting_lookup_int(filter, "max_ttl", &max_ttl))
{ {
cfg->filters[i].max_ttl = (uint8_t)max_ttl; cfg->filters[i].max_ttl = (uint8_t)max_ttl;
cfg->filters[i].do_max_ttl = 1;
} }
// Minimum length (not required). // Minimum length (not required).
@@ -200,6 +225,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int(filter, "min_len", &min_len)) if (config_setting_lookup_int(filter, "min_len", &min_len))
{ {
cfg->filters[i].min_len = min_len; cfg->filters[i].min_len = min_len;
cfg->filters[i].do_min_len = 1;
} }
// Maximum length (not required). // Maximum length (not required).
@@ -208,6 +234,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int(filter, "max_len", &max_len)) if (config_setting_lookup_int(filter, "max_len", &max_len))
{ {
cfg->filters[i].max_len = max_len; cfg->filters[i].max_len = max_len;
cfg->filters[i].do_max_len = 1;
} }
// TOS (not required). // TOS (not required).
@@ -216,6 +243,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int(filter, "tos", &tos)) if (config_setting_lookup_int(filter, "tos", &tos))
{ {
cfg->filters[i].tos = (uint8_t)tos; cfg->filters[i].tos = (uint8_t)tos;
cfg->filters[i].do_tos = 1;
} }
// Payload match. // Payload match.
@@ -265,6 +293,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int64(tcp, "sport", &sport)) if (config_setting_lookup_int64(tcp, "sport", &sport))
{ {
cfg->filters[i].tcpopts.sport = (uint16_t)sport; cfg->filters[i].tcpopts.sport = (uint16_t)sport;
cfg->filters[i].tcpopts.do_sport = 1;
} }
// Destination port. // Destination port.
@@ -273,6 +302,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int64(tcp, "dport", &dport)) if (config_setting_lookup_int64(tcp, "dport", &dport))
{ {
cfg->filters[i].tcpopts.dport = (uint16_t)dport; cfg->filters[i].tcpopts.dport = (uint16_t)dport;
cfg->filters[i].tcpopts.do_dport = 1;
} }
// URG flag. // URG flag.
@@ -281,6 +311,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_bool(tcp, "urg", &urg)) if (config_setting_lookup_bool(tcp, "urg", &urg))
{ {
cfg->filters[i].tcpopts.urg = urg; cfg->filters[i].tcpopts.urg = urg;
cfg->filters[i].tcpopts.do_urg = 1;
} }
// ACK flag. // ACK flag.
@@ -289,6 +320,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_bool(tcp, "ack", &ack)) if (config_setting_lookup_bool(tcp, "ack", &ack))
{ {
cfg->filters[i].tcpopts.ack = ack; cfg->filters[i].tcpopts.ack = ack;
cfg->filters[i].tcpopts.do_ack = 1;
} }
// RST flag. // RST flag.
@@ -297,6 +329,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_bool(tcp, "rst", &rst)) if (config_setting_lookup_bool(tcp, "rst", &rst))
{ {
cfg->filters[i].tcpopts.rst = rst; cfg->filters[i].tcpopts.rst = rst;
cfg->filters[i].tcpopts.do_rst = 1;
} }
// PSH flag. // PSH flag.
@@ -305,6 +338,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_bool(tcp, "psh", &psh)) if (config_setting_lookup_bool(tcp, "psh", &psh))
{ {
cfg->filters[i].tcpopts.psh = psh; cfg->filters[i].tcpopts.psh = psh;
cfg->filters[i].tcpopts.do_psh = 1;
} }
// SYN flag. // SYN flag.
@@ -313,6 +347,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_bool(tcp, "syn", &syn)) if (config_setting_lookup_bool(tcp, "syn", &syn))
{ {
cfg->filters[i].tcpopts.syn = syn; cfg->filters[i].tcpopts.syn = syn;
cfg->filters[i].tcpopts.do_syn = 1;
} }
// FIN flag. // FIN flag.
@@ -321,6 +356,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_bool(tcp, "fin", &fin)) if (config_setting_lookup_bool(tcp, "fin", &fin))
{ {
cfg->filters[i].tcpopts.fin = fin; cfg->filters[i].tcpopts.fin = fin;
cfg->filters[i].tcpopts.do_fin = 1;
} }
} }
} }
@@ -349,6 +385,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int64(udp, "sport", &sport)) if (config_setting_lookup_int64(udp, "sport", &sport))
{ {
cfg->filters[i].udpopts.sport = (uint16_t)sport; cfg->filters[i].udpopts.sport = (uint16_t)sport;
cfg->filters[i].udpopts.do_sport = 1;
} }
// Destination port. // Destination port.
@@ -357,6 +394,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int64(udp, "dport", &dport)) if (config_setting_lookup_int64(udp, "dport", &dport))
{ {
cfg->filters[i].udpopts.dport = (uint16_t)dport; cfg->filters[i].udpopts.dport = (uint16_t)dport;
cfg->filters[i].udpopts.do_dport = 1;
} }
} }
} }
@@ -385,6 +423,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int(icmp, "code", &code)) if (config_setting_lookup_int(icmp, "code", &code))
{ {
cfg->filters[i].icmpopts.code = (uint8_t)code; cfg->filters[i].icmpopts.code = (uint8_t)code;
cfg->filters[i].icmpopts.do_code = 1;
} }
// ICMP type. // ICMP type.
@@ -393,10 +432,14 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int(icmp, "type", &type)) if (config_setting_lookup_int(icmp, "type", &type))
{ {
cfg->filters[i].icmpopts.type = (uint8_t)type; cfg->filters[i].icmpopts.type = (uint8_t)type;
cfg->filters[i].icmpopts.do_type = 1;
} }
} }
} }
// Assign ID.
cfg->filters[i].id = filters + 1;
// Increase filter count. // Increase filter count.
filters++; filters++;
} }

View File

@@ -4,21 +4,35 @@
#include <inttypes.h> #include <inttypes.h>
#define MAX_PCKT_LENGTH 65535 #define MAX_PCKT_LENGTH 65535
#define MAX_FILTERS 255 #define MAX_FILTERS 50
struct tcpopts struct tcpopts
{ {
unsigned int enabled : 1; unsigned int enabled : 1;
unsigned int do_sport : 1;
uint16_t sport; uint16_t sport;
unsigned int do_dport : 1;
uint16_t dport; uint16_t dport;
// TCP flags. // TCP flags.
unsigned int do_urg : 1;
unsigned int urg : 1; unsigned int urg : 1;
unsigned int do_ack : 1;
unsigned int ack : 1; unsigned int ack : 1;
unsigned int do_rst : 1;
unsigned int rst : 1; unsigned int rst : 1;
unsigned int do_psh : 1;
unsigned int psh : 1; unsigned int psh : 1;
unsigned int do_syn : 1;
unsigned int syn : 1; unsigned int syn : 1;
unsigned int do_fin : 1;
unsigned int fin : 1; unsigned int fin : 1;
}; };
@@ -26,7 +40,10 @@ struct udpopts
{ {
unsigned int enabled : 1; unsigned int enabled : 1;
unsigned int do_sport : 1;
uint16_t sport; uint16_t sport;
unsigned int do_dport : 1;
uint16_t dport; uint16_t dport;
}; };
@@ -34,12 +51,17 @@ struct icmpopts
{ {
unsigned int enabled : 1; unsigned int enabled : 1;
unsigned int do_code : 1;
uint8_t code; uint8_t code;
unsigned int do_type : 1;
uint8_t type; uint8_t type;
}; };
struct filter struct filter
{ {
uint8_t id;
unsigned int enabled : 1; unsigned int enabled : 1;
uint8_t action; uint8_t action;
@@ -47,15 +69,19 @@ struct filter
uint32_t srcIP; uint32_t srcIP;
uint32_t dstIP; uint32_t dstIP;
unsigned int do_min_ttl : 1;
uint8_t min_ttl; uint8_t min_ttl;
unsigned int do_max_ttl : 1;
uint8_t max_ttl; uint8_t max_ttl;
unsigned int do_min_len : 1;
uint16_t min_len; uint16_t min_len;
unsigned int do_max_len : 1;
uint16_t max_len; uint16_t max_len;
uint32_t min_id; unsigned int do_tos : 1;
uint32_t max_id;
int8_t tos; int8_t tos;
uint8_t payloadMatch[MAX_PCKT_LENGTH]; uint8_t payloadMatch[MAX_PCKT_LENGTH];
@@ -66,4 +92,11 @@ struct filter
struct icmpopts icmpopts; struct icmpopts icmpopts;
}; };
struct xdpfw_stats
{
uint64_t allowed;
uint64_t blocked;
};
#endif #endif

View File

@@ -35,6 +35,7 @@ const struct option opts[] =
static uint8_t cont = 1; static uint8_t cont = 1;
static int filter_map_fd = -1; static int filter_map_fd = -1;
static int count_map_fd = -1; static int count_map_fd = -1;
static int stats_map_fd = -1;
void signalHndl(int tmp) void signalHndl(int tmp)
{ {
@@ -78,18 +79,17 @@ void parse_command_line(int argc, char *argv[])
void update_BPF(struct config_map *conf) void update_BPF(struct config_map *conf)
{ {
// Loop through all filters and delete the map. // Loop through all filters and delete the map.
for (uint32_t i = 0; i < MAX_FILTERS; i++) for (uint8_t i = 0; i < MAX_FILTERS; i++)
{ {
if (bpf_map_delete_elem(filter_map_fd, &i) != 0) uint32_t key = i;
{
fprintf(stderr, "Error deleting BPF item #%d\n", i); bpf_map_delete_elem(filter_map_fd, &key);
}
} }
// Add a filter to the filter maps. // Add a filter to the filter maps.
for (uint32_t i = 0; i < conf->filterCount; i++) for (uint32_t i = 0; i < conf->filterCount; i++)
{ {
if (bpf_map_update_elem(filter_map_fd, &i, &conf->filters[i], BPF_ANY)) if (bpf_map_update_elem(filter_map_fd, &i, &conf->filters[i], BPF_ANY) == -1)
{ {
fprintf(stderr, "Error updating BPF item #%d\n", i); fprintf(stderr, "Error updating BPF item #%d\n", i);
} }
@@ -162,6 +162,7 @@ int load_bpf_object_file__simple(const char *filename)
filter_map_fd = find_map_fd(obj, "filters_map"); filter_map_fd = find_map_fd(obj, "filters_map");
count_map_fd = find_map_fd(obj, "count_map"); count_map_fd = find_map_fd(obj, "count_map");
stats_map_fd = find_map_fd(obj, "stats_map");
return first_prog_fd; return first_prog_fd;
} }
@@ -254,38 +255,6 @@ static int xdp_attach(int ifindex, uint32_t *xdp_flags, int prog_fd)
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
void SetConfigDefaultsX(struct config_map *cfg)
{
cfg->updateTime = 0;
cfg->interface = "eth0";
for (uint16_t i = 0; i < MAX_FILTERS; i++)
{
cfg->filters[i].enabled = 0;
cfg->filters[i].action = 0;
cfg->filters[i].srcIP = 0;
cfg->filters[i].dstIP = 0;
cfg->filters[i].min_id = 0;
cfg->filters[i].max_id = 4294967295;
cfg->filters[i].min_len = 0;
cfg->filters[i].max_len = 65535;
cfg->filters[i].min_ttl = 0;
cfg->filters[i].max_ttl = 255;
cfg->filters[i].tos = 0;
cfg->filters[i].tcpopts.enabled = 0;
cfg->filters[i].udpopts.enabled = 0;
cfg->filters[i].icmpopts.enabled = 0;
for (uint16_t j = 0; i < MAX_PCKT_LENGTH; i++)
{
cfg->filters[i].payloadMatch[j] = 0;
}
cfg->filters[i].payloadLen = 0;
}
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
// Parse the command line. // Parse the command line.
@@ -311,11 +280,12 @@ int main(int argc, char *argv[])
// Initialize config. // Initialize config.
struct config_map *conf = malloc(sizeof(struct config_map)); struct config_map *conf = malloc(sizeof(struct config_map));
SetConfigDefaults(conf); SetConfigDefaults(conf);
// Create last updated variable. // Create last updated variable.
time_t lastUpdated = time(NULL); time_t lastUpdated = time(NULL);
time_t statsLastUpdated = time(NULL);
// Update config. // Update config.
update_config(conf, configFile); update_config(conf, configFile);
@@ -333,6 +303,7 @@ int main(int argc, char *argv[])
fprintf(stdout, "Filter #%" PRIu16 ":\n", (i + 1)); fprintf(stdout, "Filter #%" PRIu16 ":\n", (i + 1));
// Main. // Main.
fprintf(stdout, "ID => %d\n", conf->filters[i].id);
fprintf(stdout, "Enabled => %" PRIu8 "\n", conf->filters[i].enabled); fprintf(stdout, "Enabled => %" PRIu8 "\n", conf->filters[i].enabled);
fprintf(stdout, "Action => %" PRIu8 " (0 = Block, 1 = Allow).\n", conf->filters[i].action); fprintf(stdout, "Action => %" PRIu8 " (0 = Block, 1 = Allow).\n", conf->filters[i].action);
@@ -350,8 +321,6 @@ int main(int argc, char *argv[])
fprintf(stdout, "Min Length => %" PRIu16 "\n", conf->filters[i].min_len); fprintf(stdout, "Min Length => %" PRIu16 "\n", conf->filters[i].min_len);
fprintf(stdout, "Max TTL => %" PRIu8 "\n", conf->filters[i].max_ttl); fprintf(stdout, "Max TTL => %" PRIu8 "\n", conf->filters[i].max_ttl);
fprintf(stdout, "Min TTL => %" PRIu8 "\n", conf->filters[i].min_ttl); fprintf(stdout, "Min TTL => %" PRIu8 "\n", conf->filters[i].min_ttl);
fprintf(stdout, "Max ID => %" PRIu32 "\n", conf->filters[i].max_id);
fprintf(stdout, "Min ID => %" PRIu32 "\n", conf->filters[i].min_id);
fprintf(stdout, "TOS => %" PRIu8 "\n\n", conf->filters[i].tos); fprintf(stdout, "TOS => %" PRIu8 "\n\n", conf->filters[i].tos);
// TCP Options. // TCP Options.
@@ -417,7 +386,7 @@ int main(int argc, char *argv[])
// Check for valid maps. // Check for valid maps.
if (filter_map_fd < 0) if (filter_map_fd < 0)
{ {
fprintf(stderr, "Error finding 'filters_map' BPF map\n"); fprintf(stderr, "Error finding 'filters_map' BPF map.\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@@ -429,6 +398,16 @@ int main(int argc, char *argv[])
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (stats_map_fd < 0)
{
fprintf(stderr, "Error finding 'stats_map' BPF map.\n");
return EXIT_FAILURE;
}
// Update BPF maps.
update_BPF(conf);
// Signal. // Signal.
signal(SIGINT, signalHndl); signal(SIGINT, signalHndl);
@@ -450,6 +429,23 @@ int main(int argc, char *argv[])
lastUpdated = time(NULL); lastUpdated = time(NULL);
} }
// Update stats.
if ((curTime - statsLastUpdated) > 5)
{
uint16_t key = 0;
struct xdpfw_stats *stats;
bpf_map_lookup_elem(stats_map_fd, &key, stats);
if (stats != NULL)
{
fprintf(stdout, "\rPackets allowed: %" PRIu64 "\n", stats->allowed);
fprintf(stdout, "\rPackets blocked: %" PRIu64 "\n", stats->blocked);
fflush(stdout);
}
}
sleep(1); sleep(1);
} }