blocking countries via IP-Tables
Just improved a small snipped to use on my own server. Its blocks incoming Traffic from all over the world, keeping the door open for requests from Germany. Use it if you want to.
#!/bin/sh
### Restrict all countries and allow traffic from listed countries only
###
### This example allows IPs from Germany, Switzerland, Austria and France
###
### author anonymous, improved by MeErWissen, Sven Hering (2026-04-05)
###
### used CIDR-list:
###
### IPDENY.COM: "Powered by IPDENY.COM IP database."
### https://www.ipdeny.com/copyright.php
###
### Use ISO code separated by space ###
# Germany, Switzerland, Austria and France (my hosting country)
ISO="de at ch fr"
### Set PROGRAMS ###
IPT=/sbin/iptables
WGET=/usr/bin/wget
EGREP=/bin/egrep
# Country specific log message
DROPMSG='DROP (outside '$ISO') '
### No editing below ###
ACCEPTLIST="countryok"
ZONEROOT="/tmp/iptables-country"
# 2021-10-19 -> HTTPS has to be disabled because the certificate is invalid atm
#DLROOT="http://www.ipdeny.com/ipblocks/data/aggregated"
# 2026-04-05 -> HTTPS is working again
DLROOT="https://www.ipdeny.com/ipblocks/data/aggregated"
cleanOldRules(){
$IPT -w -F $ACCEPTLIST 2>/dev/null
$IPT -w -D INPUT -j $ACCEPTLIST 2>/dev/null
$IPT -w -X $ACCEPTLIST 2>/dev/null
}
# create a dir
[ ! -d $ZONEROOT ] && /bin/mkdir -p $ZONEROOT
# clean old rules
cleanOldRules
# create a new iptables list
$IPT -N $ACCEPTLIST
# Basic assumptions
# Keep localhost open
$IPT -w -A $ACCEPTLIST -s 127.0.0.1/8 -j RETURN
# Keep local nets open if the system is on any of these networks!
$IPT -w -A $ACCEPTLIST -s 10.0.0.1/8 -j RETURN
$IPT -w -A $ACCEPTLIST -s 172.16.0.0/12 -j RETURN
$IPT -w -A $ACCEPTLIST -s 192.168.0.1/16 -j RETURN
# Allow established/related connections (replies to outbound traffic)
$IPT -A $ACCEPTLIST -m state --state ESTABLISHED,RELATED -j RETURN
# Possible additions:
# Allow MAIL-Ports (fail2ban is recommended)
$IPT -A $ACCEPTLIST -p tcp -m tcp --dport 25 -j RETURN
$IPT -A $ACCEPTLIST -p tcp -m tcp --dport 465 -j RETURN
$IPT -A $ACCEPTLIST -p tcp -m tcp --dport 587 -j RETURN
# Disabled unsecure ports or obsolete protocols
#$IPT -A $ACCEPTLIST -p tcp -m tcp --dport 110 -j RETURN
#$IPT -A $ACCEPTLIST -p tcp -m tcp --dport 143 -j RETURN
#$IPT -A $ACCEPTLIST -p tcp -m tcp --dport 993 -j RETURN
#$IPT -A $ACCEPTLIST -p tcp -m tcp --dport 995 -j RETURN
# Allow SSH (fail2ban is recommended)
#$IPT -A $ACCEPTLIST -p tcp -m tcp --dport 22 -j RETURN
for c in $ISO
do
# local zone file
tDB=$ZONEROOT/$c.zone
# get fresh zone file into .tmp
$WGET -O $tDB.tmp $DLROOT/$c-aggregated.zone -o /dev/null || exit 1
# sort list by CIDR (unnecessary just for optical reasons)
sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 $tDB.tmp > $tDB
# count lines for information only, remove next 2 lines for a silent script
lcount=`wc -l < $tDB`
echo Inserting $lcount CIDRs \($c\), stay tuned...
# get each line
GOODCIDRs=$(egrep -v "^#|^$" $tDB)
for CIDRaccept in $GOODCIDRs
do
$IPT -w -A $ACCEPTLIST -s $CIDRaccept -j RETURN
done
done
# Log and Drop everything else
$IPT -w -A $ACCEPTLIST -j LOG --log-prefix "$DROPMSG"
$IPT -w -A $ACCEPTLIST -j DROP
# Insert chain in INPUT
$IPT -I INPUT -j $ACCEPTLIST
# Remove temp dir
rm -rf $ZONEROOT
exit 0
# How to enroll the script
## Save
# sudo mkdir -p /etc/iptables
# sudo iptables-save > /etc/iptables/rules.v4
## Restore test
# sudo iptables-restore < /etc/iptables/rules.v4
## Create service
#cat > /etc/systemd/system/iptables-restore.service << 'EOF'
#[Unit]
#Description=Restore iptables rules
#Before=network.target
#[Service]
#Type=oneshot
#ExecStart=/sbin/iptables-restore /etc/iptables/rules.v4
#[Install]
#WantedBy=multi-user.target
#EOF
#sudo systemctl enable --now iptables-restore
sources: https://forums.centos.org, the origin might be https://forum.archive.openwrt.org

