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