SIEM & other integrations

Connect Q-Feeds to Linux (NFtables / IPtables)

Our open source installer detects whether your server runs nftables or iptables with ipset, loads the malware IP blocklist into dedicated sets, and schedules automatic updates so the host drops traffic from known malicious addresses.

The scripts are open source and live on GitHub: Q-Feeds/NFtables-IPtables-integration-script. Always take them from there so you get the current version. You need root access, outbound HTTPS to api.qfeeds.com and a Q-Feeds API token. See Get your threat feeds. The installer asks you to accept our Terms & Conditions and EULA before it does anything.

Prerequisites

  • OS: Linux with either nftables or iptables plus ipset
  • Distributions: Debian, Ubuntu, CentOS, RHEL, AlmaLinux, Rocky Linux, Fedora, openSUSE Leap, SLES, Arch Linux, Alpine
  • Privileges: root for install, updates and firewall changes
  • Feed: malware IP list (feed_type=malware_ip)
  • Packages: installed for you, so you do not have to prepare anything. For nftables that is nftables, curl, jq and util-linux. For iptables it is iptables, ipset, curl, jq and util-linux.

Optional test before you install:

curl -v -u api_token:YOUR_TOKEN "https://api.qfeeds.com/api?feed_type=malware_ip&limit=1000"

Get the scripts

git clone https://github.com/Q-Feeds/NFtables-IPtables-integration-script.git
cd NFtables-IPtables-integration-script
chmod +x qfeeds-installer.sh qfeeds-uninstaller.sh

No git on the server? Download the ZIP from the repository page and unpack it instead.

Install

sudo ./qfeeds-installer.sh

The installer detects your firewall backend, asks a handful of questions, installs the updater plus a cron job, and then runs a first full sync so the blocklist is active straight away. The questions, in order:

  1. Terms and EULA: type yes to continue.
  2. API token: your Q-Feeds token. The installer stops if you leave this empty.
  3. Feed type: default malware_ip. Only change this if we gave you a different feed type.
  4. IP limit: press Enter for no limit, which is what we recommend.
  5. Block incoming (default yes): drops traffic from blacklisted IPs to your server.
  6. Block outgoing (default no): drops traffic from your server to blacklisted IPs.
  7. Whitelist (optional): comma separated IPv4 and IPv6 addresses or CIDRs that must never be blocked. Put your own management IPs here so you cannot lock yourself out.
  8. Cron schedule: default */10 * * * *, so every ten minutes. Running often is fine, because the updater only calls the API when your licence allows a new update.

Warnings about CIDR notation while the feed is being pulled are harmless and can be ignored. If you rerun the installer on a host that already has a Q-Feeds cron entry, it asks before touching your crontab and keeps it unchanged by default. For unattended installs, set QFEEDS_SKIP_CRON=1 to skip that step without a prompt.

How it works

  • Backend detection: if the nft command is present the installer uses nftables, otherwise it falls back to iptables with ipset. The result is stored as BACKEND in the config file, and the updater and uninstaller follow it.
  • Isolated rules: nftables gets its own ip qfeeds and ip6 qfeeds tables. On iptables the blocking rules live in dedicated QFEEDS_INPUT and QFEEDS_OUTPUT chains, with a single tagged jump rule in INPUT and OUTPUT. Your existing firewall rules are never touched.
  • Two set types: individual addresses go into a hash set and the small number of CIDR ranges into a separate network set. That is what makes loading 400,000 or more addresses take seconds rather than minutes.
  • Whitelist first: whitelist rules are evaluated before the blacklist, so a whitelisted address is always accepted.
  • Full and diff sync: the first run loads the whole feed, later runs fetch only the additions and removals since your last pull. A full sync is only applied once valid data has been downloaded, so a failed fetch never leaves you unprotected.
  • Self healing: if the local set is empty or much smaller than expected, for example after a reboot where rules were not persisted, the updater rebuilds it with a full sync instead of patching an empty set. It also forces a full sync every 24 hours by default.
  • Licence based scheduling: before each run the updater checks when your licence allows the next update. If it is not time yet, it exits without calling the API.

Verify

nftables

sudo nft list table ip qfeeds
sudo nft list set ip qfeeds qfeeds_blacklist_v4 | grep -oP '\d+\.\d+\.\d+\.\d+' | wc -l
sudo nft list set ip qfeeds qfeeds_blacklist_v4_nets | head -20
sudo nft list table ip6 qfeeds

iptables with ipset

sudo ipset list -t | grep -A4 qfeeds
sudo ipset list qfeeds_blacklist_v4 | tail -n +9 | wc -l
sudo iptables -L INPUT -n --line-numbers | grep qfeeds
sudo iptables -L QFEEDS_INPUT -n
sudo ip6tables -L QFEEDS_INPUT -n

Both backends

sudo tail -20 /var/log/qfeeds_blocklist.log
sudo grep -i error /var/log/qfeeds_blocklist.log
sudo crontab -l | grep qfeeds
sudo /usr/local/bin/update_qfeeds_blocklist.sh
sudo QFEEDS_FORCE_UPDATE=1 /usr/local/bin/update_qfeeds_blocklist.sh

The last command forces a full sync and ignores the licence schedule, which is the quickest way to confirm that everything works end to end.

Configuration

All settings live in /etc/qfeeds/qfeeds_config.conf. You can edit that file directly instead of rerunning the installer; changes take effect on the next run.

SettingDescriptionDefault
BACKENDFirewall backend, nftables or iptablesdetected
API_TOKENYour Q-Feeds API tokenrequired
FEED_TYPEFeed to fetchmalware_ip
LIMITMaximum number of IPs, empty means no limitempty
BLOCK_INCOMINGBlock traffic from blacklisted IPsyes
BLOCK_OUTGOINGBlock traffic to blacklisted IPsno
WHITELIST_V4Comma separated IPv4 addresses or CIDRsempty
WHITELIST_V6Comma separated IPv6 addresses or CIDRsempty
LOG_FILEPath to the log file/var/log/qfeeds_blocklist.log
FULL_SYNC_MAX_AGESeconds before a full sync is forced again86400

File and directory locations

  • Configuration: /etc/qfeeds/qfeeds_config.conf
  • Sync state: /etc/qfeeds/.last_sync and /etc/qfeeds/.last_count
  • Updater script: /usr/local/bin/update_qfeeds_blocklist.sh
  • Log: /var/log/qfeeds_blocklist.log
  • Lock file: /var/lock/qfeeds_blocklist.lock
  • Cron: root crontab
  • Persistence: netfilter-persistent when available, otherwise /etc/nftables.conf for nftables or /etc/ipset.conf with /etc/iptables.rules and /etc/ip6tables.rules for iptables

Uninstall

sudo ./qfeeds-uninstaller.sh

The uninstaller reads the configured backend and cleans up accordingly. On nftables it deletes the ip qfeeds and ip6 qfeeds tables with all their chains, rules and sets. On iptables it removes the tagged jump rules, flushes and deletes the QFEEDS_INPUT and QFEEDS_OUTPUT chains, and destroys every qfeeds_ set. In both cases it also removes the config directory, the updater script, the cron job, the log and the lock file. If the config file is gone it cleans up both backends to be safe.

System packages are left in place. Remove them yourself if you no longer need them:

  • Ubuntu/Debian: sudo apt-get -y remove ipset netfilter-persistent
  • CentOS/RHEL/Alma/Rocky: sudo yum -y remove ipset
  • Fedora: sudo dnf -y remove ipset
  • openSUSE/SLES: sudo zypper remove ipset
  • Arch: sudo pacman -R ipset

Be careful with iptables, nftables, curl and jq: other parts of your system almost certainly need them.

Troubleshooting

  • Sets are empty after installing: check sudo tail -50 /var/log/qfeeds_blocklist.log, confirm your API token, then run sudo QFEEDS_FORCE_UPDATE=1 /usr/local/bin/update_qfeeds_blocklist.sh.
  • "Not time yet. Next update scheduled at ...": this is normal. The cron job ran, but your licence does not allow a new update yet. The next run checks again.
  • Rules gone after a reboot: the updater saves rules automatically, and on the next run it notices the empty set and rebuilds it with a full sync. To be sure, check that netfilter-persistent is installed or that the nftables service is enabled.
  • "Batch nft -f failed. Falling back to per-command execution": harmless. It usually happens in LXC containers with a restricted netlink buffer. The fallback still loads 400,000 or more addresses in roughly ten seconds. The same goes for "Message too long".
  • "ipset restore failed": confirm ipset is present with command -v ipset and that the kernel module is loaded with lsmod | grep ip_set.
  • No rules visible in INPUT: on iptables the blocking rules sit in QFEEDS_INPUT. INPUT only holds the jump rule, tagged with the comment qfeeds. Check both with sudo iptables -L INPUT -n | grep qfeeds and sudo iptables -L QFEEDS_INPUT -n.
  • Installation fails with "Unable to locate package": distribution detection did not work. Install curl, jq and util-linux by hand, plus nftables or iptables with ipset, then run the installer again.
  • Support: support@qfeeds.com or the support page. Found a bug in the scripts? Open an issue in the GitHub repository.

Download the PDF manual View the scripts on GitHub

Evaluate our intelligence today!

Simplify your security operations, start your free Q-Feeds trial and experience the difference.

Activate free access