2018-05-28 23:59:02 +02:00
#!/bin/bash
# This script downloads a list of foreign countries' IP address ranges and it marks these IP ranges via ipset command.
# Author: bisco <bisco__AT__autistici__DOT_org>
# ipset solution has been suggested by Matt Wilcox script: https://mattwilcox.net/web-development/unexpected-ddos-blocking-china-with-ipset-and-iptables
set -e
### Variables
URL = "http://www.ipdeny.com/ipblocks/data/countries"
2019-03-04 21:49:26 +01:00
ZONES = "cn hk ru tw kp kr sg"
2018-05-28 23:59:02 +02:00
SCRIPTDIR = "/root/firewall"
ZONEDIR = " ${ SCRIPTDIR } /blocked_zones/ "
RULESFILE = " /tmp/iptables_rules- $( date +'%s' ) "
IPSET = $( which ipset)
IPTR = $( which iptables-restore)
IPTS = $( which iptables-save)
RM = $( which rm)
WGET = $( which wget)
MKDIR = $( which mkdir)
### End Variables
### Code.
### Please don't edit below unless if you know what you're doing.
### check_error function
### Check if things went all done when exit
check_error( )
{
if [ ! $? = 0 ] ; then
echo "====> ERROR!"
exit
fi
}
### trap built-in command
### Run "check_error" function on exit process status
trap check_error EXIT
### usage function
### Show help and exits
usage( )
{
echo " Usage: $0 [option] "
echo ""
echo "-c | --check : check all binaries and system are ok"
echo "-d | --download : download only the IP range lists"
echo " -b | --block : set the IP range lists into the ${ ZONES } chain "
echo "-h | --help : show this help and exits"
echo ""
}
### check_binary function
### This function checks if all binaries are properly installed on target system
check_binary( )
{
if [ " ${ IPSET } " = = "" ] || [ " ${ IPTR } " = = "" ] || [ " ${ RM } " = = "" ] || [ " ${ WGET } " = = "" ] || [ " ${ MKDIR } " = = "" ] ; then
echo "Some binaries not found. Please install: ipset, iptables-restore, rm, wget"
exit 1;
else
echo "All binaries are properly installed. Let's go on!"
fi
}
### prepare_system function
### This function handles all system operation needed.
prepare_system( )
{
# Create the $ZONEDIR directory. The "-p" flag to create the parents directories if needed and it doesn't show error if path exists.
${ MKDIR } -p " ${ ZONEDIR } "
### Remove old country zone files.
### The ${VARIABLE:?} syntax is useful to avoid wrong file deletion, if the variable content is empty.
### Examples:
### rm -rf "${EMPTY_VAR}"/* executes rm -rf /*
### rm -rf "${EMPTY_VAR:?}"/* raises an error
${ RM } -rf " ${ ZONEDIR : ? } " /*
### Save current iptables rules on temporary file
${ IPTS } > " ${ RULESFILE } "
}
### download_zones function
### This function downloads all the selected zones
download_zones( )
{
# Here there's a for cycle on an array of elements
for zone in $( echo " ${ ZONES [*] } " ) ;
do
echo " Downloading $zone .zone file " ;
2019-03-04 21:49:26 +01:00
${ WGET } --quiet -P " ${ ZONEDIR } " " ${ URL } / $zone .zone " ;
2018-05-28 23:59:02 +02:00
done
}
### create_chains function
### Create one set per IP range, specifying the hash type to "net"
create_chains( )
{
for chain in $( echo " ${ ZONES [*] } " ) ;
do
echo " Creating $chain chain " ;
2019-03-04 21:49:26 +01:00
${ IPSET } create -exist ${ chain } hash:net;
2018-05-28 23:59:02 +02:00
done
}
### populate_chains
### This function insert the IP range lists into relative chain
populate_chains( )
{
for chain in $( echo " ${ ZONES [*] } " ) ;
do
2019-03-04 21:49:26 +01:00
echo " Populating $chain " ;
2018-05-28 23:59:02 +02:00
for ip in $( cat $ZONEDIR /$chain .zone) ;
do
2019-03-04 21:49:26 +01:00
${ IPSET } add -exist $chain $ip ;
2018-05-28 23:59:02 +02:00
done ;
done
}
### reload_rules function
### Reload iptables rules saved during the prepare_system function
### Without reloading iptables rules, new IP ranges won't loaded
reload_rules( )
{
echo "Reloading iptables rules"
${ IPTR } < " ${ RULESFILE } "
}
### Main function
case $1 in
-c | --check)
check_binary; ;
-d | --download)
check_binary;
prepare_system;
download_zones; ;
-b | --block)
check_binary;
prepare_system;
download_zones;
create_chains;
populate_chains;
reload_rules; ;
-h | --help | *)
usage; ;
esac