{"id":13508277,"url":"https://github.com/jrbrtsn/ban2fail","last_synced_at":"2025-03-30T10:30:48.174Z","repository":{"id":216953501,"uuid":"223525748","full_name":"jrbrtsn/ban2fail","owner":"jrbrtsn","description":"Simple \u0026 efficient log file scanning and iptable filtering","archived":false,"fork":false,"pushed_at":"2022-08-13T20:22:11.000Z","size":378,"stargazers_count":27,"open_issues_count":2,"forks_count":7,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-01T07:33:28.775Z","etag":null,"topics":["anti-bot","attack-prevention","attackers","ban-hosts","c","fail2ban","gplv3","intrusion-prevention","iptables","iptables-filtering","iptables-rules","linux-server","loganalyzer","logfile-analysis","logs","monitoring","scanning","security","security-tools","zero-trust"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jrbrtsn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-11-23T03:38:11.000Z","updated_at":"2024-07-04T07:42:28.000Z","dependencies_parsed_at":"2024-01-13T21:29:12.631Z","dependency_job_id":"2736f55f-e871-44ff-bc20-5fac042f946a","html_url":"https://github.com/jrbrtsn/ban2fail","commit_stats":null,"previous_names":["jrbrtsn/ban2fail"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrbrtsn%2Fban2fail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrbrtsn%2Fban2fail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrbrtsn%2Fban2fail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrbrtsn%2Fban2fail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jrbrtsn","download_url":"https://codeload.github.com/jrbrtsn/ban2fail/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246307591,"owners_count":20756473,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anti-bot","attack-prevention","attackers","ban-hosts","c","fail2ban","gplv3","intrusion-prevention","iptables","iptables-filtering","iptables-rules","linux-server","loganalyzer","logfile-analysis","logs","monitoring","scanning","security","security-tools","zero-trust"],"created_at":"2024-08-01T02:00:50.737Z","updated_at":"2025-03-30T10:30:47.640Z","avatar_url":"https://github.com/jrbrtsn.png","language":"C","funding_links":[],"categories":["C","c"],"sub_categories":[],"readme":"# ban2fail\n\n(C) 2019 John D. Robertson \u003cjohn@rrci.com\u003e\n\n**ban2fail** is a simple and efficient tool to coordinate log file scanning,\nreporting, and iptables filtering. As the name implies, *ban2fail* was\ninspired by the popular *fail2ban* project (http://fail2ban.org). The main\ntechnical advantages *ban2fail* provides over *fail2ban* are:\n\n+ When installed as a systemd service, filtering response is well under 0.5\nsecond.\n\n+ By design all relevant logfiles on disk are scanned, not just the current\nlog files.\n\n+ A unique and transparent caching scheme is employed to make this process at\nleast 100x as fast as doing the same thing with, say, *grep*.\n\n+ Instantaneously and conveniently produces on command all offending logfile\nentries which exist somewhere in the logfile history for given address(es).\n\n+ Easily handles hundreds of thousands of blocked IP addresses.\n\n+ Directly calls iptables, and handles filtering rules in one fell swoop using\nfork() \u0026 execve() calls.\n\n+ Provides integrated reporting with reverse and forward DNS information.\n\n+ When reporting, DNS lookups are performed in parallel with 200 simultaneous\nlookups.\n\n+ Written in pure C, with less than 15,000 lines of source code. Your CPU has\nbetter things to do than load the python runtime 10,000 times a day ;-)\n\n+ Efficient enough to run every 0.4 seconds without monopolizing a CPU core on a\nmodest server.\n\n+ In the case of a reboot or after iptables filters get flushed, blocking rules\nwill be instantaneously generated from entire log file histories (long memory).\n\n\n*ban2fail* started with a few hours of frenzied C hacking after my mail server\nwas exploited to deliver spam for others who had cracked a user's SMTP send\npassword. After inspecting the log files I realized that crackers are now using\nwidely distributed attacks, and that I would need an extremely efficient tool\nthat could scan my entire log file history in a fraction of a second on my\nrather modest Linode virtual server to have a chance of stopping them. Here are\nthe timing results for a typical scan on my server:\n\n```\nreal    0m0.325s\nuser    0m0.186s\nsys     0m0.150s\n```\n\nCurrently I am running *ban2fail* from a *systemd* service file which triggers\n*ban2fail* whenever a watched log file is modified. This gives attackers at\nmost a 0.4 second window to do their worst. I hope you find this code useful.\n\n## Reports\n\nThere are 4 basic types of reporting provided:\n\n+ summary\n\n+ per-address\n\n+ per-country\n\n+ log file entries for specific address(es)\n\n### Summary\n\nThe summary report is very brief, but useful for spotting sudden changes\nin numbers of filtered addresses:\n\n```\nban2fail -s\n\n   155 countries affected\n  7669 addresses currently blocked\n```\n\n### Per-Address\n\nPer-address is the most useful report to a system administrator looking for\noverly zealous address blocking. Records appear sorted with the most recent\noffenders on top. Here is a truncated sample report with full DNS information:\n\n```\nban2fail -a+\n=============== ban2fail v0.13.10 =============\nScanning \"/var/log/auth.log\"... found 666 offenses (565 addresses)\nScanning \"/var/log/auth.log.1\"... found 1143 offenses (1075 addresses)\nScanning \"/var/log/auth.log.2.gz\"... found 217 offenses (174 addresses)\nScanning \"/var/log/auth.log.3.gz\"... found 966 offenses (429 addresses)\nScanning \"/var/log/auth.log.4.gz\"... found 267 offenses (168 addresses)\n\u003e\u003e\u003e\u003e Found 3259 offenses (2399 addresses) for /var/log/auth.log*\nScanning \"/var/log/exim4/mainlog\"... found 92 offenses (90 addresses)\nScanning \"/var/log/exim4/mainlog.1\"... found 319 offenses (284 addresses)\nScanning \"/var/log/exim4/mainlog.2.gz\"... found 329 offenses (302 addresses)\nScanning \"/var/log/exim4/mainlog.3.gz\"... found 315 offenses (295 addresses)\nScanning \"/var/log/exim4/mainlog.4.gz\"... found 521 offenses (214 addresses)\nScanning \"/var/log/exim4/mainlog.5.gz\"... found 254 offenses (229 addresses)\nScanning \"/var/log/exim4/mainlog.6.gz\"... found 234 offenses (214 addresses)\nScanning \"/var/log/exim4/mainlog.7.gz\"... found 256 offenses (238 addresses)\nScanning \"/var/log/exim4/mainlog.8.gz\"... found 231 offenses (218 addresses)\nScanning \"/var/log/exim4/mainlog.9.gz\"... found 330 offenses (213 addresses)\nScanning \"/var/log/exim4/mainlog.10.gz\"... found 882 offenses (351 addresses)\nScanning \"/var/log/exim4/mainlog.11.gz\"... found 1795 offenses (504 addresses)\nScanning \"/var/log/exim4/mainlog.12.gz\"... found 2222 offenses (1201 addresses)\nScanning \"/var/log/exim4/mainlog.13.gz\"... found 732 offenses (349 addresses)\nScanning \"/var/log/exim4/mainlog.14.gz\"... found 736 offenses (370 addresses)\n\u003e\u003e\u003e\u003e Found 9248 offenses (4997 addresses) for /var/log/exim4/mainlog*\nScanning \"/var/log/apache2/access.log\"... found 18 offenses (7 addresses)\nScanning \"/var/log/apache2/access.log.1\"... found 734 offenses (54 addresses)\nScanning \"/var/log/apache2/access.log.2.gz\"... found 649 offenses (23 addresses)\nScanning \"/var/log/apache2/access.log.3.gz\"... found 383 offenses (6 addresses)\nScanning \"/var/log/apache2/access.log.4.gz\"... found 235 offenses (4 addresses)\nScanning \"/var/log/apache2/access.log.5.gz\"... found 75 offenses (4 addresses)\nScanning \"/var/log/apache2/access.log.6.gz\"... found 156 offenses (2 addresses)\nScanning \"/var/log/apache2/access.log.7.gz\"... found 815 offenses (6 addresses)\nScanning \"/var/log/apache2/access.log.8.gz\"... found 582 offenses (27 addresses)\nScanning \"/var/log/apache2/access.log.9.gz\"... found 1001 offenses (16 addresses)\nScanning \"/var/log/apache2/access.log.10.gz\"... found 802 offenses (8 addresses)\nScanning \"/var/log/apache2/access.log.11.gz\"... found 386 offenses (5 addresses)\nScanning \"/var/log/apache2/access.log.12.gz\"... found 466 offenses (78 addresses)\nScanning \"/var/log/apache2/access.log.13.gz\"... found 524 offenses (25 addresses)\nScanning \"/var/log/apache2/access.log.14.gz\"... found 565 offenses (16 addresses)\n\u003e\u003e\u003e\u003e Found 7391 offenses (255 addresses) for /var/log/apache2/access.log*\nScanning \"/var/log/mail.log\"... found 608 offenses (457 addresses)\nScanning \"/var/log/mail.log.1\"... found 964 offenses (894 addresses)\nScanning \"/var/log/mail.log.2.gz\"... found 170 offenses (5 addresses)\nScanning \"/var/log/mail.log.3.gz\"... found 0 offenses (0 addresses)\nScanning \"/var/log/mail.log.4.gz\"... found 0 offenses (0 addresses)\n\u003e\u003e\u003e\u003e Found 1742 offenses (1351 addresses) for /var/log/mail.log*\n===== Found 21640 total offenses (7660 addresses) =====\nPerforming DNS lookups for up to 60 seconds ...\n\t==\u003e Completed 7660 of 7660 lookups in 60.0 seconds\n3 Dec 07 07:09      1/0    offenses US [BLK] 184.179.216.156 \t NXDOMAIN\n0 Dec 07 07:08      1/0    offenses US [BLK] 23.254.228.40 \tclient-23-254-228-40.hostwindsdns.com !!\n2 Dec 07 07:04      1/0    offenses HK [BLK] 47.91.220.119 \t NXDOMAIN\n3 Dec 07 06:57      2/0    offenses TR [BLK] 81.214.245.188 \t81.214.245.188.dynamic.ttnet.com.tr !!\n0 Dec 07 06:51      1/0    offenses -- [BLK] 188.119.103.157 \t NXDOMAIN\n0 Dec 07 06:50      1/0    offenses GB [BLK] 185.217.230.211 \t SERVFAIL\n0 Dec 07 06:47      1/0    offenses RU [BLK] 92.38.176.115 \tjournalagricult.casa !\n0 Dec 07 06:47      1/0    offenses CO [BLK] 191.103.219.225 \txdsl-191-103-219-225.edatel.net.co !!\n4 Dec 07 06:46      2/0    offenses CN [BLK] 175.6.5.233 \t NXDOMAIN\n0 Dec 07 06:44      1/0    offenses UA [BLK] 109.87.78.144 \t144.78.87.109.triolan.net !!\n0 Dec 07 06:36      1/0    offenses BR [BLK] 200.209.34.34 \t NXDOMAIN\n3 Dec 07 06:35      2/0    offenses US [BLK] 184.179.216.138 \t NXDOMAIN\n3 Dec 07 06:31      2/0    offenses CN [BLK] 120.33.205.162 \t NXDOMAIN\n0 Dec 07 06:30      1/0    offenses SG [BLK] 160.20.12.205 \t SERVFAIL\n--- snipped ---\n===============================================\n  7660 addresses currently blocked\n```\n\n### Per-Country\n\nPer-country reports show how blocked address are distributed between the countries:\n\n```\nban2fail -c\n=============== ban2fail v0.13.10 =============\nScanning \"/var/log/auth.log\"... found 666 offenses (565 addresses)\nScanning \"/var/log/auth.log.1\"... found 1143 offenses (1075 addresses)\n--- snipped ---\n===== Found 21642 total offenses (7661 addresses) =====\nUS   1335 blocked addresses\nCN    852 blocked addresses\nVN    619 blocked addresses\nRU    432 blocked addresses\nBR    414 blocked addresses\nIN    244 blocked addresses\nGB    197 blocked addresses\n--    196 blocked addresses\nAR    175 blocked addresses\nTH    141 blocked addresses\nFR    140 blocked addresses\nID    136 blocked addresses\n--- snipped ---\n===============================================\n   155 countries affected\n```\n\n### Log File Entries for Given Address(es)\n\nBefore unblocking any address it is usually necessary to investigate the\noffending log file entries. Here is an example:\n\n\n```\nban2fail 184.179.216.156 23.254.228.40\n====== Report for 184.179.216.156 ======\n------- /var/log/auth.log -------------\nDec  7 07:09:52 srv auth: pam_unix(dovecot:auth): authentication failure; logname= uid=0 euid=0 tty=dovecot ruser=andrews_maddie@somedomain.com rhost=184.179.216.156\n------- /var/log/mail.log -------------\nDec  7 07:12:29 srv dovecot: imap-login: Disconnected: Inactivity (auth failed, 1 attempts in 160 secs): user=\u003candrews_maddie@somedomain.com\u003e, method=PLAIN, rip=184.179.216.156, lip=50.116.38.131, TLS, session=\u003clZUGChyZ8+G4s9ic\u003e\n====== Report for 23.254.228.40 ======\n------- /var/log/exim4/mainlog -------------\n2019-12-07 07:08:27 H=(green.medifeetz.icu) [23.254.228.40] F=\u003c4434-1592-49095-1194-user=rrci.com@mail.medifeetz.icu\u003e rejected RCPT \u003cuser@rrci.com\u003e: 23.254.228.40 is listed at zen.spamhaus.org (127.0.0.3: https://www.spamhaus.org/sbl/query/SBLCSS)\n```\n\n\n## Configuration\n\n*ban2fail* works from a configuration file found at\n\"/etc/ban2fail/ban2fail.cfg\".  The overarching premise is that if any REGEX\nappearing in a LOGTYPE clause matches a line in an associated log file, then by\ndefault that IP will be blocked.\n\n\n```\nLOGTYPE auth {\n\n   # Where to find the log files\n   DIR= /var/log\n   PREFIX= auth.log\n\n   # How to read the timestamp\n   TIMESTAMP auth_ts {\n      # isolates the timestamp from a line matched by a TARGET\n      REGEX= ^(.*) srv\n      # Passed to strptime() to intrepret the timestamp string\n      STRPTIME= %b %d %T\n      # These stamps do not include the year, so it is implied.\n      FLAGS= GUESS_YEAR\n   }\n\n   TARGET imap {\n      # Pattern to search for, isolates the IP address\n      REGEX= imapd.*Login failed.*\\[([0-9.a-f:]+)\\]$\n      # Assign this as the severity of the offense.\n      SEVERITY= 3\n   }\n\n   TARGET ssh {\n      SEVERITY= 4\n      REGEX= sshd.*Failed password.*from ([0-9.a-f:]+) port [0-9]+ ssh2$\n      REGEX= sshd.*Invalid user.*from ([0-9.a-f:]+) port\n   }\n\n   TARGET negotiate_fail {\n      SEVERITY= 2\n      REGEX= Unable to negotiate with ([0-9.a-f:]+) port\n   }\n\n   TARGET dovecot {\n      SEVERITY= 3\n      REGEX= dovecot.*authentication failure.*rhost=([0-9.a-f:]+)\n   }\n}\n```\n\n\nSyntax in the config file is pretty much the same as the nftables syntax. All\nkeywords must be in upper case.  Any values in the key=value pairs have\nwhitespace stripped from the beginning and end of the line. Since there is\nlittle escaping of characters going on, regular expressions are mostly WYSIWYG.\nIf you have a hash symbol '#' or a double quote '\"' in your pattern (which are\nspecial characters for the config file parser), you will need to escape\nthem like so:\n\n```\n# Nov 27 02:03:03 srv named[764]: client @0x7fe6a0053420 1.192.90.183#27388 (www.ipplus360.com): query (cache) 'www.ipplus360.com/A/IN' denied\n   REGEX= named.*client.* ([0-9.a-f:]+)\\#.*denied$\n```\n\nFinding typos and so forth in the config file is easy; use the -v command flag\nto print all unrecognized content (besides comments).\n\n`ban2fail -v`\n\nThe only way to alter the default blocking behavior is with a MAX\\_OFFENSES\nclause. This clause allows you specify how many offenses are tolerated before an\nIP is blocked. Offenses will naturally disappear as old logfiles are deleted by\n*logrotate*.\n\n```\n# Whitelist ourself\nMAX_OFFENSES -1 {\n# Put your server's IP addresses here\n#   IP= 1.2.3.4\n   IP= 127.0.0.1\n#   IP= dead:beef::20::32a\n   IP= ::1\n}\n\n# Allegedly legit servers\nMAX_OFFENSES 50 {\n\n# Google Ireland\n   IP= 2a00:1450:4864:20::32a\n   IP= 2a00:1450:4864:20::336\n\n# Google EU\n# Attempted to break in\n#   IP= 35.205.240.168\n\n# Google US\n   IP= 09.85.216.42\n# Attempted to break in\n#   IP= 130.211.246.128\n   IP= 209.85.166.194\n   IP= 209.85.166.195\n   IP= 209.85.208.67\n   IP= 209.85.214.194\n   IP= 209.85.215.173\n   IP= 209.85.215.175\n   IP= 209.85.215.193\n   IP= 209.85.216.42\n   IP= 2607:f8b0:4864:20::1034\n   IP= 2607:f8b0:4864:20::a46\n\n# Yahoo\n   IP= 106.10.244.139\n\n# Outlook\n   IP= 40.92.4.30\n   IP= 40.107.73.61\n   IP= 40.107.74.48\n   IP= 40.107.74.72 \n   IP= 40.107.76.74\n   IP= 40.107.79.52\n   IP= 40.107.79.59\n   IP= 40.107.80.40\n   IP= 40.107.80.53\n   IP= 40.107.80.78\n   IP= 40.107.82.75\n   IP= 52.101.129.30\n   IP= 52.101.132.108\n   IP= 52.101.136.79\n   IP= 52.101.140.230\n}\n\n# \"trusted\" addresses\nMAX_OFFENSES 200 {\n\n# me from home\n#   IP= 1.2.3.4/20\n\n# Customer\n#   IP= 5.6.7.8/24\n}\n```\n\nIf you recieve a complaint about an address unjustly getting blocked, place it\nin one of the MAX\\_OFFENSES blocks, and the IP will be unblocked the next time\n*ban2fail* runs in production mode.\n\n## Working with *ban2fail*\n\nThere are two primary modes in which *ban2fail* is used:\n\n* Production mode, where iptables rules are modified.\n\n* Testing mode, where modifications to blocking rules are merely indicated.\n\n### Production\n\nIn production mode it is expected that *ban2fail* is running non-interactively,\nand no output is printed unless addresses are (un)blocked. It is also possible\nto generate a listing of addresses, offense counts, and status with the -a\ncommand flag. Likewise, a listing of countries and offense counts is available\nwith the *-c* flag. In order to get DNS information for the *-a* flag, follow\nwith a plus for all DNS info *-a+*, or a minus for only legit (backward \u0026\nforward match) info *-a-*. In the list, DNS issues are presented like so:\n\n```\n# DNS is good\n0 Dec 06 08:31      1/0    offenses AR [BLK] 200.71.237.244     host244.200-71-237.telecom.net.ar\n\n# Reverse lookup failed with DNS server\n0 Dec 05 19:43      1/0    offenses GB [BLK] 185.217.230.146     SERVFAIL\n\n# Reverse lookup is a non-existent domain\n2 Dec 05 21:11      1/0    offenses US [BLK] 67.205.153.94       NXDOMAIN\n\n# Forward lookup does not match reverse lookup\n0 Dec 06 08:40      1/0    offenses LU [BLK] 92.38.132.54       ibocke43.monster !\n\n# Forward DNS record does not exist\n0 Dec 06 08:37      1/0    offenses US [BLK] 63.81.90.135       63-81-90-135.nca.lanset.com !!\n\n# DNS is inconclusive due to lack of response from a DNS server\n0 Dec 05 22:04      1/0    offenses RU [BLK] 77.221.144.107     news5.burningcoalsa.com ~\n```\n\nIf you want to see the offending log lines for specific address(es), supply\nthem on the command line like so:\n\n```\njohn@srv:~$  ban2fail 68.183.105.52\n====== Report for 68.183.105.52 ======\n------- /var/log/auth.log -------------\nDec  5 17:50:47 srv sshd[22326]: Invalid user cron from 68.183.105.52 port 41874\nDec  5 17:50:48 srv sshd[22326]: Failed password for invalid user cron from 68.183.105.52 port 41874 ssh2\n\n```\n\n### Testing\n\nIn test mode (-t flag) the presumption is that you are testing a modified\nconfiguration which is not yet in place, and that you don't want to disturb the\nproduction setup. This is how you might do that:\n\n`ban2fail -t myNew.cfg -a`\n\nNo iptables rules will be modified. You will be shown in the listing which\naddresses would be (un)blocked if the contents of \"myNew.cfg\" was in place, and\n*ban2fail* was running in production mode.\n\nWhen you are happy with the new configuration, copy it into place, and the the\niptable rule changes will be realized the next time *ban2fail* runs in\nproduction mode.\n\n## Building the Project\n\nI've tested *ban2fail* only on Debian Buster, but it should compile on just\nabout any modern Linux distro. It uses the following libraries:\n\n+ *libcrypto* from the libssl package, for md5 checksums\n\n+ *libGeoIP* to identify the country of origin for IP addresses\n\n+ *libz* to read compressed log files\n\n+ *libpthread* for parallel DNS lookups (200 simultaneous)\n\n+ *libdb* caching of offense location and size in log files\n\nBuild and install like so:\n\n```\nmake release\nmake install\n```\n\nThe make *install* target calls *install.sh*, which does a bunch of stuff\nincluding setting up and enabling a systemd service, so you might want have a\nlook before pulling the trigger.\n\n*ban2fail.service* points to *ban2fail.sh*, which can be tested from the command line for debugging.  Remember to make sure the service is disabled:\n```\nsystemctl stop ban2fail\n```\n\nIn order to run *ban2fail* as non-root user, the user must belong to group\n'adm'. This is so in order to run iptables, which is accomplished via setuid(0)\nat the appropriate time.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjrbrtsn%2Fban2fail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjrbrtsn%2Fban2fail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjrbrtsn%2Fban2fail/lists"}