diff --git a/config/action.d/complain.conf b/config/action.d/complain.conf index 3f97d188..1f74d635 100644 --- a/config/action.d/complain.conf +++ b/config/action.d/complain.conf @@ -34,6 +34,9 @@ before = helpers-common.conf [Definition] +# Used in test cases for coverage internal transformations +debug = 0 + # bypass ban/unban for restored tickets norestored = 1 @@ -61,9 +64,10 @@ actioncheck = # Tags: See jail.conf(5) man page # Values: CMD # -actionban = oifs=${IFS}; - REV_IP=$(printf %%s . | tac -s.) - ADDRESSES=$(dig +short -t txt -q ${REV_IP}abuse-contacts.abusix.org | tr -d '"') +actionban = oifs=${IFS}; + RESOLVER_ADDR="%(addr_resolver)s" + if [ "" -gt 0 ]; then echo "try to resolve $RESOLVER_ADDR"; fi + ADDRESSES=$(dig +short -t txt -q $RESOLVER_ADDR | tr -d '"') IFS=,; ADDRESSES=$(echo $ADDRESSES) IFS=${oifs} IP= @@ -82,7 +86,12 @@ actionban = oifs=${IFS}; # actionunban = -[Init] +# Server as resolver used in dig command +# +addr_resolver = abuse-contacts.abusix.org + +# Default message used for abuse content +# message = Dear Sir/Madam,\n\nWe have detected abuse from the IP address $IP, which according to a abusix.com is on your network. We would appreciate if you would investigate and take action as appropriate.\n\nLog lines are given below, but please ask if you require any further information.\n\n(If you are not the correct person to contact about this please accept our apologies - your e-mail address was extracted from the whois record by an automated process.)\n\n This mail was generated by Fail2Ban.\nThe recipient address of this report was provided by the Abuse Contact DB by abusix.com. abusix.com does not maintain the content of the database. All information which we pass out, derives from the RIR databases and is processed for ease of use. If you want to change or report non working abuse contacts please contact the appropriate RIR. If you have any further question, contact abusix.com directly via email (info@abusix.com). Information about the Abuse Contact Database can be found here: https://abusix.com/global-reporting/abuse-contact-db\nabusix.com is neither responsible nor liable for the content or accuracy of this message.\n # Path to the log files which contain relevant lines for the abuser IP diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py index 28c23abd..e2046e15 100644 --- a/fail2ban/server/actions.py +++ b/fail2ban/server/actions.py @@ -341,15 +341,17 @@ class Actions(JailThread, Mapping): ticket = self._jail.getFailTicket() if not ticket: break - aInfo = CallingMap() bTicket = BanManager.createBanTicket(ticket) ip = bTicket.getIP() - aInfo["ip"] = ip - aInfo["failures"] = bTicket.getAttempt() - aInfo["time"] = bTicket.getTime() - aInfo["matches"] = "\n".join(bTicket.getMatches()) - # to bypass actions, that should not be executed for restored tickets - aInfo["restored"] = 1 if ticket.restored else 0 + aInfo = CallingMap({ + "ip" : ip, + "ip-rev" : lambda: ip.getPTR(''), + "failures": bTicket.getAttempt(), + "time" : bTicket.getTime(), + "matches" : "\n".join(bTicket.getMatches()), + # to bypass actions, that should not be executed for restored tickets + "restored": (1 if ticket.restored else 0) + }) if self._jail.database is not None: mi4ip = lambda overalljails=False, self=self, \ mi={'ip':ip, 'ticket':bTicket}: self.__getBansMerged(mi, overalljails) diff --git a/fail2ban/server/ipdns.py b/fail2ban/server/ipdns.py index f8db6a04..a5625629 100644 --- a/fail2ban/server/ipdns.py +++ b/fail2ban/server/ipdns.py @@ -346,7 +346,7 @@ class IPAddr(object): return socket.inet_ntop(self._family, binary) + add - def getPTR(self, suffix=""): + def getPTR(self, suffix=None): """ return the DNS PTR string of the provided IP address object If "suffix" is provided it will be appended as the second and top @@ -356,11 +356,11 @@ class IPAddr(object): """ if self.isIPv4: exploded_ip = self.ntoa.split(".") - if not suffix: + if suffix is None: suffix = "in-addr.arpa." elif self.isIPv6: exploded_ip = self.hexdump - if not suffix: + if suffix is None: suffix = "ip6.arpa." else: return "" diff --git a/fail2ban/tests/servertestcase.py b/fail2ban/tests/servertestcase.py index f5541ed0..fce03573 100644 --- a/fail2ban/tests/servertestcase.py +++ b/fail2ban/tests/servertestcase.py @@ -1678,18 +1678,29 @@ class ServerConfigReaderTests(LogCaptureTestCase): ('j-complain-abuse', 'complain[' 'name=%(__name__)s, grepopts="-m 1", grepmax=2, mailcmd="mail -s",' + + # test reverse ip: + 'debug=1,' + # 2 logs to test grep from multiple logs: 'logpath="' + os.path.join(TEST_FILES_DIR, "testcase01.log") + '\n' + ' ' + os.path.join(TEST_FILES_DIR, "testcase01a.log") + '", ' ']', { 'ip4-ban': ( + # test reverse ip: + 'try to resolve 10.124.142.87.abuse-contacts.abusix.org', 'Lines containing failures of 87.142.124.10 (max 2)', 'testcase01.log:Dec 31 11:59:59 [sshd] error: PAM: Authentication failure for kevin from 87.142.124.10', 'testcase01a.log:Dec 31 11:55:01 [sshd] error: PAM: Authentication failure for test from 87.142.124.10', # both abuse mails should be separated with space: 'mail -s Abuse from 87.142.124.10 abuse-1@abuse-test-server abuse-2@abuse-test-server', ), + 'ip6-ban': ( + # test reverse ip: + 'try to resolve 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.abuse-contacts.abusix.org', + 'Lines containing failures of 2001:db8::1 (max 2)', + # both abuse mails should be separated with space: + 'mail -s Abuse from 2001:db8::1 abuse-1@abuse-test-server abuse-2@abuse-test-server', + ), }), ) server = TestServer() @@ -1710,6 +1721,8 @@ class ServerConfigReaderTests(LogCaptureTestCase): jails = server._Server__jails + ipv4 = IPAddr('87.142.124.10') + ipv6 = IPAddr('2001:db8::1'); for jail, act, tests in testJailsActions: # print(jail, jails[jail]) for a in jails[jail].actions: @@ -1720,8 +1733,10 @@ class ServerConfigReaderTests(LogCaptureTestCase): # wrap default command processor: action.executeCmd = self._executeMailCmd # test ban : - self.pruneLog('# === ban ===') - action.ban({'ip': IPAddr('87.142.124.10'), - 'failures': 100, - }) - self.assertLogged(*tests['ip4-ban'], all=True) + for (test, ip) in (('ip4-ban', ipv4), ('ip6-ban', ipv6)): + if not tests.get(test): continue + self.pruneLog('# === %s ===' % test) + ticket = _actions.CallingMap({ + 'ip': ip, 'ip-rev': lambda: ip.getPTR(''), 'failures': 100,}) + action.ban(ticket) + self.assertLogged(*tests[test], all=True)