Fail2Ban For Dynamic DNS Update with FirewallD

Folks,

Long time OpenSUSE user, currently moving to Leap 15.

**1. GOAL: **Move to Fail2Ban + FirewallD combo for secure VPS instance login from any location.

2. SITUATION: From home office (or anywhere with additional configuration) update a dynamic DNS service provider with new local IP address. Cloud instance firewall is updated by whitelisting the new IP associated with the fixed domain at the DNS service. This is the ONLY access to the VPS. Typically one, or sometimes a few colleagues, will be able to access. Access is via SSH with a key etc., typically initiated from Windows via PuTTY etc. Dynamic IP is communicated to the DNS service by local host firewall (IPCop or Pfsense etc.)

3. CURRENT SOLUTION SUCCESS: Using CFS Firewall (“ConfigServer and Security Firewall”) on OpenSUSE 42 series, which has a very easy-to-understand dynamic DNS configuration, which updates the inbound whitelist. The update through the whole chain happens in seconds on any IP address change. Has never failed in three years. And system seems otherwise locked down.

4. NEW LEAP DEPLOYMENT: CFS cannot be easily deployed on new OpenSUSE Leap version (long story, CFS not updated for configuration details). Therefore, why no go with standard out-of-the-box?

5. SUCCESS OF NEW DEPLOYMENT: firewalld is deployed, with a hard-coded single IP address in the trusted zone, and the updated new port number. The login via SSH with key works perfectly. And the firewall is locking down everything else. So far, so good.

6. WHAT FAIL2BAN IS SUPPOSED TO DO: Fail2Ban makes it possible to whitelist a domain! This is really nice. Add in the DNS service domain host name, just as with CFS, and then Fail2Ban is supposed to dynamically update the associated IP address with firewalld – and apparently the interface between the two comes with the install.

7. PROBLEM WITH NEW DEPLOYMENT: New IP addresses can be manually added to firewallD. But so far Fail2Ban does not dynamically do this.

**8. DOCUMENTATION? **I haven’t seen any documentation on the interface between fail2ban and firewalld. Everyone just says “it works”. More details would really help, especially for such an important set of products.

9. HOW IMPORTANT IS THIS USE CASE? The popularity of affordable VPS cloud instances is skyrocketing! And a huge number of home office users are of course on dynamic IP addresses. The ability to easily configure a cloud instance to ONLY accept connections from a small number of home office or mobile users would be HUGELY useful it seems.

10. PROOF: And we know it works really well – case in point is the OpenSUSE 48 version with CFS.

11. SUMMARY PROBLEM: Fail2Ban is not getting the updated IP address and pumping it into firewalld. I have not been able to find information on how this is supposed to work or any logs to read or settings to do. Fail2Ban as far as I know is correctly configured.
**FAIL2BAN CONFIG

jail.local**

[DEFAULT]
**ignorip=127.0.0.1 aaa.bbb.com **/ “aaa” etc. is the FQDN model /

**[sshd] **/ f2b will monitor inbound ssh /
enabled=true
port = 2221
**action = iptables-multiport **/ Not sure even about this line /

**12. POSSIBLE PROBLEMS, **perhaps either of following?

  1. Link between Fail2Ban and DNS service.
  2. Link between Fail2Ban and FirewallD.

Thanks for any suggestions!

John

It appears that Fail2Ban uses iptables not firewalld.
I use iptables as it is in my opinion much better than firewalld.
I load a table of countries to ignore in my iptables and add any site that tries to log onto my system as root and fails and adds any site that tried 4 times and failed.
As of today I am blocking over 100 countries and 16700 ip address that have attempted to ssh to my machine.
I also limit logins to 6 per minute. I found some place that said how to do that. It sometimes allows up to 12 tries before my script to look for log failures kicks in from cron.

You will have to install iptables and enable it and load it with a shell script and disable firewalld - you cannot have both.

This is my opinion. I wrote my own answer to Fail2Ban when I started using linux in 1993 and adapted it to iptables when that came out.

Thanks Larry. You have some serious experience. From my reading though I have seen multiple statements that Fail2Ban does work with firewalld. It’s a little confusing.

For the record, I use OpenSUSE very much for YAST; Ubuntu (multiple years ago) proved to be more “techy” and a higher sysadmin load (with all respect for professional sysadmins!!). Very satisfied and share with friends that advantages. And the business of running an instance in the cloud that has reasonable security is a top use case. My previous solution worked great and was understandable (the CFS install for OpenSUSE has not been updated for Leap 15; it seems to have to do with default directories and such – I can’t figure it out and have no time). So, going with the new “out-of-the-box” firewalld seems like a good idea. I can put a single IP address in it and have it work – but if the dynamic DNS is triggered, it’s back to the console to reset the allowed IP address. If I was product manager, I’d make this a top use case to support. :slight_smile:

Took a few minutes to take a look at this…

I assume that you’ve installed fail2ban from the openSUSE repos (OSS and OSS Update).
If you installed any other way, the rest of what I’m posting won’t apply.

There is no openSUSE related documentation I can find, but this should be easy to figure out. Some might find what I’m posting here should be sufficient for “documentation.”

The Fedora Fail2Ban/FirewallD Wiki, as short as it is should apply to openSUSE as well except that we install with zypper (not dnf). There is nothing else that’s Fedora-specific, it covers general info that’s common to all deployments. Perhaps the critical item to note that shows up in all fail2ban documentation is the importance of the “ipset” rules, and in particular because we are dealing with firewalld, the “firewallcmd-ipset” ruleset

https://fedoraproject.org/wiki/Fail2ban_with_FirewallD

Next important thing to take a look at is what is installed with the openSUSE fail2ban package,
You can inspect the package’s contents with the following

rpm -ql fail2ban

I won’t repost the entire output here but the following directories and their contents should be noted…

#The rulesets, particularly the *.conf files
/etc/fail2ban/action.d/ 
#The applications supported      
/etc/fail2ban/filter.d/         

#The following are misc but important fail2ban configurations
/etc/fail2ban/jail.conf
/etc/fail2ban/jail.d
/etc/fail2ban/jail.local
/etc/fail2ban/paths-common.conf
/etc/fail2ban/paths-opensuse.conf
/etc/logrotate.d/fail2ban

#The following are the binaries. Although can be invoked directly, ordinarily should be invoked by a systemd command
/usr/bin/fail2ban-client
/usr/bin/fail2ban-python
/usr/bin/fail2ban-regex
/usr/bin/fail2ban-server

#The systemd Unit file (systemctl start|stop|restart fail2ban.service)
/usr/lib/systemd/system/fail2ban.service

#The following are man pages
/usr/share/man/man1/fail2ban-client.1.gz
/usr/share/man/man1/fail2ban-python.1.gz
/usr/share/man/man1/fail2ban-regex.1.gz
/usr/share/man/man1/fail2ban-server.1.gz
/usr/share/man/man1/fail2ban-testcases.1.gz
/usr/share/man/man5/jail.conf.5.gz

Before getting into fail2ban, a bit of clarification regarding firewalld and iptables. It might be important one day to know that firewalld does not replace iptables, firewalld is what might be called a firewall manager. Think of it as a “rule maker and manager” but does not actually have any actual firewall functionality. The firewalld rules actually only operate on the underlying iptables (or ebtables). So, when an app like fail2ban wants to block an ip address, that configuration would be sent either to iptables directly (because it is the real functionality) or to a firewall manager like firewalld which has its own way of creating and managing firewall rules which are then translated to the underlying iptables (or ebtables).

Installed properly (both firewalld and fail2ban installed from the openSUSE repositories), everything should indeed “just work,” but if you run into a problem or want to enhance how fail2ban works, the above info should hopefully be enough to make any modifications…

  • You can open the file “/etc/fail2ban/action.d/firewallcmd-ipset.conf” which appears to be a “master ruleset”
  • You can add a blocklist by configuring “badips” or “blocklist_de”
  • You can view the MAN pages (see actual choices in the RPM contents above)

Tsu2 – super thanks for your info – it is especially important because it means I’m going in the right direction.

And yes, did install from the YAST repository. Also began to think that “ipset” was key here. And I did grok that firewalld is not mutually exclusive of iptables.

As I mentioned – the thing is WORKING NOW – but only by a manual IP address update. THE GOAL here is that Fail2Ban PUSHES a new white-listed IP address (from the dynamic DNS service, based on a host name) to firewalld. F2B documentation shows that it is POSSIBLE to whitelist a host name for exactly this purpose.

And the problem right now is that F2B is NOT pushing or detecting or whatever, the changed IP address.

More research.

J.

You’ll need to describe exactly how you’re attempting to whitelist.
Although written for another distro, the steps described in the following should work on openSUSE as well(You need to configure a jail)…

https://www.the-art-of-web.com/system/fail2ban-action-whitelist/

TSU

Tsu,

Your Art-Of-The-Web reference is great. Starting to study it now.

As for exactly what I’ve done, here are the lines out of jail.local (I know from checking the service that both firewalld and fail2ban are working).

[DEFAULT]

ignorip = 127.0.0.1/8 host.domain.tld

[sshd]

enabled = true
port = 22
logpath = %(sshd_log)s
backend = %(sshd_backend)s

Elsewhere there is . . . (and other default settings and jails, not used???)

[INDENT=3][/INDENT]
backend = systemd

This matches the line in the URL you shared:

ignoreip = 127.0.0.1/8 192.168.0 secure.example.net

J.

Just to recap:

Your setup will be using either iptables, or the newer nftables, at the kernel level for packet filtering.
Packet filtering rules can be written with:

  • the user level command iptables
    , or nft if nftables is being used - a management interface such as firewalld

Fail2ban can use any of these 3 alternatives as its banaction for a particular jail. So firewalld is not even required unless a firewalld ban action is specified.

Fail2ban should honour the

ignorip = 127.0.0.1/8 host.domain.tld

rule you have written but will have timing issues.

Firstly, when your IP changes, the DNS system will still serve your old IP for some hours/days depending on the TTL set in the DNS entry for host.domain.tld. This can be overcome by resetting the TTL to 600 (seconds) or so.

Secondly, there needs to be a trigger to cause fail2ban to requery the DNS entry for host.domain.tld, and then remove the old entry and write a new entry in iptables. I presume your DDNS provider will supply such a trigger but I have never used the service myself.

Given such a trigger is available it should be a simple matter to write a bash script to force fail2ban to reload itself, after waiting at least the TTL set above. Or use fail2ban-client <JAIL> delignoreip <IP> and fail2ban-client <JAIL> addignoreip <IP> directly.

Alternatively don’t use fail2ban to set the entry. If a DDNS trigger is available, use it to run a script to write the new entry, and delete the old one, using iptables or firewalld. Else run a script that checks the current IP every 10 minutes or so with a systemd timer.

At this stage of fail2ban’s development, I don’t see an option that avoids a script of some sort.

Graeme

Graeme,

Your comments are fantastic. Especially the “I don’t see a way of avoiding a script”. That’s the kind of insight that you don’t so easily find from reading dozens of webpages and manuals!

As you may know from my previous notes, all this was working basically out-of-the-box with the CFS firewall deployed on Webmin! But I’ve had difficulties installing CFS on Leap. Also as I mentioned, any solution for this I think will be appreciated by a growing number of people. It’s interesting to see how the evidence of people looking for such as solution falls into multiple different categories – which almost don’t overlap – such as a “whitelist” oriented topic versus a “dynamic DNS” oriented topic (with other terms of course).

I understand from a high level the different options you have presented; now I have to review. And will get back when I have more info.

J.

J

Happy to help.

Graeme

J

Couple of follow up thoughts.

If you write a rule in iptables to accept your current IP address, you will have to find a way of ensuring this rule always remains first in the chain. Otherwise, some other application (such as fail2ban) may later write a rule to reject/drop your IP, that is ahead of your rule in the chain and takes precedence. I suspect there would be a fair bit of messing round to avoid this.

I think the easier approach will be to use fail2ban’s ignoreip function. IIUC fail2ban forms an an internal “whitelist” of these IPs to ensure they are never banned; much simpler than writing an over-riding rule to always accept them. The (basic and untested) script below should do this. You could run it from a ddns trigger or with a systemd timer every 10 minutes or so.

#! /bin/bash

IP_CACHE=~/.cache/ignoreIP-cache
JAIL=sshd

## Create empty cache file if not existing
 -e "$IP_CACHE" ] || /usr/bin/touch "$IP_CACHE"

## Read cached public IP
cache_ip="$(/usr/bin/cat "$IP_CACHE")"

## Get current public IP
ip="$(/usr/bin/curl -s https://ipinfo.io/ip)"

## Exit if IP is unchanged
 "$cache_ip" = "$ip" ] && exit

## Cache new IP
/usr/bin/echo "$ip" > "$IP_CACHE"

## Delete previous IP from f2b ignore list, if known
 -n "$cache_ip" ] && /usr/bin/fail2ban-client set "$JAIL" delignoreip "$cache_ip"

## Add new IP to f2b ignore list
/usr/bin/fail2ban-client set "$JAIL" addignoreip "$ip"

## Reload f2b jail
/usr/bin/fail2ban-client reload "$JAIL"

Graeme