diff options
| author | Robert Günzler <r@gnzler.io> | 2025-09-07 17:32:13 +0200 |
|---|---|---|
| committer | Robert Günzler <r@gnzler.io> | 2025-09-07 17:42:42 +0200 |
| commit | 38be6c13f76e893cf47636257071b440dec0c5b2 (patch) | |
| tree | f7ded3235a7e3362cbd1ed3d91523968fe0faf90 /bundles/fail2ban | |
initial commit
Signed-off-by: Robert Günzler <r@gnzler.io>
Diffstat (limited to 'bundles/fail2ban')
| -rw-r--r-- | bundles/fail2ban/files/etc/fail2ban/action.d/telegram-webhook.conf | 24 | ||||
| -rw-r--r-- | bundles/fail2ban/files/etc/fail2ban/filter.d/traefik-badbots.conf | 12 | ||||
| -rw-r--r-- | bundles/fail2ban/files/etc/fail2ban/filter.d/traefik-spam.conf | 13 | ||||
| -rw-r--r-- | bundles/fail2ban/files/etc/fail2ban/jail.d/sshd.conf | 5 | ||||
| -rw-r--r-- | bundles/fail2ban/files/etc/fail2ban/jail.d/traefik.conf | 10 | ||||
| -rw-r--r-- | bundles/fail2ban/files/etc/fail2ban/jail.local | 22 | ||||
| -rw-r--r-- | bundles/fail2ban/items.py | 31 | ||||
| -rw-r--r-- | bundles/fail2ban/metadata.py | 7 |
8 files changed, 124 insertions, 0 deletions
diff --git a/bundles/fail2ban/files/etc/fail2ban/action.d/telegram-webhook.conf b/bundles/fail2ban/files/etc/fail2ban/action.d/telegram-webhook.conf new file mode 100644 index 0000000..34b2cb3 --- /dev/null +++ b/bundles/fail2ban/files/etc/fail2ban/action.d/telegram-webhook.conf @@ -0,0 +1,24 @@ +[Definition] + +# Notify on Startup +# actionstart = tgnotify "The **[<name>]** jail has started" +actionstart = + +# Notify on Shutdown +# actionstop = tgnotify "The **[<name>]** jail has been stopped" +actionstop = + +actioncheck = + +# Notify on Banned +# TODO: template node.name +actionban = tgnotify '💥*inazuma/fail2ban/<name>*\nBanned [<ip>](<url_check_ip><ip>) for <bantime> seconds after <failures> failure(s).\nIf you want to unban the IP run: `fail2ban-client unban <ip>`' + +# Notify on Unbanned +# TODO: template node.name +actionunban = tgnotify '🕊️*inazuma/fail2ban/<name>*\nUnbanned [<ip>](<url_check_ip><ip>)' + +[Init] +# URL prefix for an IP checking website +# abuseipdb is used by default since there is also an action to report an IP to their API +url_check_ip = https://www.abuseipdb.com/check/ diff --git a/bundles/fail2ban/files/etc/fail2ban/filter.d/traefik-badbots.conf b/bundles/fail2ban/files/etc/fail2ban/filter.d/traefik-badbots.conf new file mode 100644 index 0000000..65ea993 --- /dev/null +++ b/bundles/fail2ban/files/etc/fail2ban/filter.d/traefik-badbots.conf @@ -0,0 +1,12 @@ +[Definition] + +badbots = 360Spider|404checker|404enemy|80legs|Abonti|Aboundex|Acunetix|ADmantX|AfD-Verbotsverfahren|AhrefsBot|AIBOT|AiHitBot|Aipbot|Alexibot|Alligator|AllSubmitter|AlphaBot|Anarchie|Apexoo|ASPSeek|Asterias|Attach|autoemailspider|BackDoorBot|Backlink-Ceck|backlink-check|BacklinkCrawler|BackStreet|BackWeb|Badass|Bandit|Barkrowler|BatchFTP|Battleztar Bazinga|BBBike|BDCbot|BDFetch|BetaBot|Bigfoot|Bitacle|Blackboard|Black Hole|BlackWidow|BLEXBot|Blow|BlowFish|Boardreader|Bolt|BotALot|Brandprotect|Brandwatch|Bubing|Buddy|BuiltBotTough|BuiltWith|Bullseye|BunnySlippers|BuzzSumo|Calculon|CATExplorador|CazoodleBot|CCBot|Cegbfeieh|CheeseBot|CherryPicker|ChinaClaw|Chlooe|Claritybot|Cliqzbot|Cloud mapping|coccocbot-web|Cogentbot|cognitiveseo|Collector|com\.plumanalytics|Copier|CopyRightCheck|Copyscape|Cosmos|Craftbot|crawler4j|crawler\.feedback|CrazyWebCrawler|Crescent|CSHttp|Curious|Custo|DatabaseDriverMysqli|DataCha0s|DBLBot|demandbase-bot|Demon|Deusu|Devil|Digincore|DigitalPebble|DIIbot|Dirbuster|Disco|Discobot|Discoverybot|DittoSpyder|DnyzBot|DomainAppender|DomainCrawler|DomainSigmaCrawler|DomainStatsBot|Dotbot|Download Wonder|Dragonfly|Drip|DTS Agent|EasyDL|Ebingbong|eCatch|ECCP/1\.0|Ecxi|EirGrabber|EMail Siphon|EMail Wolf|EroCrawler|evc-batch|Evil|Exabot|Express WebPictures|ExtLinksBot|Extractor|ExtractorPro|Extreme Picture Finder|Expanse|EyeNetIE|Ezooms|FDM|FemtosearchBot|FHscan|Fimap|Firefox/7\.0|FlashGet|Flunky|Foobot|Freeuploader|FrontPage|Fyrebot|GalaxyBot|Genieo|GermCrawler|Getintent|GetRight|GetWeb|Gigablast|Gigabot|G-i-g-a-b-o-t|Go-Ahead-Got-It|Gotit|GoZilla|Go!Zilla|Grabber|GrabNet|Grafula|GrapeFX|GrapeshotCrawler|GridBot|GT\:\:WWW|Haansoft|HaosouSpider|Harvest|Havij|HEADMasterSEO|Heritrix|Hloader|HMView|HTMLparser|HTTP\:\:Lite|HTTrack|Humanlinks|HybridBot|Iblog|IDBot|Id-search|IlseBot|Image Fetch|Image Sucker|IndeedBot|Indy Library|InfoNaviRobot|InfoTekies|instabid|Intelliseek|InterGET|Internet Ninja|InternetSeer|internetVista monitor|ips-agent|Iria|IRLbot|Iskanie|IstellaBot|JamesBOT|Jbrofuzz|JennyBot|JetCar|JikeSpider|JOC Web Spider|Joomla|Jorgee|JustView|Jyxobot|Kenjin Spider|Keyword Density|Kozmosbot|Lanshanbot|Larbin|LeechFTP|LeechGet|LexiBot|Lftp|LibWeb|Libwhisker|Lightspeedsystems|Likse|Linkdexbot|LinkextractorPro|LinkpadBot|LinkScan|LinksManager|LinkWalker|LinqiaMetadataDownloaderBot|LinqiaRSSBot|LinqiaScrapeBot|Lipperhey|Litemage_walker|Lmspider|LNSpiderguy|Ltx71|lwp-request|LWP\:\:Simple|lwp-trivial|Magnet|Mag-Net|magpie-crawler|Mail\.RU_Bot|Majestic12|MarkMonitor|MarkWatch|Masscan|masscan|Mass Downloader|Mata Hari|MauiBot|Meanpathbot|mediawords|MegaIndex\.ru|Metauri|MFC_Tear_Sample|Microsoft Data Access|Microsoft URL Control|MIDown tool|MIIxpc|Mister PiX|MJ12bot|Mojeek|Morfeus Fucking Scanner|Mr\.4x3|MSFrontPage|MSIECrawler|Msrabot|MS Web Services Client Protocol|muhstik-scan|Musobot|Name Intelligence|Nameprotect|Navroad|NearSite|Needle|Nessus|NetAnts|Netcraft|netEstate NE Crawler|NetLyzer|NetMechanic|NetSpider|Nettrack|Net Vampire|Netvibes|NetZIP|NextGenSearchBot|Nibbler|NICErsPRO|Niki-bot|Nikto|NimbleCrawler|Ninja|Nmap|NPbot|Nutch|oBot|Octopus|Offline Explorer|Offline Navigator|Openfind|OpenLinkProfiler|Openvas|OrangeBot|OrangeSpider|OutclicksBot|OutfoxBot|PageAnalyzer|Page Analyzer|PageGrabber|page scorer|PageScorer|Panscient|Papa Foto|Pavuk|pcBrowser|PECL\:\:HTTP|PeoplePal|PHPCrawl|Picscout|Picsearch|PictureFinder|Pimonster|Pi-Monster|Pixray|PleaseCrawl|plumanalytics|Pockey|POE-Component-Client-HTTP|Probethenet|ProPowerBot|ProWebWalker|Psbot|Pump|PxBroker|PyCurl|QueryN Metasearch|Quick-Crawler|RankActive|RankActiveLinkBot|RankFlex|RankingBot|RankingBot2|Rankivabot|RankurBot|RealDownload|Reaper|RebelMouse|Recorder|RedesScrapy|ReGet|RepoMonkey|Ripper|RocketCrawler|Rogerbot|SalesIntelligent|SBIder|ScanAlert|Scanbot|scan\.lol|Scrapy|Screaming|ScreenerBot|Searchestate|SearchmetricsBot|Semrush|SemrushBot|SEOkicks|SEOlyticsCrawler|Seomoz|SEOprofiler|seoscanners|SEOstats|sexsearcher|Seznam|SeznamBot|Shodan|Siphon|SISTRIX|Sitebeam|SiteExplorer|Siteimprove|SiteLockSpider|SiteSnagger|SiteSucker|Site Sucker|Sitevigil|Slackbot-LinkExpanding|SlySearch|SmartDownload|SMTBot|Snake|Snapbot|Snoopy|SocialRankIOBot|Sogou web spider|Sosospider|Sottopop|SpaceBison|Spammen|SpankBot|Spanner|Spbot|Spinn3r|SputnikBot|Sqlmap|Sqlworm|Sqworm|Steeler|Stripper|Sucker|Sucuri|SuperBot|SuperHTTP|Surfbot|SurveyBot|Suzuran|Swiftbot|sysscan|Szukacz|T0PHackTeam|T8Abot|tAkeOut|Teleport|TeleportPro|Telesoft|Telesphoreo|Telesphorep|The Intraformant|TheNomad|TightTwatBot|Titan|Toata|Toweyabot|Trendiction|Trendictionbot|trendiction\.com|trendiction\.de|True_Robot|Turingos|Turnitin|TurnitinBot|TwengaBot|Twice|Typhoeus|UnisterBot|URLy\.Warning|URLy Warning|Vacuum|Vagabondo|VB Project|VCI|VeriCiteCrawler|VidibleScraper|Virusdie|VoidEYE|Voil|Voltron|Wallpapers/3\.0|WallpapersHD|WASALive-Bot|WBSearchBot|Webalta|WebAuto|Web Auto|WebBandit|WebCollage|Web Collage|WebCopier|WEBDAV|WebEnhancer|Web Enhancer|WebFetch|Web Fetch|WebFuck|Web Fuck|WebGo IS|WebImageCollector|WebLeacher|WebmasterWorldForumBot|webmeup-crawler|WebPix|Web Pix|WebReaper|WebSauger|Web Sauger|Webshag|WebsiteExtractor|WebsiteQuester|Website Quester|Webster|WebStripper|WebSucker|Web Sucker|WebWhacker|WebZIP|WeSEE|Whack|Whacker|Whatweb|Who\.is Bot|Widow|WinHTTrack|WiseGuys Robot|WISENutbot|Wonderbot|Woobot|Wotbox|Wprecon|WPScan|WWW-Collector-E|WWW-Mechanize|WWW\:\:Mechanize|WWWOFFLE|x09Mozilla|x22Mozilla|Xaldon_WebSpider|Xaldon WebSpider|Xenu|xpymep1\.exe|YoudaoBot|Zade|Zauba|zauba\.io|Zermelo|Zeus|zgrab|Zitebot|ZmEu|ZumBot|ZyBorg|CensysInspect|Nmap Scripting Engine + +# fail regex based on traefik JSON access logs with enabled user agent logging +failregex = ^{"ClientAddr":"<F-CLIENTADDR>.*</F-CLIENTADDR>","ClientHost":"<HOST>","ClientPort":"<F-CLIENTPORT>.*</F-CLIENTPORT>","ClientUsername":"<F-CLIENTUSERNAME>.*</F-CLIENTUSERNAME>","DownstreamContentSize":<F-DOWNSTREAMCONTENTSIZE>.*</F-DOWNSTREAMCONTENTSIZE>,"DownstreamStatus":<F-DOWNSTREAMSTATUS>.*</F-DOWNSTREAMSTATUS>,"Duration":<F-DURATION>.*</F-DURATION>,"OriginContentSize":<F-ORIGINCONTENTSIZE>.*</F-ORIGINCONTENTSIZE>,"OriginDuration":<F-ORIGINDURATION>.*</F-ORIGINDURATION>,"OriginStatus":.*,"Overhead":<F-OVERHEAD>.*</F-OVERHEAD>,"RequestAddr":"<F-REQUESTADDR>.*</F-REQUESTADDR>","RequestContentSize":<F-REQUESTCONTENTSIZE>.*</F-REQUESTCONTENTSIZE>,"RequestCount":<F-REQUESTCOUNT>.*</F-REQUESTCOUNT>,"RequestHost":"<F-CONTAINER>.*</F-CONTAINER>","RequestMethod":"<F-REQUESTMETHOD>.*</F-REQUESTMETHOD>","RequestPath":"<F-REQUESTPATH>.*</F-REQUESTPATH>","RequestPort":"<F-REQUESTPORT>.*</F-REQUESTPORT>","RequestProtocol":"<F-REQUESTPROTOCOL>.*</F-REQUESTPROTOCOL>","RequestScheme":"<F-REQUESTSCHEME>.*</F-REQUESTSCHEME>","RetryAttempts":<F-RETRYATTEMPTS>.*</F-RETRYATTEMPTS>,.*"StartLocal":"<F-STARTLOCAL>.*</F-STARTLOCAL>","StartUTC":"<F-STARTUTC>.*</F-STARTUTC>","TLSCipher":"<F-TLSCIPHER>.*</F-TLSCIPHER>","TLSVersion":"<F-TLSVERSION>.*</F-TLSVERSION>","entryPointName":"<F-ENTRYPOINTNAME>.*</F-ENTRYPOINTNAME>","level":"<F-LEVEL>.*</F-LEVEL>","msg":"<F-MSG>.*</F-MSG>","request_User-Agent":"<F-USERAGENT>.*(?:%(badbots)s).*</F-USERAGENT>","time":"<F-TIME>.*</F-TIME>"}$ + +# custom date pattern for traefik JSON access logs +# based on https://github.com/fail2ban/fail2ban/issues/2558#issuecomment-546738270 +datepattern = "StartLocal"\s*:\s*"%%Y-%%m-%%d[T]%%H:%%M:%%S\.%%f\d*(%%z)?", + +ignoreregex = diff --git a/bundles/fail2ban/files/etc/fail2ban/filter.d/traefik-spam.conf b/bundles/fail2ban/files/etc/fail2ban/filter.d/traefik-spam.conf new file mode 100644 index 0000000..7abad3e --- /dev/null +++ b/bundles/fail2ban/files/etc/fail2ban/filter.d/traefik-spam.conf @@ -0,0 +1,13 @@ +[INCLUDES] + +[Definition] + +# fail regex based on traefik JSON access logs with enabled user agent logging +failregex = ^{"ClientAddr":"<F-CLIENTADDR>.*</F-CLIENTADDR>","ClientHost":"<HOST>","ClientPort":"<F-CLIENTPORT>.*</F-CLIENTPORT>","ClientUsername":"<F-CLIENTUSERNAME>.*</F-CLIENTUSERNAME>","DownstreamContentSize":<F-DOWNSTREAMCONTENTSIZE>.*</F-DOWNSTREAMCONTENTSIZE>,"DownstreamStatus":<F-DOWNSTREAMSTATUS>.*</F-DOWNSTREAMSTATUS>,"Duration":<F-DURATION>.*</F-DURATION>,"OriginContentSize":<F-ORIGINCONTENTSIZE>.*</F-ORIGINCONTENTSIZE>,"OriginDuration":<F-ORIGINDURATION>.*</F-ORIGINDURATION>,"OriginStatus":(405|404|403|402|401),"Overhead":<F-OVERHEAD>.*</F-OVERHEAD>,"RequestAddr":"<F-REQUESTADDR>.*</F-REQUESTADDR>","RequestContentSize":<F-REQUESTCONTENTSIZE>.*</F-REQUESTCONTENTSIZE>,"RequestCount":<F-REQUESTCOUNT>.*</F-REQUESTCOUNT>,"RequestHost":"<F-CONTAINER>.*</F-CONTAINER>","RequestMethod":"<F-REQUESTMETHOD>.*</F-REQUESTMETHOD>","RequestPath":"<F-REQUESTPATH>.*</F-REQUESTPATH>","RequestPort":"<F-REQUESTPORT>.*</F-REQUESTPORT>","RequestProtocol":"<F-REQUESTPROTOCOL>.*</F-REQUESTPROTOCOL>","RequestScheme":"<F-REQUESTSCHEME>.*</F-REQUESTSCHEME>","RetryAttempts":<F-RETRYATTEMPTS>.*</F-RETRYATTEMPTS>,.*"StartLocal":"<F-STARTLOCAL>.*</F-STARTLOCAL>","StartUTC":"<F-STARTUTC>.*</F-STARTUTC>","TLSCipher":"<F-TLSCIPHER>.*</F-TLSCIPHER>","TLSVersion":"<F-TLSVERSION>.*</F-TLSVERSION>","entryPointName":"<F-ENTRYPOINTNAME>.*</F-ENTRYPOINTNAME>","level":"<F-LEVEL>.*</F-LEVEL>","msg":"<F-MSG>.*</F-MSG>",("request_User-Agent":"<F-USERAGENT>.*</F-USERAGENT>",){0,1}?"time":"<F-TIME>.*</F-TIME>"}$ + +# custom date pattern for traefik JSON access logs +# based on https://github.com/fail2ban/fail2ban/issues/2558#issuecomment-546738270 +datepattern = "StartLocal"\s*:\s*"%%Y-%%m-%%d[T]%%H:%%M:%%S\.%%f\d*(%%z)?", + +# ignore common errors like missing media files or JS/CSS/TXT/ICO stuff +ignoreregex = ^{"ClientAddr":"<F-CLIENTADDR>.*</F-CLIENTADDR>","ClientHost":"<HOST>","ClientPort":"<F-CLIENTPORT>.*</F-CLIENTPORT>","ClientUsername":"<F-CLIENTUSERNAME>.*</F-CLIENTUSERNAME>","DownstreamContentSize":<F-DOWNSTREAMCONTENTSIZE>.*</F-DOWNSTREAMCONTENTSIZE>,"DownstreamStatus":<F-DOWNSTREAMSTATUS>.*</F-DOWNSTREAMSTATUS>,"Duration":<F-DURATION>.*</F-DURATION>,"OriginContentSize":<F-ORIGINCONTENTSIZE>.*</F-ORIGINCONTENTSIZE>,"OriginDuration":<F-ORIGINDURATION>.*</F-ORIGINDURATION>,"OriginStatus":(405|404|403|402|401),"Overhead":<F-OVERHEAD>.*</F-OVERHEAD>,"RequestAddr":"<F-REQUESTADDR>.*</F-REQUESTADDR>","RequestContentSize":<F-REQUESTCONTENTSIZE>.*</F-REQUESTCONTENTSIZE>,"RequestCount":<F-REQUESTCOUNT>.*</F-REQUESTCOUNT>,"RequestHost":"<F-REQUESTHOST>.*</F-REQUESTHOST>","RequestMethod":"<F-REQUESTMETHOD>.*</F-REQUESTMETHOD>","RequestPath":"<F-REQUESTPATH>.*(\.png|\.txt|\.jpg|\.ico|\.js|\.css|\.ttf|\.woff|\.woff2)(/)*?</F-REQUESTPATH>","RequestPort":"<F-REQUESTPORT>.*</F-REQUESTPORT>","RequestProtocol":"<F-REQUESTPROTOCOL>.*</F-REQUESTPROTOCOL>","RequestScheme":"<F-REQUESTSCHEME>.*</F-REQUESTSCHEME>","RetryAttempts":<F-RETRYATTEMPTS>.*</F-RETRYATTEMPTS>,.*"StartLocal":"<F-STARTLOCAL>.*</F-STARTLOCAL>","StartUTC":"<F-STARTUTC>.*</F-STARTUTC>","TLSCipher":"<F-TLSCIPHER>.*</F-TLSCIPHER>","TLSVersion":"<F-TLSVERSION>.*</F-TLSVERSION>","entryPointName":"<F-ENTRYPOINTNAME>.*</F-ENTRYPOINTNAME>","level":"<F-LEVEL>.*</F-LEVEL>","msg":"<F-MSG>.*</F-MSG>",("request_User-Agent":"<F-USERAGENT>.*</F-USERAGENT>",){0,1}?"time":"<F-TIME>.*</F-TIME>"}$ diff --git a/bundles/fail2ban/files/etc/fail2ban/jail.d/sshd.conf b/bundles/fail2ban/files/etc/fail2ban/jail.d/sshd.conf new file mode 100644 index 0000000..5eb1c14 --- /dev/null +++ b/bundles/fail2ban/files/etc/fail2ban/jail.d/sshd.conf @@ -0,0 +1,5 @@ +[sshd] +enabled = false + +[sshd-ddos] +enabled = false diff --git a/bundles/fail2ban/files/etc/fail2ban/jail.d/traefik.conf b/bundles/fail2ban/files/etc/fail2ban/jail.d/traefik.conf new file mode 100644 index 0000000..a46a1d3 --- /dev/null +++ b/bundles/fail2ban/files/etc/fail2ban/jail.d/traefik.conf @@ -0,0 +1,10 @@ +[traefik-spam] +enabled = true +filter = traefik-spam +logpath = /var/lib/traefik/access.log* + +[traefik-badbots] +enabled = true +filter = traefik-badbots +logpath = /var/lib/traefik/access.log* +maxretry = 1 diff --git a/bundles/fail2ban/files/etc/fail2ban/jail.local b/bundles/fail2ban/files/etc/fail2ban/jail.local new file mode 100644 index 0000000..45fcdc5 --- /dev/null +++ b/bundles/fail2ban/files/etc/fail2ban/jail.local @@ -0,0 +1,22 @@ +[DEFAULT] +backend = polling +banaction = nftables +banaction_allports = nftables[type=allports] +bantime = 31m +bantime.increment = true +bantime.maxtime = 6d +bantime.overalljails = true +findtime = 20m +ignoreip = 127.0.0.0/8 ::1 + 172.16.0.0/12 + 192.168.0.0/16 + 10.0.0.0/8 + 100.64.0.0/10 +maxretry = 3 +usedns = false + +# make sure no jails are enabled by default +enabled = false + +action = %(action_)s + telegram-webhook diff --git a/bundles/fail2ban/items.py b/bundles/fail2ban/items.py new file mode 100644 index 0000000..9627587 --- /dev/null +++ b/bundles/fail2ban/items.py @@ -0,0 +1,31 @@ +if node.os != "alpine": + raise BundleError(f"{node.name}: OS {node.os} is not supported.") + +from os.path import join + +svc_openrc = { + "fail2ban": { + "enabled": True, + "running": True, + "needs": { + "pkg_apk:fail2ban", + "bundle:firewall", + "bundle:tgnotify", + }, + }, +} + +files = { +} + +repo.libs.gen.add_files_recursive( + files, + join(repo.path, "bundles", "fail2ban", "files"), + { + "triggers": { + "svc_openrc:fail2ban:restart", + }, + }, +) + +# TODO: metrics? https://github.com/hectorjsmith/fail2ban-prometheus-exporter diff --git a/bundles/fail2ban/metadata.py b/bundles/fail2ban/metadata.py new file mode 100644 index 0000000..c1a54bc --- /dev/null +++ b/bundles/fail2ban/metadata.py @@ -0,0 +1,7 @@ +defaults = { + "apk": { + "packages": { + "fail2ban": {}, + }, + }, +} |