# HG changeset patch # User Carl Byington # Date 1450548744 28800 # Node ID 60f59936fabbb3bafdd2853bf5338cf0782346cb # Parent c30df5975c49550250a44c6670e1bcffe0f0cf7e good authentication prevents ip blocking for awhile diff -r c30df5975c49 -r 60f59936fabb ChangeLog --- 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 diff -r c30df5975c49 -r 60f59936fabb NEWS --- 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. diff -r c30df5975c49 -r 60f59936fabb configure.in --- 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]) diff -r c30df5975c49 -r 60f59936fabb src/syslogconfig.cpp --- 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; diff -r c30df5975c49 -r 60f59936fabb src/syslogconfig.h --- 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(); diff -r c30df5975c49 -r 60f59936fabb src/tokenizer.cpp --- 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 diff -r c30df5975c49 -r 60f59936fabb syslog2iptables.conf.top --- 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"; }; }; diff -r c30df5975c49 -r 60f59936fabb syslog2iptables.spec.in --- 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 - 1.16-1 +- good authentication prevents ip blocking for awhile + * Thu Oct 02 2014 Carl Byington - 1.15-1 - add script to build syslog2iptables.conf diff -r c30df5975c49 -r 60f59936fabb xml/syslog2iptables.in --- 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 @@ - 2009-01-25 + 2015-12-18 Carl Byington @@ -61,20 +61,30 @@ or ip address can be used as input to this package. The @PACKAGE@.conf - 5 file specifies the syslog files - to be monitored, and the regular expressions ( + 5 file specifies the syslog + files to be monitored, and the regular expressions ( regex 7 ) 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. + 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. + + 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. + + + 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. 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. + 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. 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. @PACKAGE@ properly detects and handles this case by closing the old file, and reopening the newly created file. + + With the default config file, you can manually unblock an ip + address with logger -p authpriv.info "manual unblock + 1.2.3.4" + @@ -166,7 +181,7 @@ - 2009-01-25 + 2015-12-18 @@ -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 @@ Sample ,.*nrcpts=0,.*\[(.*)\]" { + pattern "sendmail.*AUTH=server, .*\[(.*)\]," { index 1; // zero based - bucket 200; - message "sendmail rejected bounce"; + bucket -5000; + message "sendmail good authentication"; }; }; };]]>