#/bin/bash # Script to select a random server # from a list of servers (via a round robin DNS) # and rsync a bunch of files from that server # # Takes a list of DNS records, # and a list of source folders, # expands each DNS record to a list of IP Addresses # then picks a random IP to rsync the given folder # from (retrying a different server if rsync fails), # before moving on to the next DNS record. # # Used to pull various 0-day spam/malware signatures # for clamav. This caches the files locally, # and thus enables the internal-only mail servers # to pull these files from a local repo # # By Cris Haddad ##################### # SETTINGS # ##################### # An array of DNS records # which each resolve to a list of # rsync mirrors, 'round robin' style # NB Array index starts at ZERO RR_MIRRORS[0]="rsync.sanesecurity.net" #RR_MIRRORS[1]="clamav.securiteinfo.com" #RR_MIRRORS[2]="www.malwarepatrol.net" # Source folder on each remote server # make sure the array index matches # the server above! SOURCE_DIR[0]="sanesecurity" #SOURCE_DIR[1]="securesite" #SOURCE_DIR[2]="malwarepatrol" # Destination folder on local host # again make sure the array index matches # the server above! DESTINATION_DIR[0]="/ftp/pub/misc/malwaresigs/sanesecurity" #DESTINATION_DIR[1]="/ftp/pub/misc/malwaresigs/securesite" #DESTINATION_DIR[2]="/ftp/pub/misc/malwaresigs/malwarepatrol" # Text file with list of files to sync SYNC_FILE_LIST="/ftp/mirror/mirror.malwaresigs.conf" #number of attempts to rsync MAX_RETRIES="6" # Uncomment to enable debug output #DEBUG="TRUE" ################################# ## do not edit below this point # ################################# # a quick sanity check to make sure we have arrays # of matching lengths # we subtract 1 at thispoint so that we can use # this number later to iterate # through the array last_mirror=`expr ${#RR_MIRRORS[@]} - 1` last_dir=`expr ${#SOURCE_DIR[@]} - 1` if [ "$last_mirror" -ne "$last_dir" ]; then echo "ERROR: configured SOURCE_DIR count does not match RR_MIRRORS count"; exit 2; fi #now iterate through the arrays for i in `seq 0 $last_mirror` do current_mirrorset=${RR_MIRRORS[$i]} current_sourcedir=${SOURCE_DIR[$i]} current_destdir=${DESTINATION_DIR[$i]} if [ -n "$DEBUG" ]; then { echo "INFO: current mirror set is $current_mirrorset"; } fi if [ -n "$DEBUG" ]; then { echo "INFO: current source dir is $current_sourcedir";} fi #expand the round robin DNS to a list of IPs source_servers=`dig +ignore +short $current_mirrorset` #load the list of IPs into an array read -a server_array <<<$source_servers if [ -n "$DEBUG" ]; then { echo "INFO: Servers are:"; for i in ${server_array[@]}; do echo $i; done }; fi if [ -n "$DEBUG" ]; then { echo "DEBUG: Array length is: ${#server_array[@]}"; }; fi #array addresses start at zero, obviously last_entry=`expr ${#server_array[@]} - 1` if [ -n "$DEBUG" ]; then { echo "DEBUG: last entry is therefore : $last_entry"; }; fi if [ ! $last_entry -gt 0 ] ; then echo "ERROR: No mirrors found. This may be a temporary failure, but if it persists then there may be a problem. " exit 2 fi for j in `seq 1 $MAX_RETRIES` do #pick a random server random_selection=`shuf -i 0-$last_entry -n 1` if [ -n "$DEBUG" ]; then { echo "DEBUG: Randomly selected server number: $random_selection"; }; fi random_server=${server_array[$random_selection]} if [ -n "$DEBUG" ]; then { echo "INFO: Randomly selected server IP address: $random_server"; }; fi #let's get the DNS name, just for fun random_server_dns=`dig +short -x $random_server | sed 's/\.$//'` if [ -n "$DEBUG" ]; then { echo "INFO: Randomly selected server name: $random_server_dns"; }; fi if ( rsync --files-from=$SYNC_FILE_LIST -ctuz --timeout="60" --stats rsync://$random_server/$current_sourcedir $current_destdir &> /dev/null ); then #if ( rsync --files-from=$SYNC_FILE_LIST -ctuz --timeout="60" --stats rsync://$random_server/$current_sourcedir $current_destdir ); then if [ -n "$DEBUG" ]; then { echo "NOTICE: rsync success from server $random_server_dns IP $random_server on attempt $j "; }; fi break else if [ -n "$DEBUG" ]; then { echo "WARNING: rsync fail from server $random_server_dns IP $random_server on attempt $j "; }; fi fi if [ $j -eq $MAX_RETRIES ] ; then echo "ERROR: rsync failed - MAX_RETRIES exceeded" fi done done