Hi there, I am hosting a service for mainly me and also some family members. I want it to become more.

Currently the chain just as follows: interwebz <-> UDM <-> npm <-> services. The services are mostly run in VMs or LXCs, npm runs in docker, accompanied by one Adguard home instance and another AGH instance in an LXC.

I now want to add f2b to this whole chain. I’ve installed f2b in the OS which runs docker (and therefore npm) (VM1) and also in the OS of my existing service (VM2). Both VMs use Ubuntu as their OS.

What I already figured out thru testing and reading is, that f2b in VM2 acts as expected when the jail is triggered, and sets the block. But nftables/ufw don’t block connections coming from external, as they are coming thru npm. f2b sees and uses the public IP for the checks/bans.

So now I am thinking how to solve that.

  1. Keep f2b on VM2 and let it set the bans on VM1 over SSH. That’s what some people do or so I’ve read.
  2. Use f2b on VM1, let it check logs on VM2 and then set the bans. That would also be possible over SSH, I’d guess. But I didn’t read up on it yet.

So, what’s your opinion? How do you fine folks handle that in your environment? Option 2 seems to be more elegant, as it would be “at the entry” and let’s me easily add additional services later. But I don’t know, if that’s a path worth digging in to.

  • Achim :antifa:@mastodon.weindl.biz
    link
    fedilink
    arrow-up
    0
    ·
    14 hours ago

    @nibbs

    You have already found the core issue: a ban on VM2 is too late.

    VM2 does see the real client address in the HTTP logs if NPM passes X-Forwarded-For correctly, but at the network layer every connection to VM2 still originates from NPM on VM1. Therefore an nftables/UFW rule on VM2 can only block NPM — which is not exactly the intended security feature.

    For your setup, I would put the actual enforcement at the ingress point:

    • Run Fail2Ban on VM1.
    • Parse the NPM access/error logs there.
    • Let Fail2Ban add/remove bans locally on VM1.
    • Ensure NPM logs the real client IP, and only trust forwarded-IP headers from proxies you actually control.
    • Keep VM2 restricted so it accepts service traffic only from VM1/NPM where possible.

    Having Fail2Ban on VM2 execute remote firewall actions on VM1 via SSH can work, but it is basically building a small, brittle distributed ban system yourself: SSH keys, narrowly scoped sudo rules, reliable unban actions, error handling, and so on.

    Alternative:
    If you want detection from several VMs/services but enforcement centrally at NPM, CrowdSec is a more natural fit. Run agents where the relevant logs live, use a central LAPI, and run a bouncer at VM1/NPM. Then the components are designed to exchange decisions instead of hoping two independent Fail2Ban installations telepathically coordinate.

    Also: do not use set_real_ip_from 0.0.0.0/0 just to make X-Forwarded-For work. That turns a client-supplied header into an IP-spoofing API.

    #SelfHosting #ReverseProxy #Fail2Ban #CrowdSec #NginxProxyManager