ipset is an excellent tool that can be used to efficiently block a list of IP addresses at the firewall level (it uses iptables). It really helps in easily adding IP addresses and maintaining IP address blocklists.
The below guide sets up ipset to block a list of IP addresses and includes several commands to save/restore said IP lists.
This guide assumes you on are on form of Linux (Ubuntu 16.10 Server is used below).
Guide
Installing ipset
Let's first install ipset. On Debian/Ubuntu we can do:
sudo apt-get install ipset
On CentOS/Amazon-Linux you would do:
sudo yum install ipset
Creating our "blacklist"
Let's first start by creating a list - we'll call our list 'blacklist' (please forgive the lack of originality).
Note you can create several types of ipset lists, with the type defining the IP address input formats. The two we're interested in here is ip
and nethash
. ip
simply allows defining IP addresses (in their full form) and nethash
allows (and requires) CIDR format - which allows us to block entire IP ranges (which if you tried to add to an ipset using hash:ip
, could very easily fill the ipset list up to it's maximum).
To create an ip
type list:
sudo ipset create blacklist hash:ip hashsize 4096
To create a nethash
(CIDR) type list:
sudo ipset create blacklist nethash
Enabling (and deleting) the list in iptables
Now that we've created out list, we need to tell iptables to use it:
sudo iptables -I INPUT -m set --match-set blacklist src -j DROP sudo iptables -I FORWARD -m set --match-set blacklist src -j DROP
Note, we can always remove these rules (to get iptables to not use the list) by:
sudo iptables -D INPUT -m set --match-set blacklist src -j DROP sudo iptables -D FORWARD -m set --match-set blacklist src -j DROP
See Make ip-tables (firewall) rules persistent for saving the above ip-table rules permanently.
Alternatively, you can list all iptables rules (of which ipset will be in there) and then select a rule to delete. For example, the below commands will list, and then delete the listed rule 1:
sudo iptables -L --list-numbers sudo iptables -D INPUT 1
Setting ipset to be persistent (not lose lists on reboot)
netfilter-persistent should save your ipset lists. You might need to install this package. On Debian/Ubuntu:
sudo apt-get install netfilter-persistent
First make sure the service has started
sudo service netfilter-persistent start
and then save settings (once you've created your block list):
sudo service netfilter-persistent save
See chkconfig alternative for debian based distros for setting the 'netfilter-persistent' service to start on boot.
Listing / adding / removing IP addresses from our blacklist
To list current IP addresses in our list, do:
sudo ipset list
To add an IP address, simply do:
sudo ipset add blacklist <IP-ADDRESS_OR_CIDR-IF-NETHASH>
To remove an IP address, do:
sudo ipset del blacklist <IP-ADDRESS_OR_CIDR-IF-NETHASH>
To remove ALL IP addresses in a list, use the flush command
sudo ipset flush blacklist
Querying to see if IP address is in list
You can use the "test" command to check if an IP address is in a specific list:
sudo ipset test blacklist <IP-ADDRESS>
Saving / restoring IP lists
To save the current list to a file:
sudo ipset save blacklist -f ipset-blacklist.backup
To restore said file:
sudo ipset restore -! < ipset-blacklist.backup
Backing up list periodically (with cron)
It's a good idea to keep a backup of your list. One way to do this automatically is to create a cron entry to backup script.
Let's create a simple backup script that will check whether there are members (entries) for a particular list (in this example we have a list called "blacklist"), and then if there are members to backup to a specific location. Here's my script:
#!/bin/bash # check if ipset output has output. The below command counts all lines after "Members:" line of ipset list NUM_LINES=$( /sbin/ipset list blacklist | awk '/Members:/{l=1;next}l' | wc -l ) if [ $"$NUM_LINES" -gt 0 ]; then /sbin/ipset save blacklist -f /home/<USER>/ipset-blacklist.backup echo "blacklist backed up" else echo "ipset list blacklist is empty - nothing backed up" fi
Let's now make our script executable
chmod a+x ipset-blacklist_backup.sh
You can now run the above script (which needs to be run as sudo) as a cron job.
Start by opening su's crontab:
sudo crontab -e
Modify (to suit) and add the following entry into crontab
# backup ipset blacklist (list of IP addresses have blacklisted with iptables/firewall) 30 2 * * * /home/<USER>/ipset-blacklist_backup.sh
Here I've chosen to backup my blacklist every morning at 0230hrs to USER's home folder.
Note: ipset on my ubuntu setup is found at /sbin/ipset. However, if you use another distribution you will need to check where ipset is (probably at /usr/sbin/ipset or the like).
Deleting a list
You might want to delete a list. To do so you can use the 'destroy' command:
sudo ipset destroy blacklist
Note1, that you first need to remove any lists that are in use from iptables. See above section Enabling the list in iptables for details on how to do this.
Note2: use the flush command to simply delete all ip addreses in the list without deleting the list itself.
References
- https://linux-audit.com/blocking-ip-addresses-in-linux-with-iptables/
- https://unix.stackexchange.com/questions/401984/how-to-import-multiple-ips-to-ipset
- http://xmodulo.com/block-unwanted-ip-addresses-linux.html
- https://strongarm.io/blog/linux-firewall-performance-testing/
- https://linoxide.com/linux-how-to/block-ips-country-ipset/
Related articles