diff --git a/main.c b/main.c
index 487f700..d94c50d 100644
--- a/main.c
+++ b/main.c
@@ -1,3 +1,4 @@
+#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -13,6 +14,32 @@
// #define ACCESS_LOG_FILE "access.log.1"
#define ACCESS_LOG_FILE "/var/log/nginx/access.log"
+#define print_bool_opt(x) \
+ if (x) { \
+ fprintf(stderr, #x ": true\n"); \
+ } else { \
+ fprintf(stderr, #x ": false\n"); \
+ }
+#define print_str_opt(x) \
+ if (x != nullptr) { \
+ fprintf(stderr, #x ": %s\n", x); \
+ } else { \
+ fprintf(stderr, #x ": null\n"); \
+ }
+
+#define ansi(x) "\033[" x
+#define ansi_mod(x) "\033[" x "m"
+
+#define ANSI_CLEAR_LINE ansi("2K")
+#define ANSI_BLINK ansi_mod("5")
+#define ANSI_RESET ansi_mod("0")
+
+#define ANSI_COLOR(r,g,b) ansi_mod("38;2;" #r ";" #g ";" #b)
+#define ANSI_HSL(h,s,l) ansi_mod("38;2;" \
+ (int)((l < 50 ? l + s : l - s) * (1 + h / 360.0) / 100.0 * 255) ";" \
+ (int)((l < 50 ? l + s : l - s) * (1 - h / 360.0) / 100.0 * 255) ";" \
+ (int)(l * 255 / 100))
+
typedef struct
{
char** patterns;
@@ -20,6 +47,7 @@ typedef struct
char** allowed_ips;
// size_t allowedIpCount;
char** banned_ips;
+ int* banned_ip_hits;
size_t banned_ip_count;
size_t banned_ip_size;
} MatchRules;
@@ -32,6 +60,10 @@ bool print_bans = true;
bool print_only = false;
bool print_progress = true;
+bool check_allowed_ip = true;
+bool check_allowed_pattern = true;
+bool check_already_banned_ip = true;
+
bool dump_patterns = false;
char* allowed_patterns_path = ALLOWED_PATTERNS_FILE;
@@ -50,6 +82,24 @@ void* xmalloc(size_t size)
return ptr;
}
+char* str_to_hex(const char* str)
+{
+ const size_t len = strlen(str);
+ char* hex = xmalloc(len * 2 + 3);
+ for (size_t i = 0; i < len; i++)
+ {
+ sprintf(hex + i * 3, "%02x ", (unsigned char)str[i]);
+ }
+ sprintf(hex + len * 3, "00 ");
+ hex[len * 3 + 2] = '\0';
+ return hex;
+}
+
+bool streq(const char* a, const char* b)
+{
+ return a == b || (a != nullptr && b != nullptr && strcmp(a, b) == 0);
+}
+
void signal_handler(int signal_number)
{
int wait_status;
@@ -193,7 +243,7 @@ char** read_lines(const char* filename)
char** grow_string_array(char** array, size_t newSize)
{
- printf("Growing charptr array to %zu\n", newSize);
+ fprintf(stderr, ANSI_CLEAR_LINE ANSI_BLINK "Growing charptr array to %zu" ANSI_RESET "\n", newSize);
char** newArray = realloc(array, sizeof(char*) * newSize);
if (newArray == NULL)
{
@@ -203,9 +253,20 @@ char** grow_string_array(char** array, size_t newSize)
return newArray;
}
-void ban_ip(char* ip)
+int* grow_int_array(int* array, size_t newSize)
{
+ fprintf(stderr, ANSI_CLEAR_LINE ANSI_BLINK "Growing int array to %zu" ANSI_RESET "\n", newSize);
+ int* newArray = realloc(array, sizeof(int) * newSize);
+ if (newArray == NULL)
+ {
+ fprintf(stderr, "Memory allocation failed\n");
+ exit(EXIT_FAILURE);
+ }
+ return newArray;
+}
+void ban_ip(char* ip)
+{
}
void process_line(char* line, void* cbData)
@@ -229,37 +290,58 @@ void process_line(char* line, void* cbData)
// printf("meow %s\n", ip);
- for (int j = 0; rules->allowed_ips[j] != NULL; j++)
- {
- if (strstr(ip, rules->allowed_ips[j]) == ip)
+ if (check_allowed_ip)
+ for (int j = 0; rules->allowed_ips[j] != NULL; j++)
{
- if (print_allowed_ip)
- printf("Allowed IP: \"%s\" (~%s): %s\n", ip, rules->allowed_ips[j], line);
- free(ip);
- return;
+ if (streq(ip, rules->allowed_ips[j]))
+ {
+ if (print_allowed_ip)
+ printf("Allowed IP: \"%s\" (~%s): %s\n", ip, rules->allowed_ips[j], line);
+ free(ip);
+ return;
+ }
}
- }
- for (size_t j = 0; j < rules->banned_ip_count; j++)
- {
- if (strstr(ip, rules->banned_ips[j]) == ip)
+ if (check_already_banned_ip)
+ for (size_t j = 0; j < rules->banned_ip_count; j++)
{
- if (print_already_banned_ip)
- printf("Banned IP: \"%s\": %s\n", rules->banned_ips[j], line);
- free(ip);
- return;
+ if (strlen(rules->banned_ips[j]) < 5)
+ {
+ for (size_t k = 0; k < rules->banned_ip_count; k++)
+ {
+ printf("rules->banned_ips[%lu] = \"%s\" (#%s)\n", k, rules->banned_ips[k], str_to_hex(rules->banned_ips[k]));
+ }
+ printf("ASSERT: Broken rule #%lu: \"%s\" (#%s)\n", j, rules->banned_ips[j], str_to_hex(rules->banned_ips[j]));
+ abort();
+ }
+
+ if (streq(ip, rules->banned_ips[j]))
+ {
+ if (print_already_banned_ip)
+ printf("Banned IP: \"%s\" (rule %lu: %s): %s\n", ip, j, rules->banned_ips[j], line);
+
+ if (strlen(ip) != strlen(rules->banned_ips[j]) || strcmp(ip, rules->banned_ips[j]) != 0)
+ {
+ fprintf(stderr, "ASSERT: IP address length did not match! #%lu: \"%s\" (#%s) != \"%s\" (#%s)\n", j, rules->banned_ips[j], str_to_hex(rules->banned_ips[j]), ip,
+ str_to_hex(ip));
+ abort();
+ }
+
+ free(ip);
+ return;
+ }
}
- }
- for (int i = 0; rules->allowed_patterns[i] != NULL; i++)
- {
- if (strstr(line, rules->allowed_patterns[i]) != NULL)
+ if (check_allowed_pattern)
+ for (int i = 0; rules->allowed_patterns[i] != NULL; i++)
{
- if (print_allowed_pattern)
- printf("%15s matched allowed pattern \"%s\": %s\n", ip, rules->allowed_patterns[i], line);
- return;
+ 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++)
{
@@ -269,11 +351,14 @@ void process_line(char* line, void* cbData)
{
rules->banned_ip_size *= 2;
rules->banned_ips = grow_string_array(rules->banned_ips, rules->banned_ip_size);
+ rules->banned_ip_hits = grow_int_array(rules->banned_ip_hits, rules->banned_ip_size);
}
- rules->banned_ips[rules->banned_ip_count] = ip;
rules->banned_ips[rules->banned_ip_count][strcspn(rules->banned_ips[rules->banned_ip_count], "\n")] = 0;
rules->banned_ips[rules->banned_ip_count + 1] = nullptr;
+ rules->banned_ips[rules->banned_ip_count] = ip;
+ rules->banned_ip_hits[rules->banned_ip_count]++;
+ fprintf(stderr, "DBG: %s -> %d hits\n", rules->banned_ips[rules->banned_ip_count], rules->banned_ip_hits[rules->banned_ip_count]);
rules->banned_ip_count++;
if (print_bans)
printf("[Bans=%6lu] %15s matched pattern %4d (\"%s\"): %s\n", rules->banned_ip_count, ip, i, rules->patterns[i], line);
@@ -342,6 +427,12 @@ int main(int argc, char* argv[])
print_only = strstr(argv[i], "=false") == NULL;
else if (strstr(argv[i], "--print-progress") != NULL)
print_progress = strstr(argv[i], "=false") == NULL;
+ else if (strstr(argv[i], "--check-allowed-ip") != NULL)
+ check_allowed_ip = strstr(argv[i], "=false") == NULL;
+ else if (strstr(argv[i], "--check-allowed-pattern") != NULL)
+ check_allowed_pattern = strstr(argv[i], "=false") == NULL;
+ else if (strstr(argv[i], "--check-already-banned-ip") != NULL)
+ check_already_banned_ip = strstr(argv[i], "=false") == NULL;
else if (strstr(argv[i], "--dump-patterns") != NULL)
dump_patterns = true;
else if (strcmp(argv[i], "--debug") == 0)
@@ -359,7 +450,7 @@ int main(int argc, char* argv[])
printf(" --allowed-ips <path> Path to the allowed IPs file (default: %s)\n", ALLOWED_IPS_FILE);
printf(" --allowed-patterns <path> Path to the allowed patterns file (default: %s)\n", ALLOWED_PATTERNS_FILE);
printf(" --patterns <path> Path to the patterns file (default: %s)\n", PATTERNS_FILE);
- printf(" --access-log <path> Path to the access log file (default: %s)\n", ACCESS_LOG_FILE);
+ printf(" --access-log <path|stdin|-> Path to the access log file (default: %s)\n", ACCESS_LOG_FILE);
printf(" --print-allowed-ip[=false] Print allowed IPs (default: %s)\n", print_allowed_ip ? "true" : "false");
printf(" --print-allowed-pattern[=false] Print allowed patterns (default: %s)\n", print_allowed_pattern ? "true" : "false");
printf(" --print-already-banned-ip[=false] Print already banned IPs (default: %s)\n", print_already_banned_ip ? "true" : "false");
@@ -368,6 +459,9 @@ int main(int argc, char* argv[])
printf(" --print-only[=false] Print only the lines that match the rules (default: %s)\n", print_only ? "true" : "false");
printf(" --print-progress[=false] Print progress while reading file (default: %s)\n", print_progress ? "true" : "false");
printf(" --debug Enable debug mode (prints all information)\n");
+ printf(" --check-allowed-ip[=false] Check allowed IPs (default: %s)\n", check_allowed_ip ? "true" : "false");
+ printf(" --check-allowed-pattern[=false] Check allowed patterns (default: %s)\n", check_allowed_pattern ? "true" : "false");
+ printf(" --check-already-banned-ip[=false] Check already banned IPs (default: %s)\n", check_already_banned_ip ? "true" : "false");
printf(" --dump-patterns Dump pattern table and exit\n");
return 0;
}
@@ -383,16 +477,24 @@ int main(int argc, char* argv[])
access_log_path = "/dev/stdin";
}
- fprintf(stderr, "allowed_patterns_path: %s\n", allowed_patterns_path);
- fprintf(stderr, "allowed_ips_path: %s\n", allowed_ips_path);
- fprintf(stderr, "patterns_path: %s\n", patterns_path);
- fprintf(stderr, "access_log_path: %s\n", access_log_path);
+ print_bool_opt(print_allowed_ip);
+ print_bool_opt(print_allowed_pattern);
+ print_bool_opt(print_already_banned_ip);
+ print_bool_opt(print_indeterminate);
+ print_bool_opt(print_bans);
+ print_bool_opt(print_only);
+ print_bool_opt(print_progress);
- fprintf(stderr, "print_allowed_ip: %hhd\n", print_allowed_ip);
- fprintf(stderr, "print_allowed_pattern: %hhd\n", print_allowed_pattern);
- fprintf(stderr, "print_already_banned_ip: %hhd\n", print_already_banned_ip);
- fprintf(stderr, "print_indeterminate: %hhd\n", print_indeterminate);
- fprintf(stderr, "print_bans: %hhd\n", print_bans);
+ print_bool_opt(check_allowed_ip);
+ print_bool_opt(check_allowed_pattern);
+ print_bool_opt(check_already_banned_ip);
+
+ print_bool_opt(dump_patterns);
+
+ print_str_opt(allowed_patterns_path);
+ print_str_opt(allowed_ips_path);
+ print_str_opt(patterns_path);
+ print_str_opt(access_log_path);
MatchRules rules;
rules.patterns = read_lines(patterns_path);
@@ -401,6 +503,7 @@ int main(int argc, char* argv[])
rules.banned_ip_size = 8;
rules.banned_ip_count = 0;
rules.banned_ips = xmalloc(sizeof(char**) * rules.banned_ip_size);
+ rules.banned_ip_hits = xmalloc(sizeof(int*) * rules.banned_ip_size);
//rules.bannedIps[0] = ;
if (dump_patterns)
@@ -425,10 +528,16 @@ int main(int argc, char* argv[])
fprintf(stderr, "Banned %lu IPs:\n", rules.banned_ip_count);
- for (int i = 0; rules.banned_ips[i] != NULL; i++)
+ for (int i = 0; i < rules.banned_ip_count; i++)
{
+ printf("[BAN %4d] %s: %d hits\n", i, rules.banned_ips[i], rules.banned_ip_hits[i * sizeof(int)]);
free(rules.banned_ips[i]);
}
+ // for (int i = 0; rules.banned_ips[i] != NULL; i++)
+ // {
+ // printf("[BANNED IP %4d] %s\n", i, rules.banned_ips[i]);
+ // free(rules.banned_ips[i]);
+ // }
free(rules.banned_ips);
for (int i = 0; rules.patterns[i] != NULL; i++)
|