o ;s*bn@sdZdZdZdZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlmZmZddlmZmZmZzdd lmZWn eyUdZYnwdd lmZmZd d lmZdd lmZmZddlm Z m!Z!ddl"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(e&dZ)d.ddZ*ddZ+d/ddZ,d0ddZ-ddZ.ddZ/d d!Z0Gd"d#d#eZ1d$d%Z2Gd&d'd'e3Z4Gd(d)d)e3Z5Gd*d+d+e3Z6d,d-Z7dS)1z Fail2Ban reads log file that contains password failure report and bans the corresponding IP addresses using firewall rules. This tools can test regular expressions for "fail2ban". zFail2Ban DevelopersaICopyright (c) 2004-2008 Cyril Jaquier, 2008- Fail2Ban Contributors Copyright of modifications held by their respective authors. Licensed under the GNU General Public License v2 (GPL). Written by Cyril Jaquier . Many contributions by Yaroslav O. Halchenko, Steven Hiscocks, Sergey G. Brester (sebres).GPLN) OptionParserOption) NoOptionErrorNoSectionErrorMissingSectionHeaderError) FilterSystemd)version normVersion) FilterReader)Filter FileContainer)RegexRegexException) str2LogLevelgetVerbosityFormatFormatterWithTraceBack getLoggerextractOptions PREFER_ENCfail2banFyescCs2tj||d|dd}|rd|d<dtj|S)N)useDnspython)restrflavormflagszhttps://www.debuggex.com/?)r_resolveHostTagurllibparse urlencode)sampleregex multilinerargsr)?/usr/lib/python3/dist-packages/fail2ban/client/fail2banregex.py debuggexURL?s  r+cCs t|dSN)printr(r)r)r*outputHs r/5cCs$t||kr|d|ddS|S)zReturn shortened string N...)len)slr)r)r*shortstrKs r6cCs<t|sdS|r d|}nd}t|dd|ddS)Nz|- %s z| z | z `-)r3r/join)r5headerr4r)r)r* pprint_listRs  r:ccs: z|}Wn tyYqw|sdS||Vqr,)get_nextOSErrorformatJournalEntry)flt myjournalentryr)r)r*journal_lines_gen[s   rAcGstttddSNr)r/r sysexitr.r)r)r*dumpNormVersiones rEcCsdtjdS)Nz(%s [OPTIONS] [IGNOREREGEX]r)rCargvr)r)r)r*isrGc@seZdZddZdS) _f2bOptParsercOs@d|_dtdtdtj|g|Ri|dtdS)z, Overwritten format helper with full ussage.r7zUsage:  a LOG: string a string representing a log line filename path to a log file (/var/log/auth.log) systemd-journal search systemd journal (systemd-python required), optionally with backend parameters, see `man jail.conf` for usage and examples (systemd-journal[journalflags=1]). REGEX: string a string representing a 'failregex' filter name of filter, optionally with options (sshd[mode=aggressive]) filename path to a filter file (filter.d/sshd.conf) IGNOREREGEX: string a string representing an 'ignoreregex' filename path to a filter file (filter.d/sshd.conf) z> Report bugs to https://github.com/fail2ban/fail2ban/issues )usage__doc__r format_help __copyright__)selfr(kwargsr)r)r*rLlsz_f2bOptParser.format_helpN)__name__ __module__ __qualname__rLr)r)r)r*rHks rHcCsfttdtd}|tdddddtdd d d td d ddddtddtddtddddddtdddddtddtdddtd d!d"d td#d$d%d&d'd(td)d*td+d,td-d.d/d0dd1d2td3dd0td4d5td6d7dd8d9td:d;ddd?d@dAd2tdBdCddDddEd2tdFddGd9tdHddId9tdJddKd9tdLddMd9tdNddOd9tdPdQddRd9tdSddTd9g|S)UNz%prog )rJr z-cz--configz /etc/fail2banzset alternate config directory)defaulthelpz-dz --datepatternz+set custom pattern used to match date/times)rTz --timezonez--TZstorez)set time-zone used by convert time format)actionrSrTz-ez --encodingz%File encoding. Default: system localez-rz--raw store_trueFzRaw hosts, don't resolve dnsz--usednszpDNS specified replacement of tags in regexp ('yes' - matches all form of hosts, 'no' - IP addresses only)z-Lz --maxlinesrzmaxlines for multi-line regex.)typerSrTz-mz--journalmatchzGjournalctl style matches overriding filter file. "systemd-journal" onlyz-lz --log-level log_levelcriticalz(Log level for the Fail2Ban logger to use)destrSrTz-Vcallbackz,get version in machine-readable short format)rVr\rTz-vz --verbosecountverbosezIncrease verbosity)rVr[rSrTz --verbosityz'Set numerical level of verbosity (0..4))rVr[rXrTz--verbose-datez--VDz%Verbose date patterns/regex in output)rVrTz-Dz --debuggexz-Produce debuggex.com urls for debugging therez--no-check-all store_false checkAllRegexTzDisable check for all regex'sz-oz--outoutzaSet token to print failure information only (row, id, ip, msg, host, ip4, ip6, dns, matches, ...)z--print-no-missedzDo not print any missed linesz--print-no-ignoredzDo not print any ignored linesz--print-all-matchedzPrint all matched linesz--print-all-missedz*Print all missed lines, no matter how manyz--print-all-ignoredz+Print all ignored lines, no matter how manyz-tz--log-tracebackz.Enrich log-messages with compressed tracebacksz--full-tracebackzBEither to make the tracebacks full, not compressed (as by default))rHrJr add_optionsrrintrE)pr)r)r*get_opt_parsers       6rec@sDeZdZddZddZddZddZd d Zd d Zd dZ dS) RegexStatcCsd|_||_t|_dSrB)_stats _failregexlist_ipList)rN failregexr)r)r*__init__s zRegexStat.__init__cCsd|j|j|j|jfS)Nz%s(%r) %d failed: %s) __class__rhrgrjrNr)r)r*__str__szRegexStat.__str__cCs|jd7_dSNr rgrnr)r)r*incsz RegexStat.inccC|jSr,rqrnr)r)r*getStatszRegexStat.getStatscCrsr,)rhrnr)r)r* getFailRegexruzRegexStat.getFailRegexcCs|j|dSr,)rjappend)rNvaluer)r)r*appendIPzRegexStat.appendIPcCrsr,)rjrnr)r)r* getIPListruzRegexStat.getIPListN) rPrQrRrlrorrrtrvryr{r)r)r)r*rfs rfc@s(eZdZdZddZddZddZdS) LineStatsz(Just a convenience container for stats cCsJd|_|_g|_d|_g|_d|_g|_|jr#g|_g|_ g|_ dSdSrB) testedmatched matched_linesmissed missed_linesignored ignored_linesdebuggexmatched_lines_timeextractedmissed_lines_timeextractedignored_lines_timeextractedrNoptsr)r)r*rls  zLineStats.__init__cCsd|S)NzM%(tested)d lines, %(ignored)d ignored, %(matched)d matched, %(missed)d missedr)rnr)r)r*roszLineStats.__str__cCst||r t||SdS)Nr7)hasattrgetattr)rNkeyr)r)r* __getitem__zLineStats.__getitem__N)rPrQrRrKrlrorr)r)r)r*r|s  r|c@seZdZddZddZddZddZd d Zd d Zd dZ ddZ ddZ ddZ d$ddZ ddZddZddZddZd d!Zd"d#ZdS)% Fail2banRegexcCs*|jtdd|jD||_d|_d|_d|_t|_t d|_ d|_ t |_ t |_t |_d|_t||_|jrF||jnd|_|jdurW|t|j|jra|j |j|jrj||j|jrt|j |j|j |j _!d|j _"|j#o|j$ |j _#|j$|j _%|j&|j _'d|_(dS)Ncss |] \}}d||fVqdS)_Nr)).0ovr)r)r* sz)Fail2banRegex.__init__..Frauto))__dict__updatedictitems_opts _maxlines_set_datepattern_set _journalmatch share_configr_filter_prefREMatchedri _prefREGroups _ignoreregexrh _time_elapsedr| _line_statsmaxlines setMaxLines _maxlines journalmatchsetJournalMatchshlexsplittimezonesetLogTimeZone datepatternsetDatePatternusedns setUseDnsraw returnRawHost checkFindTimer`ra ignorePending_onIgnoreRegex onIgnoreRegex_backendrr)r)r*rls<         zFail2banRegex.__init__cCs|jjs t|dSdSr,)rrar/rNliner)r)r*r/rzFail2banRegex.outputcCstd|j|S)Nz)r decode_line _encodingrr)r)r*r rzzFail2banRegex.decode_linecCs||jdS)Nignore)encoderrr)r)r* encode_line#szFail2banRegex.encode_linecCsH|js |j|d|_|dur"|d||jdfdSdSdS)NTzUse datepattern : %s : %sr )rrrr/getDatePattern)rNpatternr)r)r*r&s  zFail2banRegex.setDatePatterncCs8|js|jt|d|_|d|jdSdS)NTzUse maxlines : %d)rrrrcr/ getMaxLinesrNrr)r)r*r.s zFail2banRegex.setMaxLinescCs ||_dSr,)rrr)r)r*r4s zFail2banRegex.setJournalMatchc Csni}|}ddgt|D]}z||vr||n|d|||<Wqty-Yqw|d|dS)Nlogtyper DefinitionzReal filter options : %r) getCombinedrikeysgetrr/)rNreaderfltOptrealoptscomboptskr)r)r*_dumpRealOptions7s$ zFail2banRegex._dumpRealOptionsc Cs|dvsJ|d}|jj}d}i}|dkrgt|\}}|durgd|ddvr,|f}n ||d|df}|D]/}d|vrVtj|d krMtj||}ntj|d |}ntj|}tj|rdnd}q7|dur||jjkstj|d ksd|ddvrd|vrtj|d krtj|}tj tj|d }| d |||fn| d ||fd}tj |stj |}|r| d |t |d||j|d} d} z|dur| } n | d| } Wn"ty } zt dt| f|jr| WYd} ~ nd} ~ ww| st d|dS| |j| d|jdks2ttjkr8|| || } i} | D]}|d dkrN|d}n|d dkr\|dd}nq@z|ddkrq|D]}||j_qhn|ddkr| d}|st!}| d<|D] }|"t#|qn]|ddkr| d}|st!}| d<|D] }|"t#|qn9|ddkr|D]}|$|qn&|ddkr|D]}|%|qn|ddkr|jj&dur|'|Wq@t(y} zt d|d||| fWYd} ~ dSd} ~ wwn| d |t)|f|t#|gi} | *D]%\}} |d}t+|d!|| | D]}t,|jd"|-|.q?q-d#S)$N)failrr&r.iz.confz.local/zfilter.drz&Use %11s filter file : %s, basedir: %szUse %11s file : %szUse filter options : %rzfail2ban-regex-jail)rbasedirzWrong config file: %szERROR: failed to load filter %sFr z multi-setr1setr prefregex addfailregexaddignoreregexrrraddjournalmatchz1ERROR: Invalid value for %s (%r) read from %s: %szUse %11s line : %srz add%sRegexT)/rconfigrospathbasenamer8dirnameisfilesplitextr/isabsabspathr rread setBaseDir readexplicit Exceptionr_verboseapplyAutoOptionsr getOptionslogSysgetEffectiveLevelloggingDEBUGrconvertr prefRegexrrirwrfrrrr ValueErrorr6rsetattrrtitlerv)rNrx regextyper&rfltFilerfltNametryNamesrretereadercommands regex_valuesoptoptvalstorr)r)r* readRegexDs                    & zFail2banRegex.readRegexcCsd|_|j|dS)NT) _lineIgnoredrrr)rNidx ignoreRegexr)r)r*rszFail2banRegex._onIgnoreRegexNc Cs|jj}|jdkr|dd}t||jk}d}|_z}|j||}g}g}|D].} |jjsL| t|dk|j | d} | | | | d dsY|| q-d}q-|jjrfd|dfWS|jj r|jj } | r|jd7_|jrt|j|jkr|j| nt|j|jkr|jdWnty} z td| WYd} ~ d Sd} ~ ww|jdkr1|t|dD]j} | |jjvr0z(|jj|jjd | |jr|jj|jjd | ddd Wn tyYnw|jr |js|jj d | n || d| d |jj!d7_!|jj"d8_"q|rA||j#d |}|||pH|jfS) Nr Frr1nofailTr2 ERROR: %s)NrNr7rrI)$r_Filter__lineBufferrr3r processLinerrarwrhrrryrr hasMatchedrrrr getGroupsrr/rcrrpopindexr8 _debuggexrr_print_all_matchedrr~r processedLine)rNrdate orgLineBuffer fullBuffer is_ignoredfoundlinesrmatchr&prerbufLiner)r)r* testRegexs~        zFail2banRegex.testRegexcs|jjdvrdd}|Sdkrdd}|Sdkr"dd}|Sdvr.fd d}|Sd d lmmmd d fdd}|S)zOPrepares output- and fetch-function corresponding given '--out' option (format))idipcSs|D]}t|dqdSrp)r/rrr)r)r*_outsz+Fail2banRegex._prepaireOutput.._outmsgcSsH|D]}|ddD]}t|tsddd|D}t|q qdS)Nr1matchesr7cs|]}|VqdSr,r)rrr)r)r*r >Fail2banRegex._prepaireOutput.._out..)r isinstancerr8r/rr)r)r*rs  rowc Ss>|D]}td|d|dtdd|dDfqdS)Nz [%r, %r, %r],r rcss$|] \}}|dkr||fVqdS)rNr))rrrr)r)r*rs"r r1)r/rrrr)r)r*rs2._escOutcsg}ddi|D]7dddd}|}fdd}||d <j|d }dr;||fqt|q|D]'\}dd D]tts^d d dD|dtqMqBdS)NNLrr rr1)timedatacs4dstddgdkr|dSdd<dS)Nr,r1rr msg)r3rrnrwrapr)r*_get_msg$s z=Fail2banRegex._prepaireOutput.._out.._get_msgr) escapeValrr7csrr,r)rr)r)r*r5rr r/) ActionInforeplaceDynamicTagsrwr/rr!rr8r))rrowsticketaInfor2rr%r'r&r+r$r0r*rs(      )rraserver.actionsr%r&r')rNrr)r9r*_prepaireOutputs"40) %zFail2banRegex._prepaireOutputcCst}|jjr |}|D]}t|tr*||d|d\}}}d|d}n|d}| ds6|s7q||\}}}|jjrPt |dkrO|sO||q|r{|j j d7_ |j sz|jsi|j j |jdkrz|j j||jrz|j j|nKt |dkr|j jd7_|jr|j j||jr|j j|n(|j jd7_|js|js|j j|jdkr|j j||jr|j j||j jd7_qt||_dS)Nrr r7z #)r-rrar;r!tuplerr8rstrip startswithr3rr_print_no_ignored_print_all_ignoredrrrwr rr~r rrr_print_no_missed_print_all_missedrrr}r)rN test_linest0rarline_datetimestrippedrrr)r)r*process;sF   zFail2banRegex.processc sPj}|j|j|j|jksJ||}||d}jdk|rd|f}jr|dks6|dkr:j }nj }||d}|j ksOt d|rxgg}||fD] fdd |D}qVfd d |D}t d d |D|dStd |||fdS|j kst d|rt d d |D|dStd |||fdSdS)N_linesr z %s line(s):rr~_lines_timeextracted _print_all_cs g|] }D]}||gqqSr)r))rxy)argr)r* us z,Fail2banRegex.printLines..csLg|]"}|dd|ddt|d|djjqS)rz | r z | )rvr+rrr)ra)r'rNr)r*rNvscSg|]}|qSr)r>rrKr)r)r*rNyz?%s too many to print. Use --print-all-%s to print all %d linescSrPr)rQrRr)r)r*rN~rS)rrr}r~rrr capitalizer rhrrrr:r/) rNltypelstatsrr5r9 regexlistansbr))rMr'rNr* printLinesds:      zFail2banRegex.printLinesc sjjrdStdtdtdfdd}jjrCjj}|g}jr6jD] }|d|fq+tdd j ft ||d j }|d j }jj durtd g}jj jD]3}jsh|jr|d |j|jfjr|d|j|jjt|ddf|dt|ddfq`t |dtdjjdurtdjtdjrdjsdjsȈddS)NTr7Resultsz=======c sdg}}t|D]N\}}|}||7}|sjr(|d|d||fjrWt|rW|D]!}t|d}t d|} |d|d| |drQdpRd fq5q t d ||ft |d |S) Nrz %2d) [%d] %sr rz%a %b %d %H:%M:%S %Yz %s %s%sz (multiple regex matched)r7 %s: %d totalz" #) [# of hits] regular expression) enumeratertrrwrvr3r{r- localtimestrftimer/r:) r failregexestotalracntrkrr timeTuple timeStringrnr)r*print_failregexess*     z3Fail2banRegex.printStats..print_failregexesz %sr] Prefregex Failregex Ignoreregexz Date template hits:z[%d] %sz& # weight: %.3f (%.3f), pattern: %srz # regex: %sr&z[# of hits] date formatz Lines: %sz[processed in %.2f sec]r~rr)rrar/rrgetRegexrrrwrr:rhr dateDetector templateshitsname _verbose_dateweighttemplaterrrr rZr@rB)rNrfrragrprbrrqr)rnr* printStatssP               zFail2banRegex.printStatsccs|D]}||VqdSr,)r)rNhdlrrr)r)r*file_lines_genszFail2banRegex.file_lines_genc Csf|dd\}}|drd|_z||dsWdSt|dkr+||dds+WdSWntyE}z td|WYd}~dSd}~wwtj|rzt |d }|d ||d |j | |}Wnt y~}z t|WYd}~dSd}~ww|drt std dS|d |d |j t|\}}t di|} | |j | } |j} |d| r| | |dd| t| | }nQ|jdkrd|vr|dt|dd|g}n5|d}|dt|t|D]\} } | dkr |dn|d| dt| fq|d|d|||s1dSdS)Nrzsystemd-journalsystemdrFr1rrrbzUse log file : %szUse encoding : %sz,Error: systemd library not found. Exiting...zUse systemd journalzUse journal match : %s r rIzUse single line : %sz\nz Use multi line : %s line(s)z| ...z | %2.2s: %sz`-r7Tr,)r?rrr3rr/rrropenrruIOErrorr rsetLogEncodinggetJournalReaderrraddJournalMatchr8rArrr6r)rr^rGrs)rNr(cmd_log cmd_regexrrtrDbackendbeArgsr>r?rir5r)r)r*startsp                  zFail2banRegex.startr,)rPrQrRrlr/rrrrrrrrrr;rGrZrsrurr)r)r)r*rs$& x @;)H rc Gsdt_t}|j|\}}g}|jr|jr|d|jr%|jr%|dt |dvr0|d|rH| t j dd|dt d|js[tdtd td tdt|j|_t|jtt j}|jd krtd nd }|jrt}|jrdpd|}ntj}||t|j|t|zt |}Wn/t!y}z#|jst"tj#krtj$|ddntd|t dWYd}~nd}~ww|%|st ddSdS)NTzGERROR: --print-no-missed and --print-all-missed are mutually exclusive.zIERROR: --print-no-ignored and --print-all-ignored are mutually exclusive.)rr1z&ERROR: provide both and .rIr7z Running testsz =============r z%(levelname)-1.1s: %(message)sz %(message)sz %(tb)sz %(tbc)s)exc_infor)&r exitOnIOErrorre parse_argsprint_no_missedprint_all_missedrwprint_no_ignoredprint_all_ignoredr3 print_helprCstderrwriter8rDrar/rrYrsetLevel StreamHandlerstdoutr^ log_tracebackrfull_traceback Formatter setFormatterr addHandlerrrrrrZr) r(parserrerrorsrfmtr fail2banRegexrr)r)r*exec_command_linesR              r)Fr)r0r,)8rK __author__rM __license__getoptrrrrCr-urllib.requestr" urllib.parse urllib.erroroptparserr configparserrrrserver.filtersystemdr ImportErrorr r filterreaderr server.filterrrserver.failregexrrhelpersrrrrrrrr+r/r6r:rArErJrHreobjectrfr|rrr)r)r)r*sT        ?