Table of Contents
- What Are IP Sets?
- Why Use IP Sets with iptables?
- Installation & Prerequisites
- Creating and Managing IP Sets
- 4.1 IP Set Types
- 4.2 Basic IP Set Commands
- Integrating IP Sets with iptables
- Advanced Use Cases
- Persisting IP Sets Across Reboots
- Troubleshooting Common Issues
- Best Practices
- References
What Are IP Sets?
IP sets are kernel-level data structures designed to store collections of network-related entries (IP addresses, networks, ports, etc.) for efficient lookup. Unlike individual iptables rules, which check each packet against a linear list of rules, IP sets use hash tables or trees, allowing for O(1) or O(log n) lookup times—even for large datasets.
IP sets are managed via the ipset userspace tool, which communicates with the kernel’s ip_set module. They support various types, each optimized for specific use cases (e.g., single IPs, CIDR ranges, IP-port pairs).
Why Use IP Sets with iptables?
Traditional iptables rules suffer from two major drawbacks when handling large numbers of IPs:
- Performance: A rule list with thousands of entries forces
iptablesto check each packet against every rule until a match is found, leading to latency. - Manageability: Adding/removing IPs requires modifying the rule set, which often involves flushing and reloading rules (disruptive) or appending new rules (which bloats the list further).
IP sets solve these issues by:
- Centralizing IP management: Group IPs into sets, and reference the set in a single
iptablesrule. - Dynamic updates: Add/remove IPs from a set in real time without modifying or reloading
iptablesrules. - Efficiency: Kernel-level hash tables ensure fast lookups, even for large sets.
Installation & Prerequisites
Before using IP sets, ensure your system has the required tools and kernel support.
Step 1: Check Kernel Support
IP sets require the ip_set kernel module. Verify support with:
lsmod | grep ip_set
If no output, load the module manually:
sudo modprobe ip_set
(Most modern Linux kernels include ip_set by default.)
Step 2: Install ipset Tool
The ipset userspace tool manages sets. Install it via your package manager:
-
Debian/Ubuntu:
sudo apt update && sudo apt install ipset -y -
RHEL/CentOS/Rocky Linux:
sudo dnf install ipset -y -
Arch Linux:
sudo pacman -S ipset
Step 3: Verify Installation
Confirm ipset is installed:
ipset --version
Creating and Managing IP Sets
IP sets are defined by a type (e.g., hash:ip, hash:net) and optional parameters (e.g., maximum size, timeout). Below are common operations.
IP Set Types
The most useful types include:
| Type | Purpose | Example Entry |
|---|---|---|
hash:ip | Single IPv4/IPv6 addresses | 192.168.1.100 |
hash:net | IPv4/IPv6 networks (CIDR ranges) | 10.0.0.0/24 |
hash:ip,port | IP + port pairs (e.g., 1.2.3.4:80) | 192.168.1.1:22 |
hash:net,port | Network + port pairs (e.g., 10.0.0.0/24:443) | 172.16.0.0/16:8080 |
Basic IP Set Commands
1. Create a Set
Use ipset create <set-name> <type> [parameters].
Example 1: Blocklist for single IPv4 addresses
Create a hash:ip set named blocklist-ips with a maximum of 10,000 entries:
sudo ipset create blocklist-ips hash:ip family inet hashsize 1024 maxelem 10000
family inet: Use IPv4 (omit or useinet6for IPv6).hashsize 1024: Initial hash table size (kernel auto-scales).maxelem 10000: Maximum number of entries.
Example 2: Allowlist for IPv4 networks
Create a hash:net set named allowlist-nets for CIDR ranges:
sudo ipset create allowlist-nets hash:net family inet maxelem 500
2. Add Entries to a Set
Use ipset add <set-name> <entry> [timeout <seconds>].
Add an IP to blocklist-ips:
sudo ipset add blocklist-ips 203.0.113.45
Add a network to allowlist-nets:
sudo ipset add allowlist-nets 192.168.5.0/24
Add a temporary IP (auto-expires after 1 hour):
sudo ipset add blocklist-ips 198.51.100.10 timeout 3600 # 3600 seconds = 1 hour
3. List Sets and Entries
- List all sets:
sudo ipset list - List details for a specific set:
sudo ipset list blocklist-ips
4. Remove Entries from a Set
sudo ipset del blocklist-ips 203.0.113.45 # Remove a single IP
5. Flush (Clear) a Set
Remove all entries from a set (but keep the set itself):
sudo ipset flush blocklist-ips
6. Destroy a Set
Delete a set entirely:
sudo ipset destroy blocklist-ips
Integrating IP Sets with iptables
Once a set is created, reference it in iptables rules using the -m set match extension.
Matching IP Sets in iptables Rules
The syntax for referencing a set in iptables is:
sudo iptables -A <chain> -m set --match-set <set-name> <direction> -j <target>
<chain>: The iptables chain (e.g.,INPUT,OUTPUT,FORWARD).--match-set <set-name>: The name of the IP set.<direction>:src(source IP) ordst(destination IP).<target>: Action (e.g.,DROP,ACCEPT,LOG).
Example 1: Block All IPs in blocklist-ips
Add a rule to the INPUT chain to drop traffic from any IP in blocklist-ips:
sudo iptables -A INPUT -m set --match-set blocklist-ips src -j DROP
Example 2: Allow Traffic from allowlist-nets
Allow SSH (port 22) only from networks in allowlist-nets:
sudo iptables -A INPUT -p tcp --dport 22 -m set --match-set allowlist-nets src -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j DROP # Deny all others
Example 3: Block IP-Port Pairs
Create a hash:ip,port set named blocklist-ip-port and block traffic to those pairs:
sudo ipset create blocklist-ip-port hash:ip,port family inet
sudo ipset add blocklist-ip-port 198.51.100.20:80 # Block 198.51.100.20:80
# Block incoming traffic to these IP:port pairs
sudo iptables -A INPUT -m set --match-set blocklist-ip-port dst -j DROP
Dynamic Updates: Adding/Removing IPs Without Reloading iptables
The biggest advantage of IP sets is dynamic updates. For example, to block a new IP:
sudo ipset add blocklist-ips 192.0.2.1 # No need to modify iptables!
The iptables rule referencing blocklist-ips will immediately drop traffic from 192.0.2.1.
Advanced Use Cases
Time-Based IP Sets
Use the timeout parameter to auto-expire entries. For example, block an IP for 10 minutes:
sudo ipset add blocklist-ips 203.0.113.50 timeout 600 # 600 seconds = 10 minutes
Verify with ipset list blocklist-ips (check the timeout column).
Port-Specific IP Sets
Block IPs only on specific ports using hash:ip,port sets. For example, block SSH brute-force attackers:
# Create a set for IP:port pairs (SSH is port 22)
sudo ipset create blocklist-ssh hash:ip,port family inet
# Add a rule to drop SSH traffic from these IP:port pairs
sudo iptables -A INPUT -p tcp --dport 22 -m set --match-set blocklist-ssh src -j DROP
# Block an attacker's IP on SSH (port 22)
sudo ipset add blocklist-ssh 198.51.100.30:22
Persisting IP Sets Across Reboots
IP sets are not persistent by default—they are lost on reboot. To persist them:
Step 1: Save Sets to a File
Save all sets to /etc/ipset.conf:
sudo ipset save > /etc/ipset.conf
Step 2: Restore Sets on Boot
Restore sets at startup using a systemd service.
For Debian/Ubuntu
Create a systemd service file:
sudo nano /etc/systemd/system/ipset-persistent.service
Add the following content:
[Unit]
Description=Restore IP sets on boot
Before=netfilter-persistent.service # Ensure sets load before iptables rules
[Service]
Type=oneshot
ExecStart=/usr/sbin/ipset restore -f /etc/ipset.conf
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Enable and start the service:
sudo systemctl enable ipset-persistent.service
sudo systemctl start ipset-persistent.service
For RHEL/CentOS
RHEL-based systems can use ipset-service (install with sudo dnf install ipset-service). Enable persistence with:
sudo systemctl enable ipset
sudo systemctl start ipset
This automatically saves sets to /etc/sysconfig/ipset and restores them on boot.
Troubleshooting Common Issues
Issue: “Set does not exist” when adding iptables rules
The IP set must exist before referencing it in iptables. Create the set first:
sudo ipset create blocklist-ips hash:ip # Then add the iptables rule
Issue: “Operation not permitted”
Ensure you’re running commands as root (use sudo).
Issue: ipset command not found
Reinstall the ipset package (see Installation).
Issue: Kernel module missing
If modprobe ip_set fails, your kernel may not support IP sets. Upgrade to a newer kernel or enable ip_set in kernel config.
Best Practices
- Name Sets Clearly: Use descriptive names like
blocklist-sshorallowlist-vpn. - Limit Set Size: Even with hash tables, very large sets (100k+ entries) can impact performance. Split into smaller sets if needed.
- Audit Regularly: Prune expired or unused entries with
ipset flush <set-name>or manual deletions. - Combine with Fail2ban: Use Fail2ban to automatically add malicious IPs to IP sets. Configure Fail2ban’s
actionto runipset addinstead ofiptablescommands. - Backup Sets: Periodically save sets with
ipset save > backup-ipset.confto avoid data loss.