# HG changeset patch # User Carl Byington # Date 1402415333 25200 # Node ID b45dddebe8fc023232b7abbe07c9e3b876603ad7 # Parent c95acc20f7ed9f0b59c953560aa721ec5e47361d Add exponential increase in penalty for repeat offenders diff -r c95acc20f7ed -r b45dddebe8fc ChangeLog --- a/ChangeLog Wed Aug 17 10:16:17 2011 -0700 +++ b/ChangeLog Tue Jun 10 08:48:53 2014 -0700 @@ -1,3 +1,6 @@ +1.14 2014-06-10 + Add exponential increase in penalty for repeat offenders. + 1.13 2011-08-17 Switch to auto requires for rpm builds. diff -r c95acc20f7ed -r b45dddebe8fc NEWS --- a/NEWS Wed Aug 17 10:16:17 2011 -0700 +++ b/NEWS Tue Jun 10 08:48:53 2014 -0700 @@ -1,3 +1,4 @@ +1.14 2014-06-10 Add exponential increase in penalty for repeat offenders. 1.13 2009-01-25 Document multiple contexts. 1.12 2009-01-24 Allow multiple contexts with independent add/remove commands. 1.11 2008-05-29 Fixes to compile on Fedora 9 and for const correctness. diff -r c95acc20f7ed -r b45dddebe8fc configure.in --- a/configure.in Wed Aug 17 10:16:17 2011 -0700 +++ b/configure.in Tue Jun 10 08:48:53 2014 -0700 @@ -1,6 +1,6 @@ AC_PREREQ(2.59) -AC_INIT(syslog2iptables,1.13,carl@five-ten-sg.com) +AC_INIT(syslog2iptables,1.14,carl@five-ten-sg.com) AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_HEADER([config.h]) diff -r c95acc20f7ed -r b45dddebe8fc src/syslogconfig.cpp --- a/src/syslogconfig.cpp Wed Aug 17 10:16:17 2011 -0700 +++ b/src/syslogconfig.cpp Tue Jun 10 08:48:53 2014 -0700 @@ -32,6 +32,7 @@ string_set all_strings;// owns all the strings, only modified by the config loader thread recorder_map recorders; // all the recorders are named const int maxlen = 1000; // used for snprintf buffers +const int scale_max = 500000; //////////////////////////////////////////////// @@ -39,6 +40,7 @@ IPR::IPR() { reference_count = 0; + daily_timer = 86400; } IPR* IPR::find(const char* name) { @@ -62,26 +64,28 @@ void IPR::add(int ip, int amount, CONTEXT &con, const char *file_name, int pattern_index, const char *message) { if (con.looking(ip)) { + ip_buckets::iterator j = repeat_offenders.find(ip); + int scale = (j == repeat_offenders.end()) ? 1 : (*j).second.count; + amount *= scale; + ip_buckets::iterator i = violations.find(ip); if (i == violations.end()) { bucket b; b.count = amount; - b.latch = (con.get_threshold() <= b.count); + b.blocked = (con.get_threshold() <= b.count); violations[ip] = b; - if (b.latch) { - update(ip, true, file_name, pattern_index, message); + if (b.blocked) { + update(ip, true, scale, file_name, pattern_index, message); changed(con, ip, true); } } else { bucket &b = (*i).second; if (b.count < (INT_MAX-amount)) { - int t = con.get_threshold(); - int c = b.count; b.count += amount; - if ((!b.latch) && (c < t) && (t <= b.count)) { - b.latch = true; - update(ip, true, file_name, pattern_index, message); + if ((!b.blocked) && (con.get_threshold() <= b.count)) { + b.blocked = true; + update(ip, true, scale, file_name, pattern_index, message); changed(con, ip, true); } } @@ -95,8 +99,8 @@ int ip = (*i).first; bucket &b = (*i).second; if (b.count <= amount) { - if (b.latch) { - update(ip, false, NULL, 0, NULL); + if (b.blocked) { + update(ip, false, 0, NULL, 0, NULL); changed(con, ip, false); } violations.erase(i++); @@ -106,6 +110,26 @@ i++; } } + daily_timer -= amount; + if (daily_timer < 0) { + daily_timer = 86400; + for (ip_buckets::iterator j=repeat_offenders.begin(); j!=repeat_offenders.end(); ) { + int ip = (*j).first; + bucket &b = (*j).second; + b.count = b.count * 2 / 3; + if (b.count <= 2) { + repeat_offenders.erase(j++); + char buf[maxlen]; + in_addr ad; + ad.s_addr = htonl(ip); + snprintf(buf, maxlen, "removing %s from repeat offenders", inet_ntoa(ad)); + my_syslog(buf); + } + else { + j++; + } + } + } } @@ -116,8 +140,8 @@ for (ip_buckets::iterator i=violations.begin(); i!=violations.end(); i++) { int ip = (*i).first; bucket &b = (*i).second; - if (b.latch) { - update(ip, false, NULL, 0, NULL); + if (b.blocked) { + update(ip, false, 0, NULL, 0, NULL); changed(con, ip, false); } } @@ -125,14 +149,25 @@ } -void IPR::update(int ip, bool added, const char *file_name, int pattern_index, const char *message) { +void IPR::update(int ip, bool added, int scale, const char *file_name, int pattern_index, const char *message) { if (debug_syslog > 2) { char buf[maxlen]; in_addr ad; ad.s_addr = htonl(ip); if (added) { - if (message) snprintf(buf, maxlen, "dropping traffic from/to %s based on %s in %s", inet_ntoa(ad), message, file_name); + if (message) snprintf(buf, maxlen, "dropping traffic from/to %s based on %s in %s, scale %d", inet_ntoa(ad), message, file_name, scale); else snprintf(buf, maxlen, "dropping traffic from/to %s based on pattern match %d in %s", inet_ntoa(ad), pattern_index, file_name); + ip_buckets::iterator j = repeat_offenders.find(ip); + if (j == repeat_offenders.end()) { + bucket b; + b.count = 2; + b.blocked = true; // unused + repeat_offenders[ip] = b; + } + else { + bucket &b = (*j).second; + if (b.count < scale_max) b.count = b.count * 3 / 2; + } } else snprintf(buf, maxlen, "allowing traffic from/to %s", inet_ntoa(ad)); my_syslog(buf); diff -r c95acc20f7ed -r b45dddebe8fc src/syslogconfig.h --- a/src/syslogconfig.h Wed Aug 17 10:16:17 2011 -0700 +++ b/src/syslogconfig.h Tue Jun 10 08:48:53 2014 -0700 @@ -40,21 +40,23 @@ struct bucket { int count; - bool latch; // true iff ever count>threshold + bool blocked; // true iff ever count>threshold }; typedef map ip_buckets; class IPR { int reference_count; // number of contexts using this recorder + int daily_timer; // track daily cycle to reduce repeat offenders penalties ip_buckets violations; + ip_buckets repeat_offenders; public: IPR(); int reference(int delta) {reference_count += delta; return reference_count;}; void add(int ip, int amount, CONTEXT &con, const char *file_name, int pattern_index, const char *message); void leak(int amount, CONTEXT &con); void free_all(CONTEXT &con); - void update(int ip, bool added, const char *file_name, int pattern_index, const char *message); + void update(int ip, bool added, int scale, const char *file_name, int pattern_index, const char *message); void changed(CONTEXT &con, int ip, bool added); static IPR* find(const char* name); static void release(const char* name); diff -r c95acc20f7ed -r b45dddebe8fc syslog2iptables.conf --- a/syslog2iptables.conf Wed Aug 17 10:16:17 2011 -0700 +++ b/syslog2iptables.conf Tue Jun 10 08:48:53 2014 -0700 @@ -1,23 +1,3 @@ -context dns { - threshold 1100; - - add_command "/sbin/iptables -I INPUT --protocol udp --destination-port 53 --src %s --jump DROP"; - remove_command "/sbin/iptables -D INPUT --protocol udp --destination-port 53 --src %s --jump DROP"; - - ignore { - 127.0.0.0/8; // localhost - }; - - file "/var/log/messages" { - pattern "named.*client (.*)#.*query.*cache.*'\./NS/IN'.*denied" { - index 1; // zero based - bucket 400; - message "DNS attack"; - }; - }; -}; - - context general { threshold 550; @@ -39,11 +19,26 @@ bucket 400; message "ssh failed password"; }; + pattern "sshd.*authentication failure; .* rhost=(.*) " { + index 1; // zero based + bucket 400; + message "ssh failed password"; + }; + pattern "sshd.*Did not receive identification string from (.*)" { + index 1; // zero based + bucket 400; + message "ssh failed password"; + }; pattern "proftpd.*no such user found from (.*) \[" { index 1; // zero based bucket 400; message "ftp failed password"; }; + pattern "proftpd.* authentication failure; .* rhost=(.*) " { + index 1; // zero based + bucket 400; + message "ftp failed password"; + }; pattern "vsftpd.* authentication failure; .* rhost=(.*) " { index 1; // zero based bucket 400; @@ -98,6 +93,11 @@ bucket 400; message "apache awstats.pl reference"; }; + pattern "(.*) - - .*/xmlrpc" { + index 1; // zero based + bucket 400; + message "apache xmlrpc reference"; + }; pattern "(.*) - - .*/adxmlrpc" { index 1; // zero based bucket 400; @@ -108,11 +108,36 @@ bucket 400; message "apache general.js reference"; }; + pattern "(.*) - - .*/Admin/" { + index 1; // zero based + bucket 400; + message "apache phpMyAdmin reference"; + }; + pattern "(.*) - - .*/MyAdmin/" { + index 1; // zero based + bucket 400; + message "apache phpMyAdmin reference"; + }; pattern "(.*) - - .*/phpMyAdmin/" { index 1; // zero based bucket 400; message "apache phpMyAdmin reference"; }; + pattern "(.*) - - .*/user/soapCaller" { + index 1; // zero based + bucket 400; + message "apache soapCaller reference"; + }; + pattern "(.*) - - .*POST /contact.php" { + index 1; // zero based + bucket 400; + message "apache contact.php post"; + }; + pattern "(.*) - - .*/crossdomain.xml" { + index 1; // zero based + bucket 400; + message "apache crossdomain.xml reference"; + }; pattern "(.*) - - .*/cart/" { index 1; // zero based bucket 400; @@ -143,7 +168,7 @@ }; pattern "rejecting commands from .* \[(.*)\] due to pre-greeting traffic" { index 1; // zero based - bucket 200; + bucket 1800; message "sendmail pre-greeting"; }; pattern "dovecot.*Aborted login.*rip=(.*)," { diff -r c95acc20f7ed -r b45dddebe8fc syslog2iptables.spec.in --- a/syslog2iptables.spec.in Wed Aug 17 10:16:17 2011 -0700 +++ b/syslog2iptables.spec.in Tue Jun 10 08:48:53 2014 -0700 @@ -3,7 +3,7 @@ Summary: Syslog to iptables dynamic firewall Name: @PACKAGE@ Version: @VERSION@ -Release: 2%{?dist} +Release: 1%{?dist} License: GPLv3+ Group: System Environment/Daemons Source: http://www.five-ten-sg.com/%{name}/packages/%{name}-%{version}.tar.gz @@ -67,6 +67,9 @@ %changelog +* Tue Jun 10 2014 Carl Byington - 1.14-1 +- Add exponential increase in penalty for repeat offenders. + * Wed Aug 17 2011 Carl Byington - 1.13-2 - switch to auto requires diff -r c95acc20f7ed -r b45dddebe8fc xml/syslog2iptables.in --- a/xml/syslog2iptables.in Wed Aug 17 10:16:17 2011 -0700 +++ b/xml/syslog2iptables.in Tue Jun 10 08:48:53 2014 -0700 @@ -20,6 +20,13 @@ 2009-01-25 + + Carl + Byington + + 510 Software Group + +