#!/bin/bash if [[ "$1" == 'debug' ]]; then set -x; _DEBUG=$1; shift; fi if [[ "$1" == 'debug2' ]]; then set -xvT; _DEBUG=$1; shift; fi if [[ "$1" == 'trace' ]]; then _TRACE=$1; shift; fi #################################################################### # - Dynloader geo - ### List are taken from 'https://ipdeny.com/ipblocks' ### Updates are scheduled @ ~12:20,CET .. ### ### Prefer the 'aggregated' zone files in ### https://ipdeny.com/ipblocks/data/aggregated/-aggregated.zone ### as these subsummarize complete networks in CIDR format. ### ### is the country code of the list you want #------------------------- REALPATH=`realpath $0` WHERE=`dirname $REALPATH` ME=`basename $REALPATH` cd $WHERE #------------------------- . ../../system.conf . ../../watchermap.conf . ../../common.conf . ../../common.bashlib #------ API stuff ------------ #. ../../api/bash/sql.bashlib #------ Private stuff -------- . private.bashlib . $ME.conf trap cleanup 0 1 2 9 15 cleanup() { local funtag="[${FUNCNAME[0]}]" # UNCONDITIONALY fill-in to firewall # what's in $ZONE_DIR : echo "Updates: "$UPDATES : echo "Updated: "$UPDATED : echo "Missing: "$MISSING # Fill in what we got so far for zone in $ZONES do fill_ipset $zone done PROC_END=`date +%s%N` PROC_TIME=`echo "scale=3; ($PROC_END - $PROC_START)/10^6" | bc` logger "»»» $ME: Finished: $PROC_TIME ms'" printf " » %-15s ... finished in %'8.2f ms\n" $ME $PROC_TIME rm -f *.zone # Remove relicts in the hook-dir touch .lastrun } fill_db() { # Make SQL file from zone file and load SQL into DB # $1 Zone code (ru, cn, ...) local funtag="[${FUNCNAME[0]}]" local start end runtime local zone_sql=$POOL/$ME-$1.sql local table=ipset start=$(date +%s%3N) echo "$funtag for $ME/$1" awk -v table=$table \ -v zone=$1 \ -v zone_sql=$zone_sql ' { printf "INSERT or REPLACE into %s", table > zone_sql printf " (ip, zone)" > zone_sql printf " values (\"%s\",\"%s\");\n", $1 ,zone > zone_sql } ' zones/$1*.zone printf "$funtag Loading DB for %s/%s" $ME $1 $SQL < $zone_sql end=$(date +%s%3N) runtime=$(( end - start)) printf " ... Took %9d ms\n" $runtime } fill_ipset() { # $1 .. is the zone code: e.g. 'ru' for 'Russia', 'cn' for 'China' a.s.o ... local funtag="[${FUNCNAME[0]}]" local THIS_SET=geo-$1 local ZONEFILE=$ZONE_DIR/$1$AGG_SUF local LOADFILE="$POOL/ipset.Loadfile-"$THIS_SET local have_it fill_db $1 awk -v list=$THIS_SET -v settype="$SETTYPE" -v setopts="$SETOPTS" -v loadfile="$LOADFILE" ' /^[ \t]*[#]|^$/ { next } # Ignore comments and empty lines { IP[$1]=$1 } END { printf "-exist create %s %s %s\n", list, settype, setopts > loadfile for ( ip in IP ) { printf "add %s %s comment \"%s\"\n", list, ip, list > loadfile } } ' $ZONEFILE # Make IPSET on-the-fly ... if it does not already exists have_it=`ipset -n list | grep $THIS_SET` if [ -z "$have_it" ] # then mk-ipset $THIS_SET $SETTYPE $SETOPTS then mk-ipset_lowlevel $THIS_SET $SETTYPE $SETOPTS fi $IPSET flush $THIS_SET $IPSET -file $LOADFILE restore } #------------ Main ---------------- dump_runtime PROC_START=`date +%s%N` FIRSTRUN=0 UPDATES=0 UPDATED='' # Initialize database, if it does not exist [ ! -e $DB ] && $SQL < $SCHEMA_FILE if [ ! -d $ZONE_DIR ] then mkdir $ZONE_DIR (( FIRSTRUN++ )) fi logger "»»» $ME Starting ..." ### Housekeeping ########### # Step 1 # Delete zone files from $ZONE_DIR that no longer exist in $ZONES del_zones # Step 2 # Get news zones to $ZONE_DIR that are not exist as of $ZONES # «Note»: On first run retrieves everything freshly new_zones if [ $FIRSTRUN -ne 0 ]; then exit; fi # Finish up in cleanup() ### ### Updating ############### ### logger "»»» $ME Updating ..." # Step 3 (final step) if [ -f MD5SUM ] then mv MD5SUM .laststamp else touch .laststamp fi $WGET -N $DAT_URL/MD5SUM if [ ! -s MD5SUM ] then logger "[$ME] ERROR: Failed to download MD5SUM from $DAT_URL – keeping old lists" echo "ERROR: Could not retrieve MD5SUM, exiting..." exit 0 # Not tonight, Josephine ... fi fetchlist=`mk_fetchlist` if [ -z "$fetchlist" ] then echo "»»» [$ME]: No effective update available" logger "»»» [$ME]: No effecitve update available" exit else fetch_count=`wc -w <<< $fetchlist` echo "Update(s): $fetch_count, '$fetchlist'" logger "[$ME] Updatating $fetch_count zone files" fi #MD5stamp=`date --iso -r MD5SUM` #: echo "MD5SUM stamp : "$MD5stamp #LASTstamp=`date --iso -r .laststamp` #: echo "LAST stamp : "$LASTstamp #if [ "$LASTstamp" == "$MD5stamp" ] if cmp -s MD5SUM .laststamp then : echo no change, nothing to do ... logger "[$ME] No changes, exiting $DAT_URL/..." exit # no change, nothing to do ... fi # If we are reaching here, we are walking the update line ... # Check for updates ... logger "[$ME] Tracking $DAT_URL/..." for ZONEFILE in $fetchlist do MSG="Updating zone file $ZONEFILE from $DAT_URL" : echo $MSG logger "[$ME] $MSG" fetch_zone $ZONEFILE result=$? case $result in 0) (( UPDATES++ )) ;; 1) msg "Update of zone $zone failed" echo "$msg" logger "[$ME] $msg" ;; esac done # Report updates if [ $UPDATES -gt 0 ] then logger "[$ME] $UPDATES Updated: '$UPDATED'" else logger "[$ME] All zone files up-to-date" fi # New zones and updates applied in 'cleanup' on exit ... exit