Block malicious IPs at the Linux kernel level using ipset and iptables. Packets from known attackers are dropped before they reach any application — whether that's a web server, mail server, database, or game server.
A cron job pulls the latest threat data from SikkerAPI's Blacklist API, bulk-loads it into an ipset, and atomically swaps it in with zero downtime. See the full parameter reference or check pricing for tier limits.
Use this when you need to protect services beyond just HTTP, or when you want blocking at the network layer rather than the application layer. For Nginx-specific blocking, see the Nginx integration instead.
# Every night at 3 AM: # 1. Fetch latest threat IPs from SikkerAPI curl → /tmp/blocklist.txt # 2. Bulk-load into a temporary ipset ipset restore → sikker4_tmp # 3. Atomic swap (zero downtime) ipset swap sikker4_tmp sikker4 # 4. iptables rule already references sikker4 iptables -m set --match-set sikker4 src -j DROP
The script handles fetching, splitting IPv4/IPv6, bulk-loading via ipset restore, atomic swap, and persistence across reboots.
Store your key in a file readable only by root, or export it as an environment variable.
Run the script once manually to create the ipsets and verify they populate correctly.
Create the iptables and ip6tables rules that reference the ipsets. These only need to be added once — the script updates the sets behind them atomically.
Pull your full tier limit once per day. The blacklist is sorted by confidence score (highest first), then by recency — so you always get the most dangerous IPs first.
$ sudo curl -o /usr/local/bin/sikkerapi-ipset-update \ "https://sikkerapi.com/iptables/sikkerapi-ipset-update.sh" $ sudo chmod +x /usr/local/bin/sikkerapi-ipset-update
$ echo "sk_free_your_key_here" | sudo tee /etc/sikkerapi.key $ sudo chmod 600 /etc/sikkerapi.key
$ sudo sikkerapi-ipset-update SikkerAPI: blocklist updated (4832 IPv4, 167 IPv6)
# Block IPv4 $ sudo iptables -I INPUT -m set --match-set sikker4 src -j DROP # Block IPv6 $ sudo ip6tables -I INPUT -m set --match-set sikker6 src -j DROP # Save rules (Debian/Ubuntu) $ sudo netfilter-persistent save # Save rules (RHEL/CentOS) $ sudo service iptables save
$ echo "0 3 * * * root /usr/local/bin/sikkerapi-ipset-update" \ | sudo tee /etc/cron.d/sikkerapi
The naive approach — flushing a live ipset and re-adding IPs one by one — leaves a window where your server is unprotected. Our script uses a different strategy:
This means there is zero downtime during updates. The iptables rule references the set by name, and the swap happens in a single kernel operation.
# Create temp set and bulk-load ipset restore <<EOF create sikker4_tmp hash:ip family inet ... add sikker4_tmp 203.0.113.42 add sikker4_tmp 198.51.100.17 ... (thousands more) EOF # Atomic swap — instant, no gap ipset swap sikker4_tmp sikker4 # Clean up ipset destroy sikker4_tmp
The SikkerAPI blacklist returns both IPv4 and IPv6 addresses. The script automatically splits them into separate sets: sikker4 (IPv4) and sikker6 (IPv6). Each needs its own iptables/ip6tables rule.
If your server doesn't use IPv6, disable it to save a small amount of memory and skip the second set entirely.
# Both sets are created automatically
sudo iptables -I INPUT -m set --match-set sikker4 src -j DROP
sudo ip6tables -I INPUT -m set --match-set sikker6 src -j DROP$ SIKKERAPI_IPV6=false sudo sikkerapi-ipset-update # Or in cron: 0 3 * * * root SIKKERAPI_IPV6=false /usr/local/bin/sikkerapi-ipset-update
# Only fetch IPv4 from the API (saves quota if you have few IPv6) $ SIKKERAPI_EXTRA="&ipVersion=4" sudo sikkerapi-ipset-update
Control which IPs are included using the SIKKERAPI_SCORE and SIKKERAPI_EXTRA environment variables. The scoreMinimum parameter controls the confidence threshold:
| Score | Suggested Use |
|---|---|
| 90+ | Very high confidence. Suitable for hard-blocking in most environments. Always review your logs periodically for false positives. |
| 70-89 | High confidence. Good default for most setups. Review your logs periodically for false positives. |
| 50-69 | Moderate confidence. Consider rate limiting or logging instead of hard-blocking. |
All Blacklist API filters are available via SIKKERAPI_EXTRA. See the full parameter reference for the complete list.
# Default: 70 (high confidence) $ SIKKERAPI_SCORE=90 sudo sikkerapi-ipset-update # More aggressive (may include false positives) $ SIKKERAPI_SCORE=50 sudo sikkerapi-ipset-update
# Only SSH attackers $ SIKKERAPI_EXTRA="&protocols=ssh" \ sudo sikkerapi-ipset-update # SSH + HTTP attackers $ SIKKERAPI_EXTRA="&protocols=ssh,http" \ sudo sikkerapi-ipset-update
# Only block IPs from specific countries $ SIKKERAPI_EXTRA="&onlyCountries=CN,RU" \ sudo sikkerapi-ipset-update # Exclude your own country $ SIKKERAPI_EXTRA="&exceptCountries=US,CA" \ sudo sikkerapi-ipset-update
Each IP returned from the Blacklist API counts against your daily blacklist quota (separate from your lookup quota). Plan your refresh frequency around your tier's limits.
| Tier | Blacklist IPs/Day |
|---|---|
| Free | 5,000 |
| Basic | 50,000 |
| Small Business | 75,000 |
| Medium Business | 150,000 |
| Large Business | 350,000 |
Pull your full tier limit once per day. The blacklist is sorted by confidence score (highest first), then by recency — so you always get the most dangerous IPs with the most recently active ones prioritized among equal scores. One daily pull gives you maximum coverage without wasting quota.
The script automatically detects when the list hasn't changed and skips the swap, so running it more often than necessary is harmless (but still costs quota).
$ curl -sI \ -H "Authorization: Bearer $API_KEY" \ "https://api.sikkerapi.com/v1/key/blacklist?plaintext=true&limit=1" \ | grep -i x-blacklist X-Blacklist-Limit: 5000 X-Blacklist-Used: 0 X-Blacklist-Remaining: 5000
ipsets live in kernel memory and are lost on reboot. The script automatically saves sets to disk after each update. To restore them at boot, use one of these approaches depending on your distro.
The iptables rules also need to persist. Most distros use netfilter-persistent (Debian/Ubuntu) or iptables-services (RHEL/CentOS).
Important: ipsets must be restored before iptables rules, otherwise iptables will fail because the referenced sets don't exist yet.
# Install ipset-persistent sudo apt install ipset-persistent # Save current sets sudo ipset save > /etc/ipset.d/sikkerapi.conf # Sets auto-restore before iptables at boot
# Save sets manually sudo ipset save > /etc/ipset.conf # Add to rc.local or create a systemd unit: [Unit] Description=Restore ipset rules Before=iptables.service [Service] Type=oneshot ExecStart=/usr/sbin/ipset restore -f /etc/ipset.conf [Install] WantedBy=multi-user.target
After running the script, check that the sets are populated and the iptables rules are in place.
$ sudo ipset list sikker4 -t Name: sikker4 Type: hash:ip Header: family inet hashsize 4096 maxelem 131072 Size in memory: 198432 Number of entries: 4832
$ sudo iptables -L INPUT -n --line-numbers | head -5 Chain INPUT (policy ACCEPT) num target prot source destination 1 DROP all 0.0.0.0/0 0.0.0.0/0 match-set sikker4 src
$ sudo ipset test sikker4 203.0.113.42 203.0.113.42 is in set sikker4.
$ sudo iptables -L INPUT -v -n | grep sikker 1234 56K DROP all -- * * 0.0.0.0/0 0.0.0.0/0 match-set sikker4 src