summary refs log tree commit diff
path: root/main.c
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2025-05-05 02:39:41 +0200
committerRory& <root@rory.gay>2025-05-05 02:39:41 +0200
commit527b97657ecb3b050a251e164360151eb1d977b5 (patch)
tree4d04f5eb0018386ec3869445ea3ab928c7a1cfbb /main.c
downloadBlockScrapersC-527b97657ecb3b050a251e164360151eb1d977b5.tar.xz
Initial commit
Diffstat (limited to 'main.c')
-rw-r--r--main.c308
1 files changed, 308 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644

index 0000000..e59aef8 --- /dev/null +++ b/main.c
@@ -0,0 +1,308 @@ +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <pthread.h> + +#define ALLOWED_PATTERNS_FILE "allowed_patterns.txt" +#define ALLOWED_IPS_FILE "allowed_ips.txt" +#define PATTERNS_FILE "patterns.txt" +#define ACCESS_LOG_FILE "access.log.1" +// #define ACCESS_LOG_FILE "/var/log/nginx/access.log" + +typedef struct +{ + char** patterns; + char** allowed_patterns; + char** allowedIps; + // size_t allowedIpCount; + char** bannedIps; + size_t bannedIpCount; + size_t bannedIpSize; +} MatchRules; + + +bool print_allowed_ip = false; +bool print_allowed_pattern = false; +bool print_banned_ip = false; +// bool print_allowed_ip = strcmp(getenv("PRINT_"), "1") == 0; + +void* xmalloc(size_t size) +{ + void* ptr = malloc(size); + if (ptr == NULL) + { + fprintf(stderr, "Memory allocation failed\n"); + exit(EXIT_FAILURE); + } + return ptr; +} + +void read_lines_cb(const char* filename, void cb(char*, void*), void* cbData) +{ + if (cb == nullptr) + { + fprintf(stderr, "Callback function is null\n"); + return; + } + + clock_t ctime = clock(), lastPrint = clock(); + FILE* file = fopen(filename, "r"); + if (file == NULL) + { + fprintf(stderr, "Error opening file %s: ", filename); + perror(""); + return; + } + + int count = 0; + char* buf = xmalloc(10000); + while (fgets(buf, 10000, file) != NULL) + { + if (buf[0] == '#') + { + continue; + } + count++; + buf[strcspn(buf, "\n")] = 0; + char* line = strdup(buf); + + if (cb != nullptr) + cb(line, cbData); + free(line); + + if (count % 10 == 0) + { + double elapsed = (clock() - lastPrint) * 1000.0 / CLOCKS_PER_SEC; + if (elapsed > 50.0) + { + fprintf(stderr, "\rRead %d lines from %s in %.3f ms (%.3f/s)\r", count, filename, (clock() - ctime) * 1000.0 / CLOCKS_PER_SEC, + count * 1000.0 / (clock() - ctime)); + lastPrint = clock(); + } + } + } + + free(buf); + + fclose(file); + printf("Read %d definitions from %s in %.3f ms (%.3f/s)\n", count, filename, (clock() - ctime) * 1000.0 / CLOCKS_PER_SEC, count * 1000.0 / (clock() - ctime)); +} + +char** read_lines(const char* filename) +{ + clock_t ctime = clock(), lastPrint = clock(); + FILE* file = fopen(filename, "r"); + if (file == NULL) + { + fprintf(stderr, "Error opening file %s: ", filename); + perror(""); + return nullptr; + } + + int count = 0; + { + char* buf = xmalloc(10000); + while (fgets(buf, 10000, file) != NULL) + { + if (buf[0] == '#') + { + continue; + } + count++; + } + + free(buf); + rewind(file); + } + fprintf(stderr, "Counted %d lines from %s in %.3f ms\n", count, filename, (clock() - ctime) * 1000.0 / CLOCKS_PER_SEC); + + // count = count_lines(file); + // printf("Counted %d lines from %s in %.3f ms\n", count, filename, (clock() - ctime) * 1000.0 / CLOCKS_PER_SEC); + + + rewind(file); + char** lines = xmalloc((count + 1) * sizeof(char*)); + + char* buf = xmalloc(10000); + for (int i = 0; i < count; i++) + { + if (fgets(buf, 10000, file) == NULL) + { + fprintf(stderr, "Error reading line %d from %s\n", i + 1, filename); + free(buf); + return nullptr; + } + + if (buf[0] == '#') + { + i--; + continue; + } + + buf[strcspn(buf, "\n")] = 0; + lines[i] = strdup(buf); + + + double elapsed = (clock() - lastPrint) * 1000.0 / CLOCKS_PER_SEC; + if (elapsed > 50) + { + fprintf(stderr, "\rRead %d lines from %s in %.3f ms\r", i + 1, filename, (clock() - ctime) * 1000.0 / CLOCKS_PER_SEC); + lastPrint = clock(); + } + } + free(buf); + lines[count] = nullptr; + + fclose(file); + printf("Read %d definitions from %s in %.3f ms\n", count, filename, (clock() - ctime) * 1000.0 / CLOCKS_PER_SEC); + return lines; +} + +char** grow_string_array(char** array, size_t newSize) +{ + printf("Growing charptr array to %zu\n", newSize); + char** newArray = realloc(array, sizeof(char*) * newSize); + if (newArray == NULL) + { + fprintf(stderr, "Memory allocation failed\n"); + exit(EXIT_FAILURE); + } + return newArray; +} + +void process_line(char* line, void* cbData) +{ + MatchRules* rules = cbData; + + if (line == NULL) + { + fprintf(stderr, "Line is null @ process_line!\n"); + return; + } + + + char* ip = xmalloc(32); + for (int i = 0; i < 32; i++) + { + ip[i] = 0; + } + strncpy(ip, line, strcspn(line, " ")); + + // printf("meow %s\n", ip); + + + for (int j = 0; rules->allowedIps[j] != NULL; j++) + { + if (strstr(ip, rules->allowedIps[j]) == ip) + { + if (print_allowed_ip) + printf("Allowed IP: \"%s\" (~%s): %s\r", ip, rules->allowedIps[j], line); + free(ip); + return; + } + } + + // printf("Checking IP %s against %d banned IPs\n", ip, rules->bannedIpCount); + for (size_t j = 0; j < rules->bannedIpCount; j++) + { + if (strstr(ip, rules->bannedIps[j]) == ip) + { + if (print_banned_ip) + printf("Banned IP: \"%s\": %s\r", rules->bannedIps[j], line); + free(ip); + return; + } + } + + for (int i = 0; rules->allowed_patterns[i] != NULL; i++) + { + if (strstr(line, rules->allowed_patterns[i]) != NULL) + { + if (print_allowed_pattern) + printf("%15s matched allowed pattern \"%s\": %s\n", ip, rules->allowed_patterns[i], line); + return; + } + } + + for (int i = 0; rules->patterns[i] != NULL; i++) + { + if (strstr(line, rules->patterns[i]) != NULL) + { + if (rules->bannedIpCount >= rules->bannedIpSize) + { + rules->bannedIpSize *= 2; + rules->bannedIps = grow_string_array(rules->bannedIps, rules->bannedIpSize); + } + + rules->bannedIps[rules->bannedIpCount] = ip; + rules->bannedIps[rules->bannedIpCount][strcspn(rules->bannedIps[rules->bannedIpCount], "\n")] = 0; + rules->bannedIps[rules->bannedIpCount + 1] = nullptr; + rules->bannedIpCount++; + printf("[Bans=%6lu] %15s matched pattern \"%s\": %s\n", rules->bannedIpCount, ip, rules->patterns[i], line); + + + signal(SIGCHLD, nullptr); + __pid_t pid = fork(); + if (pid == 0) + { + if (execvp("iptables", (char*[]){"iptables", "-A", "INPUT", "-s", ip, "-j", "DROP", nullptr}) != 0) + { + fprintf(stderr, "Error executing iptables: "); + perror(""); + } + } + else if (pid < 0) + { + perror("Fork failed"); + exit(1); + } + + return; + } + } + + free(ip); +} + + +int main(void) +{ + printf("Hello, World!\n"); + print_allowed_ip = getenv("D_PRINT_ALLOWED_IP") != NULL && strcmp(getenv("D_PRINT_ALLOWED_IP"), "1") == 0; + print_allowed_pattern = getenv("D_PRINT_ALLOWED_PATTERN") != NULL && strcmp(getenv("D_PRINT_ALLOWED_PATTERN"), "1") == 0; + print_banned_ip = getenv("D_PRINT_BANNED_IP") != NULL && strcmp(getenv("D_PRINT_BANNED_IP"), "1") == 0; + + MatchRules rules; + rules.patterns = read_lines(PATTERNS_FILE); + rules.allowed_patterns = read_lines(ALLOWED_PATTERNS_FILE); + rules.allowedIps = read_lines(ALLOWED_IPS_FILE); + rules.bannedIpSize = 64; + rules.bannedIpCount = 0; + rules.bannedIps = xmalloc(sizeof(char**) * rules.bannedIpSize); + //rules.bannedIps[0] = ; + + read_lines_cb(ACCESS_LOG_FILE, process_line, &rules); + + for (int i = 0; rules.bannedIps[i] != NULL; i++) + { + free(rules.bannedIps[i]); + } + free(rules.bannedIps); + + for (int i = 0; rules.patterns[i] != NULL; i++) + { + free(rules.patterns[i]); + } + free(rules.patterns); + free(rules.allowedIps); + for (int i = 0; rules.bannedIps[i] != NULL; i++) + { + free(rules.bannedIps[i]); + } + free(rules.bannedIps); + + return 0; +}