fail2ban - sshd

  • Sag mal Alex, wie genau wertet fail2ban denn die Logeinträge aus? Ich habe gerade das Problem, mich selbst ausgesperrt zu haben. Danke an IPv6, damit komme ich wenigstens noch drauf.

    In der Config für den sshd-Filter stehen ja mehrere Regex-Zeilen (failregex), nach denen gesucht wird. SSHd schreibt seinerseits mehrere Logeinträge, wenn ein Login fehlerhaft war. Genau das scheint aber ein Problem zu geben.

    SSHd schreibt vier Zeilen, für EINEN Fehlversuch. In dreien davon steht die IP.

    Jul 9 06:36:14 sshd[28054]: User fundament from 188.xxx.yyy.zzz not allowed because none of user's groups are listed in AllowGroups
    Jul 9 06:36:14 sshd[28054]: input_userauth_request: invalid user fundament [preauth]
    Jul 9 06:36:16 sshd[28054]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=188.xxx.yyy.zzz user=fundament
    Jul 9 06:36:17 sshd[28054]: Failed password for invalid user fundament from 188.xxx.yyy.zzz port 60040 ssh2

    Mein fail2ban steht auf "sperren bei 3 Fehlversuchen binnen 15 Minuten".

    So, nun scheint fail2ban die drei Logeinträge mit IP aber als 3 getrennte Login-Fehler zu werten und sperrt mich weg. Dabei war es aber nur ein Fehlversuch, der eben mehrere Logeinträge erzeugte. Dachte eigentlich, dass die diversen failregex bei einem Durchlauf als EIN Fehler gewertet werden, auch wenn mehrere gleichzeitig zutreffen. Dem ist aber wohl nicht so.

    Hm, eine Idee? Ist das normal so? Wie soll man da denn fail2ban einstellen? Es gibt ja auch Fehlversuche mit nur einem Logeintrag, kommt halt drauf an, wie man es versucht. Also den Schwellenwert auf 10 zu setzen macht da nicht viel Sinn. Andere haben dann 10 Versuche und ich hätte rein rechnerisch nur 4.

    Wenn ein Mensch nicht um dich kämpft, hat er nur gewartet, dass du gehst. ;(

  • moin,
    hast du ein jail.local?

    [pure-ftpd]
    enabled = true
    port = ftp
    filter = pure-ftpd
    logpath = /var/log/syslog
    maxretry = 3

    [dovecot]
    enabled = true
    filter = dovecot
    action = iptables-multiport[name=dovecot-pop3imap, port="pop3,pop3s,imap,imaps", protocol=tcp]
    logpath = /var/log/mail.log
    maxretry = 5

    [postfix]
    enabled = true
    port = smtp
    filter = postfix
    logpath = /var/log/mail.log
    maxretry = 3

    [ssh]

    enabled = true
    port = ssh
    filter = sshd
    logpath = /var/log/auth.log
    maxretry = 5

    Das ganze wird dann auch in den Logs gefiltert. Da denke ich ist dein Problem.

    Filter.d für SSHD sieht so aus:

    # Fail2Ban filter for openssh
    #
    # If you want to protect OpenSSH from being bruteforced by password
    # authentication then get public key authentication working before disabling
    # PasswordAuthentication in sshd_config.
    #
    #
    # "Connection from <HOST> port \d+" requires LogLevel VERBOSE in sshd_config
    #

    [INCLUDES]

    # Read common prefixes. If any customizations available -- read them from
    # common.local
    before = common.conf

    [DEFAULT]

    _daemon = sshd

    # optional prefix (logged from several ssh versions) like "error: ", "error: PAM: " or "fatal: "
    __pref = (?:(?:error|fatal): (?:PAM: )?)?
    # optional suffix (logged from several ssh versions) like " [preauth]"
    __suff = (?: \[preauth\])?\s*
    __on_port_opt = (?: port \d+)?(?: on \S+(?: port \d+)?)?

    # for all possible (also future) forms of "no matching (cipher|mac|MAC|compression method|key exchange method|host key type) found",
    # see ssherr.c for all possible SSH_ERR_..._ALG_MATCH errors.
    __alg_match = (?:(?:\w+ (?!found\b)){0,2}\w+)

    [Definition]

    prefregex = ^<F-MLFID>%(__prefix_line)s</F-MLFID>%(__pref)s<F-CONTENT>.+</F-CONTENT>$

    cmnfailre = ^[aA]uthentication (?:failure|error|failed) for <F-USER>.*</F-USER> from <HOST>( via \S+)?\s*%(__suff)s$
    ^User not known to the underlying authentication module for <F-USER>.*</F-USER> from <HOST>\s*%(__suff)s$
    ^Failed \S+ for invalid user <F-USER>(?P<cond_user>\S+)|(?:(?! from ).)*?</F-USER> from <HOST>%(__on_port_opt)s(?: ssh\d*)?(?(cond_user): |(?:(?:(?! from ).)*)$)
    ^Failed \b(?!publickey)\S+ for (?P<cond_inv>invalid user )?<F-USER>(?P<cond_user>\S+)|(?(cond_inv)(?:(?! from ).)*?|[^:]+)</F-USER> from <HOST>%(__on_port_opt)s(?: ssh\d*)?(?(cond_user): |(?:(?:(?! from ).)*)$)
    ^<F-USER>ROOT</F-USER> LOGIN REFUSED.* FROM <HOST>\s*%(__suff)s$
    ^[iI](?:llegal|nvalid) user <F-USER>.*?</F-USER> from <HOST>%(__on_port_opt)s\s*$
    ^User <F-USER>.+</F-USER> from <HOST> not allowed because not listed in AllowUsers\s*%(__suff)s$
    ^User <F-USER>.+</F-USER> from <HOST> not allowed because listed in DenyUsers\s*%(__suff)s$
    ^User <F-USER>.+</F-USER> from <HOST> not allowed because not in any group\s*%(__suff)s$
    ^refused connect from \S+ \(<HOST>\)\s*%(__suff)s$
    ^Received <F-MLFFORGET>disconnect</F-MLFFORGET> from <HOST>%(__on_port_opt)s:\s*3: .*: Auth fail%(__suff)s$
    ^User <F-USER>.+</F-USER> from <HOST> not allowed because a group is listed in DenyGroups\s*%(__suff)s$
    ^User <F-USER>.+</F-USER> from <HOST> not allowed because none of user's groups are listed in AllowGroups\s*%(__suff)s$
    ^pam_unix\(sshd:auth\):\s+authentication failure;\s*logname=\S*\s*uid=\d*\s*euid=\d*\s*tty=\S*\s*ruser=<F-USER>\S*</F-USER>\s*rhost=<HOST>\s.*%(__suff)s$
    ^(error: )?maximum authentication attempts exceeded for <F-USER>.*</F-USER> from <HOST>%(__on_port_opt)s(?: ssh\d*)?%(__suff)s$
    ^User <F-USER>.+</F-USER> not allowed because account is locked%(__suff)s
    ^<F-MLFFORGET>Disconnecting</F-MLFFORGET>: Too many authentication failures(?: for <F-USER>.+?</F-USER>)?%(__suff)s
    ^<F-NOFAIL>Received <F-MLFFORGET>disconnect</F-MLFFORGET></F-NOFAIL> from <HOST>: 11:
    ^<F-NOFAIL>Connection <F-MLFFORGET>closed</F-MLFFORGET></F-NOFAIL> by <HOST>%(__suff)s$
    ^<F-MLFFORGET><F-NOFAIL>Accepted publickey</F-NOFAIL></F-MLFFORGET> for \S+ from <HOST>(?:\s|$)

    mdre-normal =

    mdre-ddos = ^Did not receive identification string from <HOST>%(__suff)s$
    ^Connection <F-MLFFORGET>reset</F-MLFFORGET> by <HOST>%(__on_port_opt)s%(__suff)s
    ^<F-NOFAIL>SSH: Server;Ltype:</F-NOFAIL> (?:Authname|Version|Kex);Remote: <HOST>-\d+;[A-Z]\w+:
    ^Read from socket failed: Connection <F-MLFFORGET>reset</F-MLFFORGET> by peer%(__suff)s

    mdre-extra = ^Received <F-MLFFORGET>disconnect</F-MLFFORGET> from <HOST>%(__on_port_opt)s:\s*14: No supported authentication methods available%(__suff)s$
    ^Unable to negotiate with <HOST>%(__on_port_opt)s: no matching <__alg_match> found.
    ^Unable to negotiate a <__alg_match>%(__suff)s$
    ^no matching <__alg_match> found:

    mdre-aggressive = %(mdre-ddos)s
    %(mdre-extra)s

    cfooterre = ^<F-NOFAIL>Connection from</F-NOFAIL> <HOST>

    failregex = %(cmnfailre)s
    <mdre-<mode>>
    %(cfooterre)s

    # Parameter "mode": normal (default), ddos, extra or aggressive (combines all)
    # Usage example (for jail.local):
    # [sshd]
    # mode = extra
    # # or another jail (rewrite filter parameters of jail):
    # [sshd-aggressive]
    # filter = sshd[mode=aggressive]
    #
    mode = normal

    #filter = sshd[mode=aggressive]

    ignoreregex =

    maxlines = 1

    journalmatch = _SYSTEMD_UNIT=sshd.service + _COMM=sshd

    datepattern = {^LN-BEG}

    # DEV Notes:
    #
    # "Failed \S+ for .*? from <HOST>..." failregex uses non-greedy catch-all because
    # it is coming before use of <HOST> which is not hard-anchored at the end as well,
    # and later catch-all's could contain user-provided input, which need to be greedily
    # matched away first.
    #
    # Author: Cyril Jaquier, Yaroslav Halchenko, Petr Voralek, Daniel Black and Sergey Brester aka sebres
    # Rewritten using prefregex (and introduced "mode" parameter) by Serg G. Brester.

    wenn etwas möglich erscheint mach ich das, wenn das nicht klappt gehts ans unmögliche und ansonsten das undenkbare.

    - nun stolz rauchfrei - Ich denke also Bing ich!

    Support 24h Bereitschaft 0173 6107465 - NUR Für Kunden von SEO NW!

  • Ja Alex, genau das gleiche habe ich auch, das ist Debian-Default. Einziger Unterschied ist bei mir nur "maxretry = 3". Und Du hast auch die mehreren failregex drinnen, genauso wie ich. Was passiert bei Dir denn, wenn es zwei Fehlversuche gibt bzw. welche Logs werden genau geschrieben? Wenn das die gleichen wie bei mir sind, dann müsste der Dich bereits bei 2 Fehlversuchen wegsperren, denn dann sind 2x 3 Logs mit IP vorhanden und 5 Retry somit überschritten.

    Das einzige, was ich mir vorstellen könnte, wenn dem bei Dir nicht so sein sollte ist das "maxlines". Das steht bei mir auf 10. Wobei das aber eigentlich eine Art Cache ist um nicht jede Zeile einzeln lesen zu müssen.

    Wenn ein Mensch nicht um dich kämpft, hat er nur gewartet, dass du gehst. ;(

  • Genau genommen greifen diese 3 Rules:

    ^Failed \S+ for invalid user <F-USER>(?P<cond_user>\S+)|(?:(?! from ).)*?</F-USER> from <HOST>%(__on_port_opt)s(?: ssh\d*)?(?(cond_user): |(?:(?:(?! from ).)*)$)

    ^User <F-USER>.+</F-USER> from <HOST> not allowed because not listed in AllowUsers\s*%(__suff)s$

    ^pam_unix\(sshd:auth\):\s+authentication failure;\s*logname=\S*\s*uid=\d*\s*euid=\d*\s*tty=\S*\s*ruser=<F-USER>\S*</F-USER>\s*rhost=<HOST>\s.*%(__suff)s$

    Und das eben auf die 4 Log-Zeilen. Somit "drei Treffer". Und das ist doof :wall:

    Wenn ein Mensch nicht um dich kämpft, hat er nur gewartet, dass du gehst. ;(