Ponieważ z modułem GeoIP dla iptables występują problemy głównie w jego dostępności w wielu dystrybucjach, szukałem rozwiązania, jak blokować ruch z określonych krajów, z wielką pomocą przyszła strona http://ipdeny.com/ipblocks, która zawiera listę adresów IP podzielonych na strefy – kody krajów zgodne z ISO-3166. W skrypcie wykorzystuję ipset, który jest dostępny od kernela 2.4, a sama aplikacja do zarządzania listami, również ipset, może wymagać doinstalowania. Poniżej przedstawiam skrypt, który zastępuje mi GeoIP.
#!/bin/bash
Location="/scripts";
Countries="${Location}/Countries";
Zones="${Countries}/zones";
ZonesG="${Zones}/*";
Control=100000;
function DatabaseUpdate {
mkdir -p
wget http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz -O /scripts/Countries/all-zones.tar.gz
cd /scripts/Countries/zones
tar xzf /scripts/Countries/all-zones.tar.gz
}
function CreateZones {
for Zone in ${ZonesG}; do {
IPSetName=$(echo "${Zone}"|grep -Eo '[a-z][a-z]\.zone')
ipset create ${IPSetName} nethash -q;
for IPNetwork in $(cat ${Zone}); do {
ipset add ${IPSetName} ${IPNetwork} -q;
} done
} done
}
function RemoveSets {
for Zone in $(ipset -l -n | sort -u); do {
ipset destroy ${Zone};
} done
}
function CheckDatabase {
if [ "$(find ${ZonesG} -type f -mtime +7 | wc -l)" -gt 0 ]; then {
echo "Database updating";
DatabaseUpdate;
RemoveSets;
CreateZones;
} else {
echo "Database is up to date";
} fi
if [ "$(echo $Control)" == "$(CheckSets)" ]; then {
echo "Sets are OK";
} else {
echo "Sets corrupted"; CreateZones;
} fi;
}
function AddFirewallRules {
for ISOCode in ru af cn in iq; do {
ISOCode=$(echo ${ISOCode}|tr [A-Z] [a-z]);
iptables -A INPUT -m set --match-set ${ISOCode}.zone src -m comment --comment "Block countries" -j DROP;
} done
}
function CheckSets {
for ZoneFile in $(ls ${Zones} -1); do {
if [ "$(ipset -q -l -n ${ZoneFile} | wc -L;)" == "0" ]; then {
Control=$[${Control} -1];
} fi
} done
echo ${Control};
}
function Run {
CheckDatabase
AddFirewallRules
}
Run