Block IP addresses in Linux with iptables
Most system administrators will already be familiar with iptables. It is around for quite a while and is enabled by default within the Linux kernel. We can use iptables to block one, multiple IP addresses, or even full networks. This may come in handy when you get repeating port scans or see failed login attempts in your log files. Time to get started and block some IP addresses!
Check existing iptables configuration
The first step is to validate existing iptables rules. We will use an empty ruleset for test purposes.
iptables -L
Manually blocking a single IP address
The first option to permanently block an IP address is by creating a rule in the INPUT chain. This way traffic is no longer allowed from that particular IP address.
iptables -I INPUT -s 192.168.1.100 -j DROP
Although this option works great, it might not scale very well. You might even get a very long list of IP addresses to block after a while. Let’s have a look at ipset.
Using blocklists with iptables and ipset
Another option is creating a blocklist. This way we can add multiple systems we no longer want to connect to our systems.
Install ipset utility
Most Linux systems do not have the ipset utility installed by default. So first install that toolkit.
CentOS
yum install ipset
You may need to install the epel-release package first.
Debian and Ubuntu
apt install ipset
Creating a blocklist
With the newly installed ipset utility we create a new list to block IP addresses. We name it blocklist to show clearly its purpose.
Create blocklist with ipset utility (once)
ipset create blocklist hash:ip hashsize 4096
Note: if you want to block based on networks, use hash:net.
After the blocklist is created, we can use the set in iptables. It is related to the -match-set option.
Set up iptables rules. Match with blocklist and drop traffic:
iptables -I INPUT -m set --match-set blocklist src -j DROP
iptables -I FORWARD -m set --match-set blocklist src -j DROP
These commands will add the blocklist (or set) to the INPUT and FORWARD chains. As this is a blocklist, the related policy is to drop traffic. No output will be displayed when entering the commands.
Adding IP addresses to block
Next step is adding actual IP address to the list. Add a specific IP address to your newly created blocklist:
ipset add blocklist 192.168.1.100
Show details
To confirm the blocklist contains the IP address, use the ipset list
command.
Test rules and activate rules on reboot
When setting up a blocklist like this, always test it. You want to be sure that the blocklist is enforced in your specific configuration. Also, make sure it still works after a reboot of the system.
To save and restore iptables rules, use the package iptables-persistent. As the name implies, this makes the iptables rules persistent across reboots.
apt install iptables-persistent
To also store ipset rules, create a small systemd service file: /etc/systemd/system/save-ipset-rules.service
# ipset save/restore script (see https://linux-audit.com/networking/iptables/blocking-ip-addresses-in-linux-with-iptables/)
[Unit]
Description=ipset persistent rule service
Before=netfilter-persistent.service
ConditionFileNotEmpty=/etc/iptables/ipset
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/ipset -exist -file /etc/iptables/ipset restore
ExecStop=/sbin/ipset -file /etc/iptables/ipset save
[Install]
WantedBy=multi-user.target
This script helps to save and restore the ipset rules. You may need to create the /etc/iptables/ipset file.
/sbin/ipset -file /etc/iptables/ipset save
Combining ipset and IPv6
If you want to use IPv6 addresses, create the related database with the ‘inet6’ family.
ipset create blocklist6 hash:net hashsize 4096 family inet6
Then create the ip6tables rule:
ip6tables -I INPUT -m set --match-set blocklist6 src -j DROP
Happy blocking!