Skip to content

Instantly share code, notes, and snippets.

@angelflo
Forked from mkorthof/ipset-country.md
Created February 5, 2018 07:20
Show Gist options
  • Save angelflo/e33bde4a71554d3a486fd520d344af12 to your computer and use it in GitHub Desktop.
Save angelflo/e33bde4a71554d3a486fd520d344af12 to your computer and use it in GitHub Desktop.
Block countries using iptables + ipset + ipdeny.com
#!/bin/sh
# ipset-country
# Block countries using iptables + ipset + ipdeny.com
# run this script from cron, e.g. /etc/cron.daily
# to run on boot you can also add it to e.g. /etc/rc.local
# please note: this script will insert an iptables REJECT
# rule as second to last in the INPUT chain for ipset
# specify countries to block as ISOCODE,Name
# multiple entries should be seperated by semicolon
# For example: "CN,China; United States,US Russia,RU"
# alternative script: https://github.com/tokiclover/dotfiles/blob/master/bin/ips.bash
country="CN,China"
iptables="/etc/iptables/rules.v4"
# using aggregated block zone files which are smaller
# ( full zone files: ".../data/countries/<iso>.zone" )
urlipdeny="http://www.ipdeny.com/ipblocks/data/aggregated"
log="/var/log/ipset-country.log"
#log="/dev/null 2>&1"
# ipset cmds: "ipset list", ipset test setname <ip>", "ipset flush" "destroy"
IFS=";"
for c in $country; do
iso="$( echo "$c" | tr '[:upper:]' '[:lower:]' | cut -d"," -f 1 | sed -e 's/\(^ \+\| \+$\)//g' )"
cname="$( echo "$c" | tr '[:upper:]' '[:lower:]' | cut -d"," -f 2 | sed -e 's/\(^ \+\| \+$\)//g' -e 's/ /_/g' )"
zfile="${iso}-aggregated.zone"
# create a new set using type hash
{ ipset list -terse "$cname" >/dev/null 2>&1 || ipset create "$cname" hash:net; } && ipsc="OK" || ipsc="NOK"
echo "$( date +%F\ %T ) ipset: create set \"$cname\" - $ipsc"
# download zone file and verify using md5sum
wget -q -O "/tmp/$zfile.$$" "$urlipdeny/$zfile"
md5src="$( wget -q -O - "$urlipdeny/MD5SUM" | grep "$zfile" | cut -d" " -f 1 )"
md5chk="$( md5sum "/tmp/$zfile.$$" | cut -d" " -f 1 )"
if [ "$md5src" = "$md5chk" ]; then
mv "/tmp/$zfile.$$" "/etc/iptables/$zfile" && zf="OK" || zf="NOK"
echo "$( date +%F\ %T ) zonefile: get \"$zfile\" - $zf"
# add blocks to ipset
c=0; while read l; do ipset -A -exist -quiet "$cname" "$l" && c=$((co+1)); done < "/etc/iptables/$zfile" >/dev/null 2>&1 && \
ipsa="OK" || ipsa="NOK"
echo "$( date +%F\ %T ) ipset: add \"$zfile\" to \"$cname\" - $ipsa - $c entries"
# restore iptables and insert rules for ipset
/sbin/iptables-restore < "$iptables" && ipr="OK" || ipr="NOK"
echo "$( date +%F\ %T ) iptables: restore - $ipr"
# rulenum=$(( $(iptables -S INPUT|wc -l) - 1 ))
# if [ "$rulenum" -gt "0" ] &&
rulenum=3
if [ "$cname" != "" ]; then
[ ! /sbin/iptables -n -L LOGIPS >/dev/null 2>&1 ] && { /sbin/iptables -N LOGIPS && iptn="OK" || iptn="NOK"; } || iptn="already exists"
/sbin/iptables -A LOGIPS -m limit --limit 10/min -j LOG --log-prefix "IPS REJECT: " --log-level 6 && iptl="OK" || iptl="NOK"
/sbin/iptables -A LOGIPS -j REJECT --reject-with icmp-port-unreachable && iptr="OK" || iptr="NOK"
/sbin/iptables -I INPUT "$rulenum" -p tcp -m set --match-set "$cname" src -j LOGIPS && ipti="OK" || ipti="NOK"
if ! iptables -n -L LOGIPS >/dev/null 2>&1; then
/sbin/iptables -I INPUT "$rulenum" -p tcp -m set --match-set "$cname" src -j REJECT --reject-with icmp-port-unreachable && \
ipti="OK" || ipti="NOK"; iptn="disabled"; iptl="disabled"; iptr="disabled"; fi
echo "$( date +%F\ %T ) iptables: create log chain - $iptn"
echo "$( date +%F\ %T ) iptables: append log rule - $iptl, append reject rule - $iptr"
echo "$( date +%F\ %T ) iptables: insert ipset rule - $ipti"
fi
fi
[ -f "/tmp/$zfile.$$" ] && rm "/tmp/$zfile.$$"
done >>"$log"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment