Important
This setup forces iptables-legacy (not nftables) and installs a custom-built xt_geoip_query tool written in C to properly read modern GeoIP databases (xtables-addons ≥ 3.20).
The script does not modify firewall rules automatically; it only echoes recommended examples.
Caution
If you use Docker or containerized services, switching to iptables-legacy can temporarily break container networking.
This happens because Docker manages its own NAT and MASQUERADE rules, which can be lost when iptables backends change or modules are reloaded.
SEE NOTES BELOW.
This script automates configuring GeoIP filtering for iptables.
It installs dependencies, builds and loads the xt_geoip kernel module, compiles a working GeoIP lookup utility, and verifies that lookups return the correct ISO country code.
Supports colored terminal output using ANSI escape codes. 😎
Run the script as root or with sudo.
Starting with xtables-addons 3.20, the binary format of GeoIP .iv4 and .iv6 files changed slightly.
The original xt_geoip_query shipped with older versions fails to read these files correctly on modern systems, returning incorrect country codes (e.g., AE instead of US for Google DNS).
To fix this, the installer compiles a custom C utility that reads the modern binary structure directly, without relying on outdated headers or deprecated logic.
This ensures accurate results for both IPv4 and IPv6 lookups and aligns with the endian layout used by current database builders (xt_geoip_build).
This script supports the following distributions (and derivatives):
| Distro Family | Package Manager | Tested On | Notes | 
|---|---|---|---|
| Debian / Ubuntu | apt | 
Debian 12 (Bookworm), Ubuntu 22.04+ | Installs xtables-addons-dkms & headers automatically | 
| RHEL / CentOS / Fedora | dnf | 
AlmaLinux 9, Fedora 39 | Uses system kernel-devel for matching build | 
| Arch / Manjaro | pacman | 
Arch Linux (2025.09 snapshot) | Requires base-devel & linux-headers | 
| Others | — | — | May work if xtables-addons and xt_geoip are available and compatible | 
- Installs required build tools and dependencies
 - Ensures the system is using the 
iptables-legacybackend (not nftables) - Installs matching Linux kernel headers
 - Downloads and compiles 
xtables-addonsversion 3.25 from inai.de - Verifies that 
/usr/share/xt_geoipcontains valid.iv4/.iv6GeoIP binary files - Builds and installs 
/usr/local/bin/xt_geoip_query, a custom binary parser for.iv4/.iv6files - Performs a quick lookup test using 
8.8.8.8— if successful, it should display US - Echoes example 
iptablesrules for allowing local and U.S. traffic (no rules are actually applied) 
iptables -F
iptables -I INPUT -i lo -j ACCEPT
iptables -I INPUT -s 10.0.0.0/8 -j ACCEPT
iptables -I INPUT -s 172.16.0.0/12 -j ACCEPT
iptables -I INPUT -s 192.168.0.0/16 -j ACCEPT
iptables -I INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -I INPUT -m geoip --src-cc US -j ACCEPT
iptables -P INPUT DROP
DOCKER-USERis evaluated before Docker’s own rules.
# Create (if missing) and clear DOCKER-USER
iptables -N DOCKER-USER 2>/dev/null || true
iptables -F DOCKER-USER
# Allow established and local RFC1918 sources
iptables -I DOCKER-USER 1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -I DOCKER-USER 2 -s 10.0.0.0/8 -j ACCEPT
iptables -I DOCKER-USER 3 -s 172.16.0.0/12 -j ACCEPT
iptables -I DOCKER-USER 4 -s 192.168.0.0/16 -j ACCEPT
# Allow only US; everything else to containers is dropped
iptables -I DOCKER-USER 5 -m geoip --src-cc US -j ACCEPT
iptables -A DOCKER-USER -j DROP
iptables -I INPUT -m geoip --src-cc XX -j DROPReplace XX with the ISO 3166-1 alpha-2 country code to block.
iptables -I INPUT -m geoip ! --src-cc YY -j DROPReplace YY with the country code you want to allow.
No such file or directory
iptables v1.8.7 (nf_tables): Could not read geoip database
root@vmd155394:/usr/share/xt_geoip#