Grails-Applikation mit Fail2ban schützen

von Manuel Breitfeld

Fail2ban [1] ist ein Tool, welches Log-Files nach bestimmten Mustern scannt und abhängig von den definierten Filtern IPs für eine gewisse Zeit sperrt. Ein typisches Anwendungsszenario für Fail2ban ist beispielsweise das Absichern des SSH-Servers: Hat die gleiche IP innerhalb von 10 Minuten eine gewisse Anzahl an fehlgeschlagenen Logins überschritten, wird sie für eine bestimmte Zeit gesperrt. Damit erhält man nicht nur mehr Sicherheit - auch die Log-Files werden übersichtlicher, da sie nicht mit tausenden von fehlgeschlagenen Logins überfüllt werden.

Die eigene Grails-Applikation mit Fail2Ban schützen

Im Folgenden möchte ich zeigen, wie einfach und schnell die eigene Grails-Applikation mit Fail2Ban geschützt werden kann. Wir verwenden das SpringSecurity Plugin [2] und wollen eine IP dann sperren, wenn von ihr 5 fehlgeschlagene Logins binnen einer Minute ausgingen. 

SpringSecurity AuthenticationFailureEvent

In Config.groovy definieren wir den Aufruf zu unserem Logger: LoginUtils.logFailedLogin()

grails.plugins.springsecurity.useSecurityEventListener = true
grails {
    plugins {
        springsecurity {
            onAbstractAuthenticationFailureEvent  = { e, appCtx ->
                LoginUtils.logFailedLogin()
                return true
            }
        }
    }
}

Wie geloggt werden soll, definieren wir ebenfalls in der Config.groovy: 

log4j = {
    appenders {
        rollingFile name: "failedLoginsFile", maxFileSize: "7MB", 'append': true, file: "/var/log/exensio-demoapp/failedlogins.log",  layout: pattern(conversionPattern: '%d{yyyy-MM-dd HH:mm:ss,SSS} %p %c{2} %m%n')
    }

    warn failedLoginsFile: 'com.exensio.utils.LoginUtils'
}

Der Logger sieht dabei wie folgt aus: 

class LoginUtils {
    private static final log = LogFactory.getLog(this)

    def static logFailedLogin() {
        GrailsWebRequest request = RequestContextHolder.currentRequestAttributes()
        def ip = getRemoteAddress(request)
        log.warn("Failed login attempt for IP: ${ip}")
    }

    private static getRemoteAddress(GrailsWebRequest request)  {
        def retVal = request.getRequest().getRemoteAddr()
        // If you're application is behind a proxy, you may have to call
        // a: request.getRequest().getHeader("X-Forwarded-For")
        // b: request.getRequest().getHeader("Client-IP")
        return retVal
    }
}

Fail2Ban-Installation

Unter Debian/Ubuntu kann Fail2Ban einfach über das Paketmanagement installiert werden. Das geht beispielsweise so:

sudo aptitude install fail2ban

Fail2Ban-Konfiguration

Das Kernstück der Fail2Ban-Konfiguration steckt in der Datei jail.conf. In ihr werden die unterschiedlichen Dienste, sprich Log-Files, definiert, die zu überwachen sind. In unserem Fall sieht der Abschnitt wie folgt aus:

[exensio-demoapp]
enabled = true
port = 8080
filter = exensio-demoapp
logpath  = /var/log/exensio-demoapp/failedlogins.log
maxretry = 5
bantime = 600
findtime = 60

Die Konfigurationen im Einzelnen:

  • enabled: Gibt an, ob der Filter überhaupt genutzt werden soll
  • port: Gibt an, für welchen Port die IP gesperrt werden soll. In unserem Fall läuft die Grails-Applikation auf 8080.
  • filter: Gibt den Namen des Filters an, siehe nächster Abschnitt
  • logpath: Der Pfad zur Log-Datei
  • maxretry: Die Anzahl an fehlgeschlagenen Logins
  • bantime: Die Zeit in Sekunden, für die eine IP gesperrt werden soll
  • findtime: Die Zeit in Sekunden, in der die fehlgeschlagenen Logins erfolgen müssen. In unserem Fall müssen 5 Fehl-Logins innerhalb von 60 Sekunden vorkommen.

Dabei gibt das in eckigen Klammern geschriebene [exensio-demoapp] an, um welchen Filter es sich handelt. Ein Filter definiert, wie das Muster eines fehlgeschlagenen Logins aussieht. Nach unserem Beispiel in der Methode logFailedLogin() aus der Grails-Applikation lautet der Pseudo Reguläre Ausdruck:

[Definition]
failregex = Failed login attempt for IP: <host>
ignoreregex = 
</host>

Die Datei kopieren wir in das filter.d-Verzeichnis von fail2ban, zum Beispiel unter dem Namen exensio-demoapp.conf. 

Fail2Ban-Log überprüfen

Das Fail2Ban-Log-File unter /var/log/fail2ban.log registriert alle gebannten IPs und den Zeitpunkt, an welchem sie wieder freigeschalten wurden. 

2012-05-07 08:28:35,427 fail2ban.jail   : INFO   Creating new jail 'exensio-demoapp'
2012-05-07 08:28:35,427 fail2ban.jail   : INFO   Jail 'exensio-demoapp' uses poller
2012-05-07 08:28:35,438 fail2ban.filter : INFO   Added logfile = /var/log/exensio-demoapp/failedlogins.log
2012-05-07 08:28:35,439 fail2ban.filter : INFO   Set maxRetry = 5
2012-05-07 08:28:35,440 fail2ban.filter : INFO   Set findtime = 60
2012-05-07 08:28:35,440 fail2ban.actions: INFO   Set banTime = 600
2012-05-07 08:28:35,446 fail2ban.jail   : INFO   Jail 'exensio-demoapp' started
2012-05-07 08:28:45,458 fail2ban.actions: WARNING [exensio-demoapp] Ban 192.168.11.30
2012-05-07 08:38:45,466 fail2ban.actions: WARNING [exensio-demoapp] Unban 192.168.11.30

Fazit

Fail2Ban ist ein einfaches Tool, um Dienste zusätzlich zu schützen und Log-Files übersichtlich zu halten. Es kann in seiner Standard-Konfiguration verwendet werden, um populäre Applikationen wie SSH, Apache, Tomcat, Courier-Imap oder zum Beispiel FTP-Server wie ProFTP oder PureFTP zu sichern. Wie in diesem Beitrag gezeigt wurde, lässt sich darüber hinaus mit wenig Aufwand auch die eigene Grails-Applikation absichern.
Bei der Konfiguration ist jedoch zu beachten, dass eine IP in großen Unternehmen für viele Mitarbeiter gleich ist und so die Anzahl von 'maxRetry' nicht zu klein gewählt werden sollte. Ansonsten wird das ganze Unternehmen für einige Zeit ausgesperrt. 

Kategorien: GrailsSpring

Zurück