fail2ban schützt owncloud hinter Reverse-Proxy

fail2ban ist eine gute Idee, eine Site, einen Service etc. gegen brute-force-Attacken von außen abzusichern. Ich habe das bei mir u.a. beim owncloud-Server gemacht, der hinter einem Reverse-Proxy arbeitet.

Problem dabei ist, dass fail2ban lokal auf dem Server laufen muss, auf dem der owncloud-Apache arbeitet und daher dort aus die IP-Nummern-Sperre aktiviert. Entweder ist das die IP des Proxy, was dann gleich die “ganze Welt” auf einmal aussperrt. Oder – wenn trusted_proxies konfiguriert ist, s.u. – dann wird zwar die Quell-IP gesperrt, das hat jedoch keine Wirkung, weil die Pakete (aus sicht des owncloud-Apache) vom Proxy und nicht von der Quell-IP kommen.

Was ist zu tun?

1. Reverse-Proxy den X-Forwarded-For-Header beibringen

mod_proxy in Apache macht das “von selber”. Siehe mod_proxy-Doku.

2. Loggen der eigentichen Quell-IP in Owncloud

Damit hinter dem Reverse-Proxy auch die wirklichen IPs und nicht die IP des Proxy geloggt wird ist noch folgendes nötig in /var/www/owncloud/config/config.php:

...
trusted_proxies' => array('192.168.41.4'),
...

2. “Intelligente” Fail2ban-Action

In /etc/fail2ban/action.d/iptables-x-forwarded-for.conf steht eine Action, die nicht nach der Quell-IP der Pakete filtert, sondern in die Pakete schaut und die filtert, in den “X-Forwarded-For” steht.

# diff /etc/fail2ban/action.d/iptables.conf  /etc/fail2ban/action.d/iptables-x-forwarded-for.conf 
41c42
< actionban = iptables -I fail2ban-<name> 1 -s <ip> -j <blocktype>
---
> actionban = iptables -I fail2ban-<name> 1 -p tcp --dport 80 -m string --algo bm --string 'X-Forwarded-For: <ip>' -j DROP
49c50
< actionunban = iptables -D fail2ban-<name> -s <ip> -j <blocktype>
---
> actionunban = iptables -D fail2ban-<name> -p tcp --dport 80 -m string --algo bm --string 'X-Forwarded-For: <ip>' -j DROP
61c62

Anhang 1: iptables-x-forwarded-for.conf

# Fail2Ban configuration file
#
# Author: Centos.Tips
# see https://centos.tips/fail2ban-behind-a-proxyload-balancer/
#
#

[INCLUDES]

before = iptables-blocktype.conf

[Definition]

# Option:  actionstart
# Notes.:  command executed once at the start of Fail2Ban.
# Values:  CMD
#
actionstart = iptables -N fail2ban-<name>
              iptables -A fail2ban-<name> -j RETURN
              iptables -I <chain> -p <protocol> --dport <port> -j fail2ban-<name>

# Option:  actionstop
# Notes.:  command executed once at the end of Fail2Ban
# Values:  CMD
#
actionstop = iptables -D <chain> -p <protocol> --dport <port> -j fail2ban-<name>
             iptables -F fail2ban-<name>
             iptables -X fail2ban-<name>

# Option:  actioncheck
# Notes.:  command executed once before each actionban command
# Values:  CMD
#
actioncheck = iptables -n -L <chain> | grep -q 'fail2ban-<name>[ \t]'

# Option:  actionban
# Notes.:  command executed when banning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
#
actionban = iptables -I fail2ban-<name> 1 -p tcp --dport 80 -m string --algo bm --string 'X-Forwarded-For: <ip>' -j DROP

# Option:  actionunban
# Notes.:  command executed when unbanning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
#
actionunban = iptables -D fail2ban-<name> -p tcp --dport 80 -m string --algo bm --string 'X-Forwarded-For: <ip>' -j DROP

[Init]

# Default name of the chain
#
name = default

# Option:  port
# Notes.:  specifies port to monitor
# Values:  [ NUM | STRING ]  Default:
#
port = http

# Option:  protocol
# Notes.:  internally used by config reader for interpolations.
# Values:  [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp

# Option:  chain
# Notes    specifies the iptables chain to which the fail2ban rules should be
#          added
# Values:  STRING  Default: INPUT
chain = INPUT

Anhang 2: Mein Jail

/etc/fail2ban/jail.conf:

[owncloud]

enabled = true
port = 80,443,39931
protocol = tcp
filter = owncloud
maxretry = 3
logpath = /var/log/syslog
action = iptables-x-forwarded-for[name = apache-proxy, port = http, protocol = tcp]
         sendmail-whois[name=LoginDetect, dest=dirk2@wor.net, sender=fail2ban-owncloudsrv@steinkopf.net, sendername="Fail2Ban"]

15 thoughts on “fail2ban schützt owncloud hinter Reverse-Proxy

  1. Hallo Dirk,
    ich möchte selbiges bei meiner Nextcloud machen. Hinter meiner Pfsense Haproxy (auf extra Hardware) als Reverse Proxy ist dann die Nextcloud. Fail2ban ist aktiv…. IP Adressen kommen auch “richtig” in der Logdatei an. https://www.c-rieger.de/nextcloud-installation-guide-ubuntu/#c06 meine Config bisher sieht so aus.
    die Datei /etc/fail2ban/action.d/iptables-x-forwarded-for.conf gibt´s in meinem fail2ban/action.d Verzeichnis nicht? Muss man die anlegen?
    Anhang 1: iptables-x-forwarded-for.conf was ist damit gemeint? Muss das auch nur in die iptables… mit rein. Du schreibst Anhang 1, dass verwirrt mich 😉
    In der Jail Config
    action = iptables-x-forwarded-for[name = apache-proxy, port = http, protocol = tcp]
    vermutlich läuft bei Dir der apache Reverse Proxy auf der gleichen Maschine, daher steht hier apache-proxy, port. Oder ist das der normale Webserver in Deiner Owncloud, bei mir ist das dann halt der Ngix
    Danke, der Horst

    1. Hallo Horst,

      freut mich soweit 🙂 Leider ist der Artikel 2 Jahre her und das Szenario läuft so bei mir gar nicht mehr: Ich benutze Nextcloud statt Owncloud (weil da m.E. von “Haus aus” mehr Sicherheit “drin” ist – z.B. auch das automatische Aussperren von IP-Adressen, um das es hier ja geht). Außerdem benutze ich bin kong als Reverse-Proxy.

      Ich versuche, Dir trotzdem zu gut ich kann, aus dem Kopf zu antworten:

      • Die Datei /etc/fail2ban/action.d/iptables-x-forwarded-for.conf musst du neu anlegen (das habe ich tatsächlich nicht gut beschrieben). Sie beschreibt die Action iptables-x-forwarded-for. D.h. was ist zu tun, um eine forwarded IP-Adresse auszusperren, wieder freizugeben etc. Auf die Action wird ja in der /etc/fail2ban/jail.conf verwiesen.
        • Sie ist sehr ähnlich zur bestehenden iptables.conf, weil sie fast das gleiche macht: Sie sperrt aber nicht die IP, von der die Pakete kommen (das wäre ja der Reverse-Proxy), sondern die ursprüngliche IP.
      • Ich wollte nicht die ganze Datei im Quelltext im laufenden Text unterbringen. Daher habe die sie in einem “Kapitel” mit dem Namen “Anhang 1”. (Ich hoffe, das beantwortet Deine Frage.)
      • Der Reverse-Proxy (ja, bei mir Apache) läuft (und lief nie) auf der selben (virtuellen) Maschine. Daher kommt ja die Schwierigkeit des Aussperrens der IP – deswegen kann auch die Action iptables nicht benutzt werden.
      • action = iptables-x-forwarded-for[name = apache-proxy, port = http, protocol = tcp]: Die Werte name, port und protocol sind die Parameter, die an die Action übergeben werden und dort bei <name>, <port> und <protocol> eingesetzt werden.

      Ich hoffe das hilft (und stimmt auch noch – wie gesagt, ist bei mir schon eine Weile her…). Bitte gib mir Bescheid.

      Dirk

  2. Danke Dirk,
    die Nextcloud Brute-force sperrt doch nie ganz für den Zeitraum? Oder kann man das nicht irgendwo in der Config anpassen? Nur an und ausschalten? Oder kann man das auch noch verändern?

    1. Also hier steht:

      If triggered, brute force protection makes requests coming from an IP on a bruteforce protected controller with the same API slower for a 24 hour period.

      Du hast recht, das ist kein völliges Sperren, reicht mir aber. Ich meine, auch irgendwo gelesen zu haben, dass es eine Bezahl-Variante gibt, wo man mehr einstellen kann – aber vielleicht täusche ich mich.

  3. Hallo Dirk,
    so sieht die Config für die Nextcloud aus, es läuft allerdings ein Nginx
    https://www.c-rieger.de/nextcloud-installation-guide-ubuntu/#c06

    Nun kann ich das ja nicht einfach so zusammenkopieren…
    und in der /etc/fail2ban/action.d/iptables-x-forwarded-for.conf spricht man nur Port 80 an. Naja, ich bin halt kein Administrator… 😉 wofür ist der Port 39931dann noch zusätzlich? Ich glaube ich lasse das lieber. Wie Du schon geschrieben hast, dass macht eigentlich Nextcloud schon fast von selber…

    Danke!

    [nextcloud]
    backend = auto
    enabled = true
    port = 80,443
    protocol = tcp
    filter = nextcloud
    maxretry = 10
    bantime = 360
    findtime = 360
    logpath = /var/nc_data/nextcloud.log
    action = iptables-x-forwarded-for[name = apache-proxy, port = http, protocol = tcp]
    [nginx-http-auth]
    enabled = true

  4. Ich weiß irgendwie nicht weiter:
    Meine Anwendung erkennt die IP aus dem X-Forwarded-For Header, der scheint also richtig gesendet zu werden.
    Selbst mit sudo iptables -I INPUT 1 -p tcp -m string --algo bm --string "192.168.192.8" -j DROP ist der Zugriff über den reverse Proxy vom gleichen Rechner weiterhin möglich. Was mache ich falsch? Muss ich ähnlich wie beim natten das forwarding im Kernel, irgendetwas anderes aktivieren?

    1. Oh, sorry, da bin ich inzwischen auch Gedanklich zu weit weg und kenne jetzt auch Deine genau Situation nicht. Hast du denn schon versucht, das Forwarding im Kernel zu aktivieren, um zu schauen, ob das etwas verändert? (sysctl net.ipv4.ip_forward ...) Aber eigentlich macht ja der Kernel beim Proxying kein Forward – schon gar nicht das Ziel-System. Ich würde jetzt nochmal nachlesen, was genau diese iptables-Regel macht bzw. machen soll und wie das funktioniert. Offenbar matcht sie bei Dir ja nicht. Vielleicht liegt es daran, dass Du im Match-String das X-Forwarded-For: weggelassen hast?

    2. Danke für die schnelle Antwort: Ja ich habe mit dem in deiner Anleitung beschriebenen Befehl angefangen und das dann immer weiter verallgemeinert und heruntergebrochen, um mögliche Fehlerquellen auszuschließen (Dass da vielleicht kein “:”, sondern ein “=” gelesen wird oder so). Verzweifelt habe ich dann aufgehört bei dem von mir geposteten Befehl. Meine Anwendung läuft auch auf Port 9000 (Ich will einen IRC Webclient “thelounge” absichern), kann das daran liegen? Die Erkennung läuft auch einwandfrei, mit “iptables -S” sehe ich, dass die Regel durch fail2ban auch eingetragen wurde. Darum vermute ich iptables als Ursache.

      Gruß

    3. Als nächstes würde ich versuchen, mit tcpdump die Pakete anzuschauen, die gefiltert werden sollen aber nicht gefiltert werden. Vielleicht hilft das bei der Frage, warum iptables nicht funktioniert wie erwartet.

    4. Hmmm das habe ich jetzt mal ausprobiert, ich bekomme folgendes am interface des servers, der die Anfrage des reverse proxy empfängt raus:
      GET / HTTP/1.1
      Connection: upgrade
      X-Forwarded-For: 192.168.192.8
      X-Forwarded-Proto: https
      Host: 10.10.100.55:9000

      Mein interface ist übrigens nicht eth0 sondern ens18. Kann das ein Problem für die DPI sein? Sorry, dass ich so doof nachfrage aber von iptables habe ich wenig Ahnung.

    5. Hm. Dann müsste eigentlich das --algo bm --string 'X-Forwarded-For: 192.168.192.8' matchen. Hast Du das genau so ausprobiert. Der Interface-Name spielt keine Rolle. Nun bin ich auch langsam am Ende meiner Ideen – so aus der Ferne…. Ah nochwas: Probier doch mal ein “ganz simples” fail2ban (also ohne Reverse-Proxy) aus, schau, ob das geht und “taste” Dich schrittweise näher an die Situation, wo es nicht geht. Vielleicht siehst Du dann, ab wo es nicht mehr geht.

    6. Ja das simple-fail2ban funktioniert eben komischerweise. Ich kann den reverse-proxy selbst sperren, dann kann halt kein Client mehr auf den Server zugreifen (ist jetzt auch aktuelles setting). Es geht nicht mehr ab dem Punkt, wo iptables in Pakete reingucken und anhand eines Strings filtern soll.

      Nun ich fahre erstmal mit dem jetzigen setting weiter, der Zeitaufwand den wir beide betreiben ist den Nutzen nicht wert. Aktuell wäre der Forwarded-For-fail2ban eine prophylaktische Maßnahme. Ich danke dir für den support 🙂

  5. Danke, deine Anleitung hat mir sehr weiter geholfen. Auch wenn mein Setup ganz anders war: Eigene PHP-Webseite, die aber falsche Logins in ein Log schreibt. Dabei schreibe ich die X-Real-IP ins Log.
    Dank der oben beschriebenen Action, die ich auf X-Real-IP umgeändert habe, funktioniert nun auch Fail2Ban.
    Merci

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert