ufw

Support for ipset

Bug #1571579 reported by Jean Revertera
50
This bug affects 9 people
Affects Status Importance Assigned to Milestone
ufw
Triaged
Wishlist
Unassigned

Bug Description

Firewalld 0.4 will have built-in support for ipset: http://www.firewalld.org/2015/12/ipset-support/

It would be nice to have something similar in ufw.

This may also resolve #801833

Tags: wishlist
description: updated
Revision history for this message
txemi (txemitron) wrote :

I would love this too, I would like use symbolic names and lists on rules and ipset integration in ufw could be easy to implement. Now rules with ipset names fail as they are not recognized as IP addresses.

Not having this forces me to write similar rules for groups of addresses or networks making rules difficult to understand and maintain.

More references to this:

http://askubuntu.com/questions/755008/using-ufw-with-ipsets/888534

Changed in ufw:
importance: Undecided → Wishlist
status: New → Triaged
Revision history for this message
Jamie Strandboge (jdstrand) wrote :

FYI, it is possible to use ipset with ufw, but it isn't integrated into the ufw command itself. This can be done via the /etc/ufw/before.init and /etc/ufw/after.init scripts (see 'man ufw-framework' for details).

One way to do this is make after.init executable (chmod 740 /etc/ufw/after.init) and update it to have something like:

savefile="/etc/ufw/custom/ipset.save"
if [ ! -f "$savefile" ]; then
    echo "Could not find '$savefile'" >&2
    return
fi

IPSET_EXE="/sbin/ipset"

case "$1" in
start)
    # Loading ipsets
    $IPSET_EXE restore < "$savefile"

    # Setting firewall rules
    iptables -I INPUT -m set --match-set blacklist-ip src -j DROP
    iptables -I INPUT -m set --match-set blacklist-ip src -j LOG --log-prefix "[UFW BLOCK IN bl-ip] "
    iptables -I FORWARD -m set --match-set blacklist-ip src -j DROP
    iptables -I FORWARD -m set --match-set blacklist-ip src -j LOG --log-prefix "[UFW BLOCK FW bl-ip] "
    iptables -I OUTPUT -m set --match-set blacklist-ip src -j DROP
    iptables -I OUTPUT -m set --match-set blacklist-ip src -j LOG --log-prefix "[UFW BLOCK IN bl-ip] "

    ... continue like above for each set
    ;;
stop)
    # Unset firewall rules
    iptables -D INPUT -m set --match-set blacklist-ip src -j DROP || true
    iptables -D INPUT -m set --match-set blacklist-ip src -j LOG --log-prefix "[UFW BLOCK IN bl-ip] " || true
    iptables -D FORWARD -m set --match-set blacklist-ip src -j DROP || true
    iptables -D FORWARD -m set --match-set blacklist-ip src -j LOG --log-prefix "[UFW BLOCK FW bl-ip] " || true
    iptables -D OUTPUT -m set --match-set blacklist-ip src -j DROP || true
    iptables -D OUTPUT -m set --match-set blacklist-ip src -j LOG --log-prefix "[UFW BLOCK IN bl-ip] " || true

    ... continue like above for each set

    # Destroy ipset lists
    $IPSET_EXE destroy blacklist-ip || true

    ... continue like above for each set
    ;;
status)
    echo "= after.init ="
    for s in blacklist-ip ... other sets ; do
        echo "== $s =="
        $IPSET_EXE list $s | grep -v '^[1-9]' | grep -v '^Members' || true
        echo ""
    done
    ;;
flush-all)
    "$0" stop
    ;;
save)
    # Custom command
    $IPSET_EXE save > "$savefile"
    ;;
*)
    echo "'$1' not supported"
    echo "Usage: after.init {start|stop|flush-all|status}"
    ;;
esac

after.init is executed last, so after the firewall is setup, the ipset saved rules are loaded into the kernel, then the -I inserted rules above are put before anything else in the primary chains. Initial setup requires:

$ sudo mkdir /etc/ufw/custom
$ sudo ipset create blacklist-ip hash:ip family inet hashsize 8192 maxelem 65536 # or however you want it set. Do this for each set you want
$ sudo /etc/ufw/after.init save

Adding rules is simply a matter of:

$ sudo ipset add blacklist-ip <ip1>
$ sudo ipset add blacklist-ip <ip2>
$ sudo /etc/ufw/after.init save # if want newly added rules to survive a reboot

Revision history for this message
txemi (txemitron) wrote :

Yes, I was thinking adding ipset this way before ufw rules are loaded and then use ipset aliases in ufw rules. This fails:

root:~# ipset -N myset iphash
root:~# ipset -A myset 1.1.1.1
root:~# ipset -A myset 2.2.2.2
root:~# ufw allow from myset
ERROR: Dirección de orígen errónea
root:~#

As you say I was thinking adding ipset commands in /etc/ufw/before.init.

I suppose it would be easy modifying ufw to allow rules using ipset previously added aliases.

Revision history for this message
Ilya Ka (ilka2018) wrote :

I use ``sshguard`` to protect ssh server.
One of its usages is based on ipset: it simply fills ipset with bad ip addresses,
and you block connections when source is in this address,
like
``m set --match-set sshguard4 src -j DROP``

With ufw this can be added to ``rules.before``, but ufw starts before ``sshguard``, so it doesn't see this set, and simply fails leaving my machine with an empty INPUT chain with DROP policy :)

People even wrote systemd units that run before ufw just to create ipset

https://selivan.github.io/2018/07/27/ipset-save-with-ufw-and-iptables-persistent-and.html

While I can use chains instead of ipset (unlike ipset, a chain could be created with ufw) I believe
ipset is a better solution of the huge list of IP addresses.

``netfilter-persistent`` tool loads ipset before iptables, so there is no such problem there.

I think ``ufw`` must have the ability to create an empty ipset to be compatible with sshguard.

Revision history for this message
Jamie Strandboge (jdstrand) wrote :

@Ilya, I suggest looking at comment #2 since with that mechanism (adapting it for your needs), you can ensure that the ipset is setup in time.

Revision history for this message
Kodiak Firesmith (kfiresmith-whoi) wrote :

Paying Canonical customer here. +1 to supporting ipset or at least ensuring support for nftables sets is present for UFW when we all switch over to the nft backend.

Canonical needs to take a look at what Red Hat offers and strive for feature/function parity within the Ubuntu ecosystem since many enterprises making the switch to Ubuntu will be coming from RHEL.

Revision history for this message
Jamie Strandboge (jdstrand) wrote :

Thanks for the feedback. It's true that nft is the future and it's also true that there is a ton of software out there that uses iptables. This is why iptables upstream made the wise choice to rearchitect iptables for 1.8 to continue to support the historic, legacy xtables backed while giving the user the ability to use the new nft backend while keeping the command line interface the same with either. ufw still uses iptables under the hood (which is fine for its current feature set).

Ubuntu 20.04 LTS and newer has iptables 1.8 and you are free to choose either the nft or the legacy backends via the 'update-alternatives' mechanism. ufw will then follow the system preference of backend and is confirmed to work with either (and CI/CD verifies this with new builds). Ubuntu 20.04 LTS defaults to legacy while 21.04 and newer default to nft.

As for rule sets, I agree if/when ufw implements the feature natively, it would need to consider working with either backend and that could be the time to implement the nftables backend. Despite ufw not natively supporting the feature, you can still use take advantage of ipsets/nftables sets by utilizing the ufw framework as details in comment #2 (which can be updated easily enough for nftables sets if you prefer the nft backend).

I'll also note the the main focus of ufw is as a bastion firewall and making it easy to configure for that. While it has historically and continues to function very well in that regard, it does offer some additional features for a routing firewall and its framework allows people to extend it further.

Revision history for this message
David Klann (dxklann) wrote :

Looks like this is still a thing. I adapted the after.init script in comment #2 (thanks @jdstrand) with minor changes for my UFW instance.

+1 for native ipset support in UFW.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.