Öffentlichen Port absichern

Started by srvmr, September 04, 2025, 12:11:11 AM

Previous topic - Next topic
September 04, 2025, 12:11:11 AM Last Edit: September 04, 2025, 12:49:51 AM by srvmr
Hallo in die Runde!

Ich bin seit Julei OPNsense-Nutzer und habe vorher Niemals eine Firewall verwaltet.
Seitdem habe ich mein Repertoire extrem erweitert.
Trotzdem bitte ich ggf. um Zaunpfähle, dir mir die Welt bedeuten!


Was möchte ich Erreichen und Warum?

1.: Präambel

Mein Modem (Fritz.Box) reicht Port 80, 443 & einen WireGuard-Port an meine OPNsense weiter.
Das sollte nun an meinem HAProxy ankommen.
Für die öffentlichen Dinge hört dieser Proxy-Server an der IP 192.168.0.2/32 (network netmask 23).
Dienste für meine VPN-Teilnehmer werden vom gleichen Proxy über (virtuelle IP) 192.168.0.3 bedient.
Das Handling der Domains übernimmt Unbound DNS + die Records bei NetCup GmbH - Anyhow:

Das funktioniert ganz gut, aber mein einziger, anderer Server war ein Raspberry Pi, den ich vor ~zehn Jahren mit Debian aufgesetzt habe.
Vermutlich übersehe ich Dinge.
Ich benutze Alles _from Scratch_, da diese Sachen eine Lerneinheit sind.

Dort hatte ich die ähnlichen Freigaben auf der gleichen Fritz.box aktiv.
Alles Was ankam, landete auf meinem lighttpd-Proxy.

Dort habe ich dann fail2ban rüber geworfen, und ich fühlte mich sicher.

2.: Was möchte ich Erreichen (und mini-Warum)?

Meine OPNsense zeigt mir seit Gestern in der LiveView, dass mindestens 100 vers. IPs versuchen im Sekundentakt 192.168.0.2:443 zu erreichen.
Die IPs wechseln sich ab, tauchen aber immer wieder auf.
Nun habe ich Angst, dass ich die Daten meiner VPN-Teilnehmer riskiere.
Wenn ich selber, über eine fremde Internet-Verbindung, meine einziges, öffentliches Frontend mit einem falschen Pfad aufrufe (oder über meine statische IP, auch ein Grund Alles sauber zu halten), bekomme ich den HTTP Response Code 503.
Was bedeutet der nun effektiv für mich?

Meine OPNSense ist eine Mini-DMZ als KVM VM.
Ich möchte weder CPU noch Speicher unnötig auslasten.
Das IP-Bannen hat mir damals Sicherheit gegeben (mental).
Ich sehe sowenige HAProxy-*.log-Einträge (shell und UI):
Nur meine WireGuard, LAN-Clients und gelegentlich ein paar durchgehende Anfragen auf mein Frontend:

2025-09-03T23:18:20    Informational    haproxy    Connect from 192.168.1.20:50528 to 192.168.0.3:443 (intranet-services/HTTP)     
2025-09-03T23:18:19    Informational    haproxy    185.177.72.106:36804 [03/Sep/2025:23:18:19.488] public_HTTP_frontend-redirect public_HTTP_frontend-redirect/<NOSRV> 0/-1/-1/-1/0 301 111 - - LR-- 4/1/0/0/0 0/0 "GET /admin/server_info.php HTTP/1.1"     
2025-09-03T23:17:49    Informational    haproxy    185.177.72.106:33100 [03/Sep/2025:23:17:49.464] public_HTTP_frontend-redirect public_HTTP_frontend-redirect/<NOSRV> 0/-1/-1/-1/0 301 116 - - LR-- 5/1/0/0/0 0/0 "GET /static/js/main.e85f7a37.js HTTP/1.1"     
2025-09-03T23:17:32    Informational    haproxy    Connect from 10.0.20.105:47206 to 192.168.0.3:443 (intranet-services/HTTP)

Allerdings werden die durchgehenden Anfragen aus Extern (keine trusted Clients) immer mehr!

Ich würde gerne:

1. Sehen, welche IP welchen Pfad (und Host/Domain) über :443 angefragt hat. Mit tcpdump bekomme ich nur Netzwerk-Pakete; keine Path-Segmente.
2. Bannen, wer mich scraped. Wer - inzwischen - >10000 Anfragen durchgeführt hat, soll IP gebannt - oder besser, still fallengelassen - werden. Dafür habe ich CloudSec installiert, aber es wurde _Nichts_ gemonitored oder gemeldet.
3. Verstehen, wie die ACL-Regeln auf dem Frontend zusammenspielen (bspw. Drei Regeln: Mit And, None und Or).

Auf der Firewall werden mir externe IP-Adressen [4+6 (kein IPv6-Listener!)] als PASS angezeigt.
Diese sollte nun (IPv4) beim HAproxy ankommen.

Ich versuche die 503-Rückmeldungen zu zählen, HTTP rates & HTTP error rates zu zählen, die HAProxy-Logs für ein besseren Verständnis zu sichten.
Aber davon konnte ich Nichts erreichen.

3.: Warum?

Ich verstehe das Logging in OPNsense nicht.
Vorinstalliert bei mir ist syslog & syslog-ng.
Es gibt 24 verschiedene Logmöglichkeiten in HAProxy, aber local0 ist der Weg.
Die Config's davon Sehen für _mich_ gut aus.
Aber wie kann ich die Sachen Sichten?

Wie verbanne ich diese Assis für eine Zeit-lang, mich abzusammeln und (&!) darf ich mich sicher fühlen?

Hiermit mein relevantes Frontend + Präambel.
Die Config ist 50% eingekürzt; Aber Nichts Relevantes.
Ich hoffte, wegen des Frontends *nextcloud_PUBLIC_shares* bereits Zugriff auf diese, in der Firewall durchgelassenen, Abfragen zu haben.
Aber Nöschts.

#
# Automatically generated configuration.
# Do not edit this file manually.
#

global
    uid                         80
    gid                         80
    chroot                      /var/haproxy
    daemon
    stats                       socket /var/run/haproxy.socket group proxy mode 775 level admin
    nbthread                    1
    hard-stop-after             60s
    no strict-limits
    httpclient.resolvers.prefer   ipv4
    tune.ssl.default-dh-param   4096
    spread-checks               2
    tune.bufsize                16384
    tune.lua.maxmem             0
    log                         /var/run/log local0 info
    lua-prepend-path            /tmp/haproxy/lua/?.lua
cache opnsense-haproxy-cache
    total-max-size 4
    max-age 60
    process-vary off

defaults
    log     global
    option redispatch -1
    timeout client 30s
    timeout connect 30s
    timeout server 30s
    retries 3
    default-server init-addr last,libc

# autogenerated entries for ACLs


# autogenerated entries for config in backends/frontends

# autogenerated entries for stats




# Frontend: intranet-services ()
frontend intranet-services
    http-response set-header Strict-Transport-Security "max-age=15768000"
    bind 192.168.0.3:443 name 192.168.0.3:443 ssl prefer-client-ciphers ssl-min-ver TLSv1.2 ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256 ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 no-alpn crt-list /tmp/haproxy/ssl/68a47835254d57.84435535.certlist
    mode http
    option http-keep-alive

    # logging options
    # ACL: nc_caldav
    acl acl_68a476959ef0d3.68182446 path_end -i /.well-known/caldav
    # ACL: nextcloud
    acl acl_68a47673c491f9.26985569 hdr(host) -i XXXXXXXX.de
    # ACL: nc_carddav
    acl acl_68a476ab3bcf77.90676780 path_end -i /.well-known/carddav
    # ACL: nc_nodeinfo
    acl acl_68a476ce1f2780.78624769 path /.well-known/nodeinfo
    # ACL: nc_webfinger
    acl acl_68a476e9b94c54.76139249 path /.well-known/webfinger
    # ACL: nc_shares
    acl acl_68a49a46486474.25653534 path_beg -i /s/
    # ACL: gogs
    acl acl_68ace820815617.14637270 hdr(host) -i XXXXXXXXX.de
    # ACL: registry
    acl acl_68b5acab49af84.64595841 hdr(host) -i XXXXXXXXXXXXXX.de

    # ACTION: nc_caldav
    http-request redirect code 301 location /remote.php/dav if acl_68a476959ef0d3.68182446 acl_68a47673c491f9.26985569
    # ACTION: nc_carddav
    http-request redirect code 301 location /remote.php/dav if acl_68a476ab3bcf77.90676780 acl_68a47673c491f9.26985569
    # ACTION: nc_nodeinfo redirect
    http-request redirect code 301 location /index.php/%[capture.req.uri] if acl_68a476ce1f2780.78624769 acl_68a47673c491f9.26985569
    # ACTION: nc_webfinger redirect
    http-request redirect code 301 location /index.php/%[capture.req.uri] if acl_68a476e9b94c54.76139249 acl_68a47673c491f9.26985569
    # ACTION: nc_shares
    use_backend nextcloud if acl_68a49a46486474.25653534 acl_68a47673c491f9.26985569
    # ACTION: gogs
    use_backend Gogs if acl_68ace820815617.14637270
    # ACTION: nextcloud
    use_backend nextcloud if acl_68a47673c491f9.26985569

# Frontend: HTTP_frontend-redirect ()
frontend HTTP_frontend-redirect
    bind 192.168.0.3:80 name 192.168.0.3:80
    mode http
    option http-keep-alive

    # logging options
    # ACL: no_SSL-connection
    acl acl_6887d1b9bf21b3.95791483 ssl_fc

    # ACTION: redirect_https
    http-request redirect scheme https code 301 if !acl_6887d1b9bf21b3.95791483

# Frontend: nextcloud_PUBLIC_shares ()
frontend nextcloud_PUBLIC_shares
    bind 192.168.0.2:443 name 192.168.0.2:443 ssl prefer-client-ciphers ssl-min-ver TLSv1.2 ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256 ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 no-alpn crt-list /tmp/haproxy/ssl/68a49d2a7e20e4.88467887.certlist
    mode http
    option http-keep-alive

    # logging options
    option httplog
    # ACL: nc_shares
    acl acl_68a49a46486474.25653534 path_beg -i /s/
    # ACL: nextcloud
    acl acl_68a47673c491f9.26985569 hdr(host) -i XXXXXXXX.de

    # ACTION: nc_shares
    use_backend nextcloud if acl_68a49a46486474.25653534 acl_68a47673c491f9.26985569

# Frontend: public_HTTP_frontend-redirect ()
frontend public_HTTP_frontend-redirect
    bind 192.168.0.2:80 name 192.168.0.2:80
    mode http
    option http-keep-alive
    # stickiness
    stick-table type ip size 50k expire 30m  # Edit: Überbleipsel vom Rumspielen. Ich kann jederzeit zurück-snapshotten; Bin also zum Spielen bereit.
    tcp-request connection track-sc0 src
    # logging options
    option httplog
    # ACL: no_SSL-connection
    acl acl_6887d1b9bf21b3.95791483 ssl_fc

    # ACTION: redirect_https
    http-request redirect scheme https code 301 if !acl_6887d1b9bf21b3.95791483

# Backend: nextcloud ()
backend nextcloud
    # health checking is DISABLED
    mode http
    balance source
    # stickiness
    stick-table type ip size 1m expire 30m store http_err_cnt,http_err_rate(10s)
    stick on src
    http-reuse safe
    option forwardfor
    server nextcloud 10.0.30.50:8443 ssl verify none

# statistics are DISABLED

Danke für's Lesen.
Danke für Anmerkungen.
Danke für Antworten, oder Ähnliches.

Ich frage mich gerade ob du wirklich den HA-Proxy für deinen WEB-Server brauchst oder nicht einfacher mit einer Port-Nat besser fährst. Opensens und HA-Proxy sind zwei große Pakete und da du gerade anfängst machst du es dir warscheinlich unnötig kopliziert.

Durch den Einsatz der Fritzbox vor der OpnSense funktionieren einige Dinger auch nicht oder werden deutlich komplizierter, darunter:

  • GeoIP-Blocking
  • Ausstellen von Zertifikaten
  • Nutzung von IPv6 und IPv4 alternativ
  • DynDNS

Das gilt insbesondere dann, wenn man Dienste exponieren will. Siehe auch:

https://forum.opnsense.org/index.php?topic=39556

und:

https://forum.opnsense.org/index.php?topic=37155

Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, ZTE F6005

1100 down / 800 up, Bufferbloat A+

September 04, 2025, 10:30:24 PM #3 Last Edit: September 04, 2025, 10:32:16 PM by srvmr
@osmom: Ich hab noch weitere Services, die für die VPN-Clients da sind, über den HAProxy eingerichtet.
Das aktuelle Frontend ist gerade nur für öffentliche Verlinkungen der Nextcloud Nutzer.

@meyergru: Danke für die Hinweise.
Im zweiten Artikel, bei dem du über das Betreiben öffentlicher Services schreibst, habe ich die Empfehlung für ein default Backend mit fake Zertifikat herausgelesen. Wolltest du mich darauf stubsen?

Erstmal: Danke!

Bevor ich ein Default Backend einrichte, wollte ich inspizieren, ob der aktuelle Status Quo bei mir nicht ausreichend ist.
Die OPNsense läuft gemütlich, trotz der tausenden Anfragen, vor sich her.
Aber Vorsicht ist besser als Nachsicht, gerade bei persönlichen Daten und Sicherheit.

Ich wundere mich halt, dass HAProxy HTTP Return Codes von 503 zurückliefert, aber Nichts loggt.
Mein Wunsch wäre es, dass ich für die IP (die sehe ich auch korrekt durchgereicht) die Anzahl an "unerlaubten" Path-Segmenten, bzw. 503 Returns zähle.
Und dann die Anfragen still und heimlich fallen lasse.
Alternativ wäre eben auch ein IP-Bann okay, dass die OPNsense diese für eine Zeit ausschließt, wenn die über mein WAN reinkommen.

Und nochmal explizit die Frage: Bin ich _jetzt gerade_ bereits geschützt?

Das Fake-Zertifikat würde ich nur nutzen, wenn es nicht besser geht, nämlich mit Wildcard-Zertifikaten. Das Fake-Zertifikat wird nur gezeigt, wenn jemand nicht mit dem korrekten Namen anfragt, also z.B. bei einem Portscan. Aber auch die "echten" Zertifikate können Infos offenlegen, siehe hier.

Was die HAproxy-Logs angeht: Siehst Du überhaupt Einträge? Hast Du die Logs-Levels alle in der Übersicht selektiert? Sind in HAProxy alle Logs auf den richtigen Log-Level eingerichtet ("Services: HAProxy: Settings -> Logging")?

Ich meine mich zu erinnern, dass mit irgendeinem Update ein Fehler eingebaut wurde, bei dem die Logs für manche Plugins nicht mehr korrekt bei Installation eingetragen wurden. Schau mal, ob in /usr/local/etc/syslog-ng.conf.d/syslog-ng-local.conf dieser Abschnitt steht:

###################################################################
# Local syslog-ng configuration filter definition [haproxy].
###################################################################
filter f_local_haproxy {
    program("haproxy");
};
destination d_local_haproxy {
    file(
        "/var/log/haproxy/haproxy_${YEAR}${MONTH}${DAY}.log"
        create-dirs(yes)
        flags(syslog-protocol)
    );
};
log {
    source(s_all);
    filter(f_local_haproxy);
    destination(d_local_haproxy);
};

Falls nicht, trag es nach, starte OpnSense neu und schau nochmal. Wenn es so sein sollte, mach bitte auf Github einen Bug Request auf.


Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, ZTE F6005

1100 down / 800 up, Bufferbloat A+

Quote from: meyergru on September 04, 2025, 10:48:07 PMDas Fake-Zertifikat würde ich nur nutzen, wenn es nicht besser geht, nämlich mit Wildcard-Zertifikaten. Das Fake-Zertifikat wird nur gezeigt, wenn jemand nicht mit dem korrekten Namen anfragt, also z.B. bei einem Portscan. Aber auch die "echten" Zertifikate können Infos offenlegen, siehe hier.

Vielen Dank für deine Erklärung & Verlinkung. Hab' zum Start schon viele deiner Beiträge gelesen und als Grundlage für Nachforschungen genutzt.
DNS-01 Challenge war mit den bestehenden Beiträgen einfach einzurichten; Dabei wusste ich gar nicht von den Vorzügen.
Ganz sauber ist es nicht, da ich zuerst die Firewall erreichbar haben wollte (Ich war naiv); Dann lernte ich von WireGuard und habe die Subdomäne eingestampft.

Quote from: meyergru on September 04, 2025, 10:48:07 PMWas die HAproxy-Logs angeht: Siehst Du überhaupt Einträge? Hast Du die Logs-Levels alle in der Übersicht selektiert? Sind in HAProxy alle Logs auf den richtigen Log-Level eingerichtet ("Services: HAProxy: Settings -> Logging")?

Geloggt wird Alles ab Info, syslog local0 gegen 127.0.0.1.
Wie in meinem initialen Post erwähnt: Geloggt wird nur, was an einem gültigen Frontend ankommt.
Das irritiert mich, da HAProxy ja arbeitet und 503 zurückmeldet.

Quote from: meyergru on September 04, 2025, 10:48:07 PMIch meine mich zu erinnern, dass mit irgendeinem Update ein Fehler eingebaut wurde, bei dem die Logs für manche Plugins nicht mehr korrekt bei Installation eingetragen wurden. Schau mal, ob in /usr/local/etc/syslog-ng.conf.d/syslog-ng-local.conf dieser Abschnitt steht:

Das ist nicht der Fall; Der Eintrag existiert.

Die Bot-Farm ist inzwischen weitergezogen & OPNsense + HAProxy haben Mühelos die Tür gemacht.
Als Sie die einzige, gültige Freigabe (nextcloud-domain + ^/s/.*) gefunden haben, konnte ich sehen, was versucht wurde anzufragen (Sicherheitslücken, nehme ich an. Siehe ersten Post).

Ich fühle mich schon sicherer und bin ganz stolz auf meine neue Firewall!

Wie kann ich nach vermehrten http-response 503 Meldungen meines HAProxies, die anfragende Person für eine Zeit lang verbannen?
Ich könnte jetzt ein Default Backend erstellen und die Sachen dort fallen lassen, nach X Anfragen.
Aber was soll das Backend überhaupt liefern?
Ist das vielleicht sogar für meine Box aufwändiger, als einfach den Scan zu ertragen?
Oder gibt es dort einen anderen Kniff, den Load Balancer strenger zu gestalten?

In der HAProxy Dokumentation habe ich nicht viel entnehmen können.
Um Regeln wie hier aufzustellen, würde ich halt gerne die entsprechenden Anfragen an den Load Balancer Teil sehen wollen..

September 05, 2025, 12:57:07 AM #6 Last Edit: September 05, 2025, 09:14:45 AM by meyergru
Also erstmal müsste man gucken, was übrhaupt die 503er Antwort auslöst. Das könnte eventuell auch ein Port-Scan sein, der keinen gültigen TLS-Handshake macht, dann gäbe es nichts zu tun. Du kannst natürlich so etwas wie Crowdsec, oder Suricata einsetzen und darauf hoffen, dass der Angriff dort erkannt wird, aber das kann auch nach hinten losgehen. Zunächst sollte man das immmer mal im IDS und nicht IPS-Modus laufen lassen, um False Positives auszuschließen.

Oft genug gehen solche Zugriffe von bekannten Scannern aus, die man per Blockliste draußen halten halten oder mit Geoip (oder bietest Du Deine Dienste in China oder Indien an?). Man kann über Firewall Aliases auch ASNs aussperren und Blocklisten (z.B. FireHol oder Blocklist.de) nutzen. Aber wie gesagt: Wenn Deine Fritzbox als Router fungiert, kommen die Angreifer mindestens mal so weit durch.

Auf dem HAproxy werden an sich schon zu viele Ressourcen verbraucht, wenn Du eh schon weißt, dass es sich um Angreifer handelt, die weithin bekannt sind.
Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, ZTE F6005

1100 down / 800 up, Bufferbloat A+

Quote from: meyergru on September 05, 2025, 12:57:07 AMAlso erstmal müsste man gucken, was übrhaupt die 503er Antwort auslöst. Das könnte eventuell auch ein Port-Scan sein, der keinen gültigen TLS-Handshake macht, dann gäbe es nichts zu tun. Du kannst natürlich so etwas wie Crowdsec, oder Suricata einsetzen und darauf hoffen, dass der Angriff dort erkannt wird, aber das kann auch nach hinten losgehen. Zunächst sollte man das immmer mal im IDS und nicht IPS-Modus laufen lassen, um False Positives auszuschließen.

Oft genug gehen solche Zugriffe von bekannten Scannern aus, die man per Blockliste herausbekommt oder mit Geoip (oder bietest Du Deine Dienste in China oder Indien an?). Man kann über Firewall Aliases auch ASNs aussperren und Blocklisten (z.B. FireHol oder Blocklist.de) nutzen. Aber wie gesagt: Wenn Deine Fritzbox als Router fungiert, kommen die Angreifer mindestens mal so weit durch.

Auf dem HAproxy werden an sich schon zu viele Ressourcen verbraucht, wenn Du eh schon weiß, dass es sich um Angreifer handelt, die weithin bekannt sind.


Danke für Rat, Einschätzung und Info!
Damit habe ich genug Ansätze, um erstmal zu Recherchieren & behandle meinen aktuellen Status als angehend sicher :).