IPsets with UFW
This is an example that lets you use UFW (https://wiki.ubuntu.com/UncomplicatedFirewall) and IPsets to dynamically whitelist IPs for a common host-based firewall.
First you need a systemd script that creates an ipset
on startup and then have a script that integrates this ipset
with UFW to allow specific traffic (like an SSH knock), you'll need to create two main components:
- A systemd service script that creates and loads the
ipset
at startup. - A UFW application profile or direct rules that utilize the IPset for allowing specific traffic.
1. Systemd Service for IPset
Create a systemd service that will run at startup to create and populate your ipset
. Here's how you can create this service:
Step 1: Create the ipset
Script
First, create a script that will define and load your ipset
. Let's call this script create_ipset.sh
.
/usr/local/bin/create_ipset.sh:
#!/bin/bash
# Name of the ipset
IPSET_NAME="knocknoc"
# Flush if exists and create
ipset ipset -exist flush $IPSET_NAME
ipset -exist create $IPSET_NAME hash:ip
# Optionally, add IPs here or via separate mechanism
# ipset add $IPSET_NAME 192.168.1.100
Make sure to make it executable:
sudo chmod +x /usr/local/bin/create_ipset.sh
Step 2: Create the systemd Service File
Create a new systemd service file called ipset.service
.
/etc/systemd/system/ipset.service:
[Unit]
Description=Create ipset for SSH Knocking
Before=ufw.service
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/create_ipset.sh
[Install]
WantedBy=multi-user.target
This script sets up the service to run before UFW (as indicated by Before=ufw.service
) but after the network is available (After=network.target
).
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable ipset.service
sudo systemctl start ipset.service
2. Integrating IPset with UFW
For integrating the ipset
with UFW, you will typically use direct iptables rules. However, UFW does not directly support ipset
in its regular configuration files, so you'll have to add these rules in the after.rules
file for them to be applied with UFW.
Add Rules to UFW's after.rules
Edit the /etc/ufw/after.rules
file to add your custom iptables rules referencing the ipset
.
# At the end of /etc/ufw/after.rules
-A ufw-after-input -m set --match-set knocknoc src -p tcp --dport 22 -j ACCEPT
COMMIT
This rule will allow SSH connections on port 22 for IP addresses that are in the knocknoc
IPset.
Notes and Considerations
- Testing: Always test firewall and startup scripts in a controlled environment before deploying them on a production server. "Cutting your hands off" is too easy if you are not careful!
- Order of Execution: The systemd script needs to execute before UFW starts, hence the
Before=ufw.service
directive. Ensure that the network is available before the script runs.
With this setup, your system will create and populate the ipset
at startup, and UFW will utilize these sets to allow traffic as specified. This approach provides a balance between the simplicity of UFW and the power of ipset
and iptables. Always ensure to test and verify your configuration in a safe environment before applying it to a live system.