/* * * BlockBadIP - Blocca gli IP degli attaccanti * (C) 2002 by Piergiorgio Ghezzo * * * Questo programma analizza i pacchetti in arrivo sul dispositivo netlink, * si ricava i destinatari e blocca gli indirizzi per il numero di minuti * specificato. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define VERSION "1.0" #define DEFAULT_NETLINK_DEVICE "/dev/netlink" #define DPRINTF(args...) { if (g_debug) fprintf(stderr, ##args); } // Intestazione dei pacchetti che arrivano da netlink struct netlinkhdr { unsigned int len; unsigned int mark; char iface[IFNAMSIZ]; }; // Variabili globali static int g_debug = 0; static int g_log_packets = 0; static int g_minutes = 120; static u_int16_t g_ip_id; // Prototipi delle funzioni static void usage(const char *); static void version(const char *); static int main_loop(int); static u_int16_t ipv4_checksum_final(int); static char *ip_to_char(u_int32_t); int main(int argc, char *argv[]) { int opts; int result; int daemon_mode = 0; int fd; char *netlink_device = DEFAULT_NETLINK_DEVICE; char *pid_file = NULL; FILE *fp; srand(time(NULL)); g_ip_id = rand() & 0xffff; while ((opts = getopt(argc, argv, "hvbdsm:f:p:")) != EOF) { switch (opts) { case 'h': usage(argv[0]); exit(1); case 'v': version(argv[0]); exit(1); case 'b': daemon_mode = 1; break; case 'd': g_debug = 1; DPRINTF("Debugging enabled.\n"); break; case 's': g_log_packets = 1; break; case 'f': netlink_device = optarg; break; case 'm': g_minutes = atoi(optarg); break; case 'p': pid_file = optarg; break; } } DPRINTF("Block bad IPs for %d minutes.\n", g_minutes); DPRINTF("Using netlink device: %s\n", netlink_device); fd = open(netlink_device, O_RDONLY); if (fd < 0) { fprintf(stderr, "Failed to open %s: %s\n", netlink_device, strerror(errno)); exit(1); } DPRINTF("Netlink device opened OK.\n"); if (g_debug == 0) { if (daemon_mode == 1) daemon(0, 0); openlog("pktdeny", LOG_PID, LOG_DAEMON); if (pid_file != NULL) { fp = fopen(pid_file, "w+"); if (fp != NULL) { fprintf(fp, "%d\n", getpid()); fclose(fp); } } } result = main_loop(fd); close(fd); exit(result); } static int main_loop(int nlfd) { int b; char buf[BUFSIZ]; char *source_ip; struct netlinkhdr *nlh = (struct netlinkhdr *) buf; struct iphdr *iph = (struct iphdr *) (buf + sizeof(struct netlinkhdr)); struct tcphdr *tcph; char Comando[250]; int minutes; while ((b = read(nlfd, buf, sizeof(buf))) > 0) { // E' lungo a sufficienza per essere un pacchetto TCP? if (b < sizeof(struct netlinkhdr) + (iph->ihl << 2) + sizeof(struct tcphdr)) { DPRINTF("Short packet, ignoring.\n"); continue; } source_ip = ip_to_char(iph->saddr); DPRINTF("Netlink: iface %s, source %s, len %d, mark 0x%.8x\n", nlh->iface, source_ip, nlh->len, nlh->mark); if (iph->protocol == IPPROTO_TCP) { tcph = (struct tcphdr *) (buf + sizeof(struct netlinkhdr) + (iph->ihl << 2)); DPRINTF("sport = %d\n", ntohs(tcph->source)); DPRINTF("dport = %d\n", ntohs(tcph->dest)); } // Blocca l'IP sorgente sprintf (Comando, "/sbin/iptables -I INPUT -s %s -j DROP", source_ip); DPRINTF("%s\n", Comando); system (Comando); sprintf (Comando, "echo \"/sbin/iptables -D INPUT -s %s -j DROP\" | at now+%dminutes >/dev/null 2>/dev/null", source_ip, g_minutes); DPRINTF("%s\n", Comando); system (Comando); // Scrivo il log di sistema se richiesto if (g_log_packets) syslog(LOG_NOTICE, "%s: address %s blocked for %d minutes\n", nlh->iface, source_ip, g_minutes); free(source_ip); } if (b < 0) return 1; return 0; } static char *ip_to_char(u_int32_t ip) { char *str; str = (char *) malloc(16); if (str == NULL) return NULL; ip = ntohl(ip); snprintf(str, 16, "%d.%d.%d.%d", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); return str; } static void usage(const char *name) { char *tmp; if ((tmp = strrchr(name, '/')) != NULL) name = tmp + 1; fprintf(stderr, "\nUsage: %s [-hvbds] [-m minutes] [-f device] [-p pidfile]\n" "\n" "\t-h\t\tThis help.\n" "\t-v\t\tShow version.\n" "\t-b\t\tForce daemon into the background.\n" "\t-d\t\tTurn on debugging mode.\n" "\t-s\t\tSyslog blocked adresses.\n" "\t-m minutes\tBlock bad IPs for specified minutes instead of %d.\n" "\t-f device\tUse specifed device instead of %s.\n" "\t-p pidfile\tWrite the daemon PID to this file.\n\n", name, g_minutes, DEFAULT_NETLINK_DEVICE); } static void version(const char *name) { char *tmp; if ((tmp = strrchr(name, '/')) != NULL) name = tmp + 1; fprintf(stderr, "\n%s version %s\n" "Copyright © 2002 by Piergiorgio Ghezzo\n" "Build date: %s %s\n\n", name, VERSION, __DATE__, __TIME__); }