Mercurial > syslog2iptables
changeset 63:60f59936fabb
good authentication prevents ip blocking for awhile
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Sat, 19 Dec 2015 10:12:24 -0800 |
parents | c30df5975c49 |
children | 4b147494fc64 |
files | ChangeLog NEWS configure.in src/syslogconfig.cpp src/syslogconfig.h src/tokenizer.cpp syslog2iptables.conf.top syslog2iptables.spec.in xml/syslog2iptables.in |
diffstat | 9 files changed, 191 insertions(+), 125 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Sat Oct 04 10:21:40 2014 -0700 +++ b/ChangeLog Sat Dec 19 10:12:24 2015 -0800 @@ -1,3 +1,6 @@ +1.16 2015-12-19 + good authentication prevents ip blocking for awhile + 1.15 2014-10-02 add script to build syslog2iptables.conf
--- a/NEWS Sat Oct 04 10:21:40 2014 -0700 +++ b/NEWS Sat Dec 19 10:12:24 2015 -0800 @@ -1,3 +1,4 @@ +1.16 2015-12-19 good authentication prevents ip blocking for awhile 1.15 2014-10-02 add script to build syslog2iptables.conf 1.14 2014-06-10 Add exponential increase in penalty for repeat offenders. 1.13 2009-01-25 Document multiple contexts.
--- a/configure.in Sat Oct 04 10:21:40 2014 -0700 +++ b/configure.in Sat Dec 19 10:12:24 2015 -0800 @@ -1,6 +1,6 @@ AC_PREREQ(2.59) -AC_INIT(syslog2iptables,1.15,carl@five-ten-sg.com) +AC_INIT(syslog2iptables,1.16,carl@five-ten-sg.com) AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_HEADER([config.h])
--- a/src/syslogconfig.cpp Sat Oct 04 10:21:40 2014 -0700 +++ b/src/syslogconfig.cpp Sat Dec 19 10:12:24 2015 -0800 @@ -64,6 +64,7 @@ void IPR::add(int ip, int amount, CONTEXT &con, const char *file_name, int pattern_index, const char *message) { if (con.looking(ip)) { + if (amount > 0) { ip_buckets::iterator j = repeat_offenders.find(ip); int scale = (j == repeat_offenders.end()) ? 1 : (*j).second.count; amount *= scale; @@ -81,7 +82,9 @@ } else { bucket &b = (*i).second; - if (b.count < (INT_MAX-amount)) { + if ((b.count >= 0) && (b.count < 2600000)) { + // good authentication (count<0) prevents blocking + // not much point in blocking for more than a month b.count += amount; if ((!b.blocked) && (con.get_threshold() <= b.count)) { b.blocked = true; @@ -91,6 +94,37 @@ } } } + + else { // amount < 0 + char buf[maxlen]; + in_addr ad; + ad.s_addr = htonl(ip); + snprintf(buf, maxlen, "%s for %s", message, inet_ntoa(ad)); + my_syslog(buf); + + ip_buckets::iterator j = repeat_offenders.find(ip); + if (j != repeat_offenders.end()) { + repeat_offenders.erase(j++); + snprintf(buf, maxlen, "removing %s from repeat offenders", inet_ntoa(ad)); + my_syslog(buf); + } + ip_buckets::iterator i = violations.find(ip); + if (i == violations.end()) { + bucket b; + b.count = amount; + b.blocked = false; + violations[ip] = b; + } + else { + bucket &b = (*i).second; + b.count = amount; + if (b.blocked) { + update(ip, false, 0, NULL, 0, NULL); + changed(con, ip, false); + } + } + } + } } @@ -98,6 +132,14 @@ for (ip_buckets::iterator i=violations.begin(); i!=violations.end(); ) { int ip = (*i).first; bucket &b = (*i).second; + if (b.count < 0) { + if (b.count >= -amount) violations.erase(i++); + else { + b.count += amount; + i++; + } + } + else { if (b.count <= amount) { if (b.blocked) { update(ip, false, 0, NULL, 0, NULL); @@ -110,6 +152,7 @@ i++; } } + } daily_timer -= amount; if (daily_timer < 0) { daily_timer = 86400;
--- a/src/syslogconfig.h Sat Oct 04 10:21:40 2014 -0700 +++ b/src/syslogconfig.h Sat Dec 19 10:12:24 2015 -0800 @@ -21,7 +21,8 @@ const char * pattern; // owned by the string table regex_t re; int index; // zero based substring of the regex match that contains the ip address or hostname - int amount; // count to add to the ip address leaky bucket + int amount; // if positive, count to add to the ip address leaky bucket; + // if negative count to set into the ip address leaky bucket const char * message; // for logging, owned by the string table public: ~PATTERN();
--- a/src/tokenizer.cpp Sat Oct 04 10:21:40 2014 -0700 +++ b/src/tokenizer.cpp Sat Dec 19 10:12:24 2015 -0800 @@ -78,7 +78,7 @@ { s_single, s_term, s_string, s_single, s_eol, }, // 0x2A * { s_single, s_token, s_string, s_single, s_eol, }, // 0x2B + { s_single, s_term, s_string, s_single, s_eol, }, // 0x2C , - { s_single, s_token, s_string, s_single, s_eol, }, // 0x2D - + { s_token, s_token, s_string, s_token, s_eol, }, // 0x2D - // like digits { s_single, s_token, s_string, s_single, s_eol, }, // 0x2E . { s_slash, s_term, s_string, s_slash, s_eol, }, // 0x2F / { s_token, s_token, s_string, s_token, s_eol, }, // 0x30 0
--- a/syslog2iptables.conf.top Sat Oct 04 10:21:40 2014 -0700 +++ b/syslog2iptables.conf.top Sat Dec 19 10:12:24 2015 -0800 @@ -9,6 +9,11 @@ }; file "/var/log/secure" { + pattern "manual unblock (.*)" { + index 1; // zero based + bucket -5000; + message "manual unblock"; + }; pattern "sshd.*Failed password .* from ::ffff:(.*) port" { index 1; // zero based bucket 400; @@ -46,12 +51,12 @@ }; pattern "dovecot.* authentication failure; .* rhost=::ffff:(.*) " { index 1; // zero based - bucket 400; + bucket 100; message "dovecot failed password"; }; pattern "dovecot.* authentication failure; .* rhost=(.*) " { index 1; // zero based - bucket 400; + bucket 100; message "dovecot failed password"; }; }; @@ -59,7 +64,7 @@ file "/var/log/messages" { pattern "dovecot.* authentication failure; .* rhost=(.*) " { index 1; // zero based - bucket 400; + bucket 100; message "dovecot failed password"; }; pattern "kernel.*local-net-to.*SRC=(.*) DST=.*DPT=" { @@ -75,19 +80,14 @@ }; file "/var/log/maillog" { - pattern "\]: .* \[(.*)\] did not issue MAIL" { - index 1; // zero based - bucket 200; - message "sendmail banner probe"; - }; pattern "lost input channel from.* \[(.*)\] .* after (mail|rcpt|auth)" { index 1; // zero based - bucket 200; + bucket 100; message "sendmail spammer dropping connection"; }; - pattern " \[(.*)\]: possible SMTP attack" { + pattern " \[(.*)\].* possible SMTP attack" { index 1; // zero based - bucket 600; + bucket 100; message "sendmail authentication attack"; }; pattern "rejecting commands from.* \[(.*)\] due to pre-greeting traffic" { @@ -97,17 +97,22 @@ }; pattern "authentication failure: checkpass failed,.*\[(.*)\]" { index 1; // zero based - bucket 600; - message "sendmail authentication attack"; + bucket 100; + message "sendmail authentication failed"; }; pattern "dovecot.*Aborted login.*rip=(.*)," { index 1; // zero based bucket 100; message "dovecot failed password"; }; - pattern "dovecot: pop3-login: Disconnected: Shutting down.*rip=(.*)," { + pattern "dovecot.*Login: .* rip=(.*)," { index 1; // zero based - bucket 100; - message "dovecot failed password"; + bucket -5000; + message "dovecot good authentication"; + }; + pattern "sendmail.*AUTH=server, .*\[(.*)\]," { + index 1; // zero based + bucket -5000; + message "sendmail good authentication"; }; };
--- a/syslog2iptables.spec.in Sat Oct 04 10:21:40 2014 -0700 +++ b/syslog2iptables.spec.in Sat Dec 19 10:12:24 2015 -0800 @@ -72,6 +72,9 @@ %changelog +* Sat Dec 19 2015 Carl Byington <carl@five-ten-sg.com> - 1.16-1 +- good authentication prevents ip blocking for awhile + * Thu Oct 02 2014 Carl Byington <carl@five-ten-sg.com> - 1.15-1 - add script to build syslog2iptables.conf
--- a/xml/syslog2iptables.in Sat Oct 04 10:21:40 2014 -0700 +++ b/xml/syslog2iptables.in Sat Dec 19 10:12:24 2015 -0800 @@ -19,7 +19,7 @@ <refentry id="@PACKAGE@.1"> <refentryinfo> - <date>2009-01-25</date> + <date>2015-12-18</date> <author> <firstname>Carl</firstname> <surname>Byington</surname> @@ -61,20 +61,30 @@ or ip address can be used as input to this package.</para> <para>The <citerefentry> <refentrytitle>@PACKAGE@.conf</refentrytitle> - <manvolnum>5</manvolnum> </citerefentry> file specifies the syslog files - to be monitored, and the regular expressions (<citerefentry> + <manvolnum>5</manvolnum> </citerefentry> file specifies the syslog + files to be monitored, and the regular expressions (<citerefentry> <refentrytitle>regex</refentrytitle> <manvolnum>7</manvolnum> </citerefentry>) to be applied to new lines in those files. Each - regular expression needs an index to specify the matching substring that - contains either an ip address or host name, and a bucket count which is - added to the leaky bucket for that ip address when a matching line is - read from that syslog file.</para> + regular expression needs an INDEX to specify the matching substring + that contains either an ip address or host name, and a DELTA which is + used to modify the leaky bucket count for that ip address when a + matching line is read from that syslog file. </para> + + <para>If the DELTA is negative, the leaky bucket count is set to that + DELTA value, any existing blocking for that ip address is removed, and + new blocking is prevented until that bucket leaks upward to zero. + </para> + + <para>If the DELTA is positive and the current leaky bucket count is + not negative, that DELTA value is added to the leaky bucket count for + that ip address. Once the bucket contains more than a configurable + THRESHOLD number of tokens, that ip address is added to the INPUT + chain with a DROP target.</para> <para>Each ip address has an associated leaky bucket, which leaks one - token per second. Once the bucket contains more than a configurable - threshold number of tokens, that ip address is added to the INPUT chain - with a DROP target. When the bucket is drained to zero, that ip address - is removed from the INPUT chain.</para> + token per second so the count moves toward zero. When the bucket is + drained to zero, that ip address is removed from the INPUT + chain.</para> <para>The discussion has focused on syslog files, but any ascii text file can be used, so long as some other process appends lines to that @@ -85,6 +95,11 @@ via logrotate. <command>@PACKAGE@</command> properly detects and handles this case by closing the old file, and reopening the newly created file.</para> + + <para>With the default config file, you can manually unblock an ip + address with <command>logger -p authpriv.info "manual unblock + 1.2.3.4"</command> </para> + </refsect1> <refsect1 id='options.1'> @@ -166,7 +181,7 @@ <refentry id="@PACKAGE@.conf.5"> <refentryinfo> - <date>2009-01-25</date> + <date>2015-12-18</date> </refentryinfo> <refmeta> @@ -205,8 +220,8 @@ IG-SINGLE := IP-ADDRESS "/" CIDR-BITS FILE := "file" FILENAME "{" PATTERN+ "}" PATTERN := "pattern" REGULAR-EXPRESSION "{" {INDEX | BUCKET | MESSAGE}+ "};" -INDEX := "index" REGEX-INTEGER-VALUE ";" -BUCKET := "bucket" BUCKET-ADD-INTEGER-VALUE ";" +INDEX := "index" REGEX-INTEGER ";" +DELTA := "bucket" BUCKET-DELTA-INTEGER ";" MESSAGE := "message" REASON ";" REASON := string to appear in syslog messages IPT-CMD := string containing exactly one %s replacement token for @@ -216,26 +231,6 @@ <refsect1 id='sample.5'> <title>Sample</title> <literallayout class="monospaced"><![CDATA[ -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.*denied" { - index 1; // zero based - bucket 400; - message "DNS attack"; - }; - }; -}; - - context general { threshold 550; @@ -247,6 +242,11 @@ }; file "/var/log/secure" { + pattern "manual unblock (.*)" { + index 1; // zero based + bucket -5000; + message "manual unblock"; + }; pattern "sshd.*Failed password .* from ::ffff:(.*) port" { index 1; // zero based bucket 400; @@ -257,86 +257,96 @@ 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"; }; - - file "/var/log/messages" { - pattern "ipop3d.* Login failed .* \[(.*)\]" { + pattern "vsftpd.* authentication failure; .* rhost=(.*) " { index 1; // zero based bucket 400; - message "pop3 failed password"; + message "ftp failed password"; + }; + pattern "dovecot.* authentication failure; .* rhost=::ffff:(.*) " { + index 1; // zero based + bucket 100; + message "dovecot failed password"; + }; + pattern "dovecot.* authentication failure; .* rhost=(.*) " { + index 1; // zero based + bucket 100; + message "dovecot failed password"; }; }; - file "/var/log/httpd/access_log" { - // of course you cannot use this if you actually use cgi-bin directories - pattern "(.*) - - .* /cgi-bin" { + file "/var/log/messages" { + pattern "dovecot.* authentication failure; .* rhost=(.*) " { index 1; // zero based - bucket 400; - message "apache cgi-bin reference"; + bucket 100; + message "dovecot failed password"; }; - // or if you actually have an index2.php script - pattern "(.*) - - .*/index2.php" { + pattern "kernel.*local-net-to.*SRC=(.*) DST=.*DPT=" { index 1; // zero based bucket 400; - message "apache index2.php reference"; + message "kernel firewall blocked packet"; }; - // or if you have a main.php script - pattern "(.*) - - .*/main.php" { + pattern "kernel.*outside-net-from.*SRC=(.*) DST=.*DPT=" { index 1; // zero based bucket 400; - message "apache main.php reference"; - }; - pattern "(.*) - - .*/awstats.pl" { - index 1; // zero based - bucket 400; - message "apache awstats.pl reference"; - }; - pattern "(.*) - - .*/adxmlrpc" { - index 1; // zero based - bucket 400; - message "apache adxmlrpc reference"; + message "kernel firewall blocked packet"; }; }; file "/var/log/maillog" { pattern "lost input channel from .* \[(.*)\] .* after (mail|rcpt|auth)" { index 1; // zero based - bucket 200; + bucket 100; message "sendmail spammer dropping connection"; }; - pattern " \[(.*)\]: possible SMTP attack" { + pattern " \[(.*)\].* possible SMTP attack" { index 1; // zero based - bucket 600; + bucket 100; message "sendmail authentication attack"; }; pattern "rejecting commands from .* \[(.*)\] due to pre-greeting traffic" { index 1; // zero based - bucket 200; + bucket 1800; message "sendmail pre-greeting"; }; + pattern "authentication failure: checkpass failed, .*\[(.*)\]" { + index 1; // zero based + bucket 100; + message "sendmail authentication failed"; + }; pattern "dovecot.*Aborted login.*rip=(.*)," { index 1; // zero based bucket 100; message "dovecot failed password"; }; - pattern "dovecot: pop3-login: Disconnected: Shutting down.*rip=(.*)," { + pattern "dovecot.*Login: .* rip=(.*)," { index 1; // zero based - bucket 100; - message "dovecot failed password"; + bucket -5000; + message "dovecot good authentication"; }; - - // make sure your upstream MX servers are listed in the - // ignore block above, otherwise you will kill them off - // when they try to forward such mail to you. - pattern "sendmail.*from=<>,.*nrcpts=0,.*\[(.*)\]" { + pattern "sendmail.*AUTH=server, .*\[(.*)\]," { index 1; // zero based - bucket 200; - message "sendmail rejected bounce"; + bucket -5000; + message "sendmail good authentication"; }; }; };]]></literallayout>