LFCE 84 ๐ง ipset โ Practical Configuration
The previous chapter established what ipset is and why it exists. This chapter is the operational sequence. It covers the commands that create a set, populate it, reference it from iptables, and make it survive a reboot. The configuration is simple on its surfaceโa set is created, addresses are added, and a rule matches against the setโbut the details determine whether the set is actually consulted by the kernel. A set that exists but is not referenced by any rule does nothing. A rule that references a set that does not exist fails to load. A set that is created but not saved disappears on the next reboot, and the rule that references it fails to load because the set is missing.
The practical configuration has two parts: the ipset layer and the iptables layer. The ipset layer defines the data structure and its contents. The iptables layer defines the rule that reads from the set. The two layers are independent in their lifecycleโthe set can be updated without touching the ruleโbut they are coupled in their dependency: the rule cannot be loaded unless the set exists . The persistence layer saves both the set and the rule, and the boot sequence must restore the set before the rule.
Key point: The ipset command creates and populates the set, and the iptables command references it with -m set --match-set <name> src. The set must be created before the rule is added, and the set must be restored at boot before the iptables rules are restored. On Debian and Ubuntu, the iptables-persistent package includes a plugin that saves the sets to /etc/iptables/ipsets and restores them with the netfilter-persistent service . On RHEL and its derivatives, the ipset service and the iptables service must be ordered so that the sets are restored first.
Why practical configuration requires explicit sequencing
The dependency problem.
An iptables rule that references an ipset by name is not a self-contained rule. The kernel resolves the set name when the rule is loaded, and if the set does not exist, the rule fails to load with an error. This means the set must be created before the rule is added, and the boot sequence must restore the sets before the firewall rules . A saved iptables ruleset that references a set is not portable to a system where the set does not exist.
The persistence problem.
The ipset command operates on the kernel’s in-memory data structures. A reboot clears them. The ipset save command writes the set definitions and contents to a file, and the ipset restore command reads them back. The file contains the create command with the set type and options, and the add commands with the members . The file must be restored at boot, and the restoration must happen before the iptables rules that reference the sets.
The update problem.
The set can be updated without touching the iptables rule. The ipset add and ipset del commands modify the set’s contents at runtime, and the rule continues to match against the updated set. This is the mechanism that allows dynamic blocklists to be managed by external tools. The rule is static; the set is dynamic. The separation is the reason ipset is used for fail2ban-style protection.
a. Creating and populating the set
The first step is to create the set with the appropriate type. The type determines what the set can store and how it is stored.
# Create a hash:net set for network blocklists
sudo ipset create blocklist hash:net maxelem 100000
# Create a hash:ip set for host blocklists
sudo ipset create hosts hash:ip maxelem 65536
# Add networks to the hash:net set
sudo ipset add blocklist 203.0.113.0/24
sudo ipset add blocklist 198.51.100.0/24
# Add hosts to the hash:ip set
sudo ipset add hosts 192.0.2.10
sudo ipset add hosts 192.0.2.20
The hash:net type is the correct choice for a blocklist of networks, because it stores CIDR blocks of different sizes in a single set . The hash:ip type is the correct choice for individual hosts. The maxelem option sets the upper bound on the number of elements, and the hash table is sized to accommodate that many entries . The ipset list command shows the set’s contents.
# List the set
sudo ipset list blocklist
# Output shows the type, the members, and the number of entries
b. Referencing the set from iptables
The set is referenced from iptables with the set match. The --match-set option specifies the set name and the direction, and the src or dst keyword determines whether the packet’s source or destination address is checked.
# Drop packets from any address in the blocklist
sudo iptables -A INPUT -m set --match-set blocklist src -j DROP
# Drop packets to any address in the blocklist
sudo iptables -A OUTPUT -m set --match-set blocklist dst -j DROP
The -m set loads the set match module, and the --match-set blocklist src option tells the kernel to check the packet’s source address against the set named blocklist . The rule is a single line, regardless of how many addresses the set contains. The -I flag can be used instead of -A to insert the rule at the top of the chain, which is the correct position for a blocklist rule.
The SET target is the write counterpart. It adds the packet’s address to a set, which is how dynamic blocklists are populated.
# Add the source address to the blocklist when the condition is met
sudo iptables -A INPUT -p tcp --dport 22 -m recent --name ssh --update --seconds 60 --hitcount 4 -j SET --add-set blocklist src
The SET --add-set blocklist src target adds the packet’s source address to the set . The rule can be combined with any match that detects the condition, such as the recent match that counts connections within a time window. The set is updated at the kernel level, and the next packet from the same address is matched by the set rule and dropped.
c. Saving and restoring the set
The set is lost on reboot unless it is saved. The ipset save command writes the set definition and contents to a file, and the ipset restore command reads them back.
# Save all sets to a file
sudo ipset save > /etc/ipset.conf
# Restore the sets from the file
sudo ipset restore < /etc/ipset.conf
The saved file contains the create command with the set type and options, and the add commands with the members . The -exist flag can be used with restore to ignore errors when the set already exists, which is useful when the restore is run repeatedly .
On Debian and Ubuntu, the iptables-persistent package includes a plugin that saves the sets to /etc/iptables/ipsets and restores them with the netfilter-persistent service . The plugin’s save_sets function runs ipset save, and the load_sets function runs ipset restore -exist. The service must be enabled with systemctl enable netfilter-persistent. On RHEL and its derivatives, the ipset service restores the sets from /etc/sysconfig/ipset, and it must be ordered before the iptables service.
# Debian: save the sets with the persistent service
sudo netfilter-persistent save
# RHEL: save the sets to the service file
sudo ipset save > /etc/sysconfig/ipset
sudo systemctl enable ipset
The persistence layer is the step that makes the configuration survive the reboot. Without it, the set is a temporary in-memory structure, and the iptables rule that references it fails to load on the next boot.
Complete Example Session
# ============================================
# PART 1: CREATE THE SET
# ============================================
sudo ipset create blocklist hash:net maxelem 100000
# ============================================
# PART 2: POPULATE THE SET
# ============================================
sudo ipset add blocklist 203.0.113.0/24
sudo ipset add blocklist 198.51.100.0/24
sudo ipset add blocklist 192.0.2.10
# ============================================
# PART 3: VERIFY THE SET
# ============================================
sudo ipset list blocklist
# Output shows the type, the members, and the number of entries
# ============================================
# PART 4: REFERENCE THE SET IN IPTABLES
# ============================================
sudo iptables -I INPUT -m set --match-set blocklist src -j DROP
# ============================================
# PART 5: VERIFY THE RULE
# ============================================
sudo iptables -L INPUT -n -v | grep blocklist
# Output shows the rule with the set match
# ============================================
# PART 6: TEST THE BLOCKLIST
# ============================================
# From a blocked address: the connection is dropped
# From an allowed address: the connection succeeds
# ============================================
# PART 7: SAVE THE SET
# ============================================
sudo ipset save > /etc/ipset.conf
# ============================================
# PART 8: RESTORE THE SET
# ============================================
sudo ipset restore -exist < /etc/ipset.conf
# ============================================
# PART 9: SAVE WITH THE PERSISTENT SERVICE (DEBIAN)
# ============================================
sudo netfilter-persistent save
# ============================================
# PART 10: ENABLE THE SERVICE
# ============================================
sudo systemctl enable netfilter-persistent
The ten parts demonstrate the complete practical configuration: creation, population, verification, iptables reference, rule verification, testing, saving, restoring, saving with the persistent service, and enabling the service. The critical steps are Part 4 (the rule reference) and Part 7 (the save), because the rule is inert without the set and the set is lost without the save.
Quick Reference
ipset Commands
| Command | Purpose |
|---|---|
ipset create <name> <type> maxelem <n> | Create a set |
ipset add <name> <element> | Add an element |
ipset del <name> <element> | Remove an element |
ipset list <name> | Show the set |
ipset save > file | Save all sets |
ipset restore < file | Restore sets |
ipset destroy <name> | Delete a set |
iptables Integration
| Command | Purpose |
|---|---|
-m set --match-set <name> src | Match source address |
-m set --match-set <name> dst | Match destination address |
-j SET --add-set <name> src | Add source to set |
Persistence Methods
| System | Save Command | Restore Service |
|---|---|---|
| Debian/Ubuntu | netfilter-persistent save | netfilter-persistent |
| RHEL/Rocky | ipset save > /etc/sysconfig/ipset | ipset |
| Generic | ipset save > file | ipset restore < file |
Verification
| Command | Purpose |
|---|---|
ipset list | Show all sets |
ipset test <name> <element> | Test an element |
iptables -L -n -v | Show rules with set references |
Best Practices
โ Do This:
# Create the set before the iptables rule
ipset create blocklist hash:net # โ
# Reference the set with the set match
iptables -I INPUT -m set --match-set blocklist src -j DROP # โ
# Save the set for persistence
ipset save > /etc/ipset.conf # โ
# Restore at boot before the iptables rules
ipset restore -exist < /etc/ipset.conf # โ
# Use -exist to ignore duplicate sets
ipset restore -exist < /etc/ipset.conf # โ
# Enable the persistent service
systemctl enable netfilter-persistent # โ
โ Don’t Do This:
# Add the iptables rule before the set exists
iptables -I INPUT -m set --match-set blocklist src -j DROP # โ Fails
# Forget to save the set
# The set is lost on reboot and the rule fails to load # โ
# Restore the sets after the iptables rules
# The rules fail to load because the sets do not exist # โ
# Use the wrong set type for networks
ipset create blocklist hash:ip # Cannot add networks # โ
# Forget the -exist flag on restore
# Duplicate sets cause errors # โ
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Rule fails to load | Set does not exist | Create the set first |
| Set lost on reboot | Not saved | ipset save and enable the service |
| Rule fails after reboot | Sets restored after rules | Order the services correctly |
| Cannot add network to hash:ip | Wrong type | Use hash:net |
| Restore fails with duplicate | Set already exists | Use -exist |
Real-World Examples
1. Create a blocklist set
ipset create blocklist hash:net maxelem 100000
2. Add a network
ipset add blocklist 203.0.113.0/24
3. Reference in iptables
iptables -I INPUT -m set --match-set blocklist src -j DROP
4. Save the set
ipset save > /etc/ipset.conf
5. Restore the set
ipset restore -exist < /etc/ipset.conf
6. Debian persistent save
netfilter-persistent save
7. Debian enable service
systemctl enable netfilter-persistent
8. RHEL save
ipset save > /etc/sysconfig/ipset
9. RHEL enable service
systemctl enable ipset
10. Test an element
ipset test blocklist 203.0.113.5
Visual
The ipset and iptables Layers
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THE SET AND THE RULE ARE SEPARATE LAYERS โ
โ โ
โ ipset layer: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ ipset create blocklist hash:net โ โ
โ โ ipset add blocklist 203.0.113.0/24 โ โ
โ โ ipset add blocklist 198.51.100.0/24 โ โ
โ โ โ โ
โ โ โ data structure in the kernel โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โ referenced by โ
โ โผ โ
โ iptables layer: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ iptables -I INPUT -m set --match-set blocklist src -j DROPโ
โ โ โ โ
โ โ โ rule reads from the set โ โ
โ โ โ single rule; no per-address rules โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The Dependency Order
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THE SET MUST EXIST BEFORE THE RULE โ
โ โ
โ โ
Correct order: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ 1. ipset create blocklist hash:net โ โ
โ โ 2. iptables -I INPUT -m set --match-set blocklist ... โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โ Wrong order: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ 1. iptables -I INPUT -m set --match-set blocklist ... โ โ
โ โ 2. ipset create blocklist hash:net โ โ
โ โ โ the rule fails to load: set does not exist โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Persistence Sequence
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SAVE โ RESTORE AT BOOT โ RULES LOAD โ
โ โ
โ Runtime: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ ipset create blocklist hash:net โ โ
โ โ ipset add blocklist 203.0.113.0/24 โ โ
โ โ iptables -I INPUT -m set --match-set blocklist ... โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ Save: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ ipset save > /etc/ipset.conf โ โ
โ โ iptables-save > /etc/iptables/rules.v4 โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ Boot: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ 1. ipset restore < /etc/ipset.conf โ โ
โ โ 2. iptables-restore < /etc/iptables/rules.v4 โ โ
โ โ โ the set exists before the rule is loaded โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| Set creation | ipset create <name> <type> maxelem <n> |
| Set population | ipset add <name> <element> |
| iptables match | -m set --match-set <name> src |
| iptables target | -j SET --add-set <name> src |
| Save | ipset save > file |
| Restore | ipset restore -exist < file |
| Debian persistence | netfilter-persistent save |
| RHEL persistence | ipset save > /etc/sysconfig/ipset |
| Dependency order | Set before rule |
| Boot order | Set restore before rule restore |
Key takeaways:
- The set must be created before the iptables rule. The rule references the set by name, and the kernel resolves the name when the rule is loaded. If the set does not exist, the rule fails to load with an error .
- The
hash:nettype is for networks, andhash:ipis for hosts. The type determines what the set can store, and the wrong type produces an error when an element of the wrong shape is added . - The set must be saved for persistence. The
ipset savecommand writes the set to a file, and theipset restorecommand reads it back. The Debiannetfilter-persistentservice and the RHELipsetservice automate the restore at boot . - The boot order matters. The sets must be restored before the iptables rules that reference them. On Debian, the
netfilter-persistentservice handles both, and it restores the sets first . On RHEL, theipsetservice must be ordered before theiptablesservice. - The
SETtarget writes to the set. The-j SET --add-set <name> srctarget adds the packet’s address to the set, which is the mechanism for dynamic blocklists . The rule that reads the set is separate from the rule that writes to it. - The
-existflag prevents duplicate-set errors. Theipset restore -existcommand ignores the error when the set already exists, which is useful for repeated restores .
Remember: The practical ipset configuration is two layers and a persistence step. The ipset layer creates and populates the set. The iptables layer references the set with the set match. The persistence layer saves the set and restores it before the rules. The set must exist before the rule, and the set must be saved for the reboot. The hash:net type is for networks, the hash:ip type is for hosts, and the SET target is for dynamic updates. The result is a firewall that blocks thousands of addresses with a single rule and a set that survives the reboot.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!