GeorgeT93

pihole-gemini - Two-way Pi-hole lists sync

Mar 12th, 2019
1,206
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #! /bin/bash
  2. # Script was last updated 03-12-2019
  3.  
  4. SCRIPTVER="pihole-gemini v0.0.2.2a"
  5. # --------------------------------------------------------------------------------------------------------
  6. # This script was written to try and keep the white and black lists in sync between two Pi-holes.
  7.  
  8. # The script should be launched from /opt/pihole/gravity.sh
  9. # It should be called in the second to last line of the gravity.sh file and should be run as the user
  10. # configured for the sync process. In my case, I'm using user pi, so you would change the user from 'pi'
  11. # to the username you're using to sync the files (the user you're assigning to HAUSER in this script.)
  12.  
  13. # Example of the line to add as the second to last line of the /opt/pihole/gravity.sh file:
  14.  
  15. #       su -c '/usr/local/bin/pihole-gemini' - pi
  16.  
  17. # In the above example, you change the 'pi' at the end to your sync user, and it should appear directly
  18. # above the line that reads:
  19. #       "${PIHOLE_COMMAND}" status
  20. # in the /opt/pihole/gravity.sh file.
  21.  
  22. # --------------------------------------------------------------------------------------------------------
  23. # USER-DEFINED VARIABLES - START - Edit the values in this section to configure the script to your install.
  24.  
  25.     # User account - Should have sudo and ssh access, and a "matching" account should be set up on both Pi-hole systems
  26.         HAUSER=pi
  27.  
  28.     # Pi-hole directory (this path is expected to be the same on both Pi-holes, and should be where the FILES are located)
  29.         PIHOLEDIR=/etc/pihole
  30.  
  31.     # IP Addresses - Note that removing the value or the variable definition of either SSHPORT will cause the script to
  32.                 #    use the default SSH Port of 22 for connections to that ip address.
  33.         # Primary Pi-hole ip and ssh port
  34.             PIHOLE1=192.168.1.2
  35.             SSHPORT1=22
  36.  
  37.         # Secondary Pi-hole ip and ssh port
  38.             PIHOLE2=192.168.1.3
  39.             SSHPORT2=22
  40.  
  41.     # Define the local path to store the logfile, DO NOT include a trailing "/". Make sure this path is writeable by the user
  42.     # that runs the sync. Change this from /tmp to another folder to prevent logs from being cleared on system restart
  43.         LOGFILEPATH="/tmp"
  44.  
  45.     # How long to keep old log files (in addition to the current day's log, so a value of 6 means 7 days)
  46.         LOGKEEPDAYS=6
  47.  
  48. # USER-DEFINED VARIABLES - END - Edits made below this line may break the script.
  49. # ---------------------------------------------------------------------------------------------------------
  50.  
  51. # SCRIPT VARIABLES - START - These values are used by the script and should not be changed manually.
  52.  
  53.     # List of files to sync
  54.         FILES=(
  55.             'black.list'
  56.             'blacklist.txt'
  57.             'regex.list'
  58.             'whitelist.txt'
  59.             'lan.list'
  60.             'adlists.list'
  61.             'gravity.list'
  62.         )
  63.  
  64.     # Full logfile path and name, uncluding timestamp
  65.         LOGFILE="${LOGFILEPATH}/pihole-gemini_`date +\%Y\%m\%d`.log"
  66.  
  67.     # Flags used to determine script blocks to run.
  68.         # RUNUPDATE - 0 = Don't update; 1 = update Pi-holes
  69.         RUNUPDATE=0
  70.  
  71.         # RESTART - 0 = Don't restart; 1 = restart
  72.         RESTART=0
  73.  
  74.         # RUNGRAVITY - 0 = Don't update gravity; 1 = Update gravity (don't download lists)
  75.         RUNGRAVITY=0
  76.  
  77.         # DEFAULT SSHPORT - This value is only provided here to use the default port of 22 if a port is not defined for the specified ip address
  78.         DEFAULTSSHPORT=22
  79.  
  80.         # INITIALIZE PORT VARIABLES - This segment keeps the SSHPORT variables as set in the user-defined variables section. They are included here
  81.                                     # mainly as a fallback in case the variables are accidentally removed from the user-defined variables section.
  82.             SSHPORT1=$SSHPORT1
  83.             SSHPORT2=$SSHPORT2
  84.  
  85.         # DETERMINE IP AND PORTS TO USE - START
  86.             # This section checks the interface used to connect to the local gateway, then determines the current ip address
  87.             # based on that interface. Finally, it checks the current ip address against the two addresses the script has
  88.             # configured to determine which one is the remote Pi-hole to send commands to, and configures the appropriate port.
  89.  
  90.                 LOCALGATEWAY=$(ip -4 route | awk '{print $3}' | head -n 1)
  91.                 LOCALINTERFACE=$(ip -4 route | awk '{print $3}' | tail -n 1)
  92.                 LOCALIP=$(ip -4 -o addr show $LOCALINTERFACE | awk '{print $4}' | cut -d "/" -f 1)
  93.                     case $LOCALIP in
  94.                         $PIHOLE1)
  95.                             # echo "Local ip address matches PIHOLE1 ip, so the remote Pi-hole is PIHOLE2."
  96.                             REMOTEPI=$PIHOLE2
  97.                             if [ -z $SSHPORT2 ]; then
  98.                                 # SSHPORT2 value is empty, use the default ssh port.
  99.                                 SSHPORT=$DEFAULTSSHPORT
  100.                             else
  101.                                 # SSHPORT2 value exists, use that for connections to PIHOLE2.
  102.                                 SSHPORT=$SSHPORT2
  103.                             fi
  104.                         ;;
  105.                         $PIHOLE2)
  106.                             # echo "Local ip address matches PIHOLE2 ip, so the remote Pi-hole is PIHOLE1."
  107.                             REMOTEPI=$PIHOLE1
  108.                             if [ -z $SSHPORT1 ]; then
  109.                                 # SSHPORT1 value is empty, use the default ssh port.
  110.                                 SSHPORT=$DEFAULTSSHPORT
  111.                             else
  112.                                 # SSHPORT1 value exists, use that for connections to PIHOLE1.
  113.                                 SSHPORT=$SSHPORT1
  114.                             fi
  115.                         ;;
  116.                         *)
  117.                             echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  118.                             echo "* `date '+%Y-%m-%d %H:%M:%S'` - ERROR! - $SCRIPTVER was unable to determine the local ip address." 2>&1 | tee -a $LOGFILE
  119.                             echo "                                  This is a fatal error. Script can not continue. Please check your" 2>&1 | tee -a $LOGFILE
  120.                             echo "                                  configuration for the script, and make sure you are connected to" 2>&1 | tee -a $LOGFILE
  121.                             echo "                                  your router and have an ip address assigned." 2>&1 | tee -a $LOGFILE
  122.                             echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  123.                             REMOTEPI="Unknown"
  124.                             exit 1
  125.                         ;;
  126.                     esac
  127.  
  128.         # DETERMINE IP AND PORTS TO USE - END
  129.  
  130. # SCRIPT VARIABLES - END
  131.  
  132. # LOG HEADER START - The following echo commands are for formatting purposes in the log file.
  133.     echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  134.     echo "`date '+%Y-%m-%d %H:%M:%S'` - $SCRIPTVER was successfully launched as user: $USER" 2>&1 | tee -a $LOGFILE
  135.     echo "                      $LOCALIP is updating Pi-hole on $REMOTEPI"
  136.     echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  137. # LOG HEADER - END
  138.  
  139. # SSH CONNECTION TEST - START
  140.     echo "`date '+%Y-%m-%d %H:%M:%S'` - Testing SSH Connection to $HAUSER@$REMOTEPI. Please wait." 2>&1 | tee -a $LOGFILE
  141.  
  142.     ssh -q -p $SSHPORT $HAUSER@$REMOTEPI exit
  143.     SSHSTATUS=$?
  144.  
  145.         if [ $SSHSTATUS -eq 0 ]; then
  146.             # SSH is up
  147.             echo "`date '+%Y-%m-%d %H:%M:%S'` - SSH Connection to $HAUSER@$REMOTEPI was tested successfully." 2>&1 | tee -a $LOGFILE
  148.             RUNUPDATE=1
  149.  
  150.         else
  151.             # SSH is down
  152.             echo "* `date '+%Y-%m-%d %H:%M:%S'` - ERROR! Unable to establish SSH connection as $HAUSER@$REMOTEPI on port $SSHPORT." 2>&1 | tee -a $LOGFILE
  153.             echo "*                       This is a fatal error as SSH is required for this script. Unable to update $REMOTEPI on port $SSHPORT." 2>&1 | tee -a $LOGFILE
  154.             echo "*                       $REMOTEPI may be offline, you may have specified the wrong port, or you have not correctly configured your SSH keys." 2>&1 | tee -a $LOGFILE
  155.             echo "*                       $REMOTEPI has NOT been updated."
  156.             RUNUPDATE=0
  157.         fi
  158. # SSH CONNECTION TEST - END
  159.  
  160. # UPDATE REMOTE PIHOLE - START
  161.     if [ $RUNUPDATE -eq 1 ]; then
  162.     echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  163.  
  164.     # FILE SYNC - START - This section handles compares the local and remote versions of the files specified in the $FILES variable
  165.                     #     and updates the remote files if neccesary.   
  166.         for FILE in ${FILES[@]}
  167.             do
  168.                 if [[ -f $PIHOLEDIR/$FILE ]]; then
  169.                     echo "`date '+%Y-%m-%d %H:%M:%S'` - Comparing local to remote $FILE and updating if neccesary." 2>&1 | tee -a $LOGFILE
  170.  
  171.                     RSYNC_COMMAND=$(rsync --rsync-path='/usr/bin/sudo /usr/bin/rsync' -aiu -e "ssh -l $HAUSER@$REMOTEPI -p$SSHPORT" $PIHOLEDIR/$FILE $HAUSER@$REMOTEPI:$PIHOLEDIR)
  172.  
  173.                         if [[ -n "${RSYNC_COMMAND}" ]]; then
  174.                             # rsync copied changes so restart
  175.  
  176.                             case $FILE in
  177.                                 adlists.list)
  178.                                     # Updating adlists.list requires only a gravity update
  179.                                     echo "`date '+%Y-%m-%d %H:%M:%S'` - Updated $FILE on $REMOTEPI. Gravity will be updated on $REMOTEPI." 2>&1 | tee -a $LOGFILE
  180.                                     RUNGRAVITY=1
  181.                                 ;;
  182.  
  183.                                 gravity.list)
  184.                                     # Updating gravity.list requires only a gravity update
  185.                                     echo "`date '+%Y-%m-%d %H:%M:%S'` - Updated $FILE on $REMOTEPI. Gravity will be updated on $REMOTEPI." 2>&1 | tee -a $LOGFILE
  186.                                     RUNGRAVITY=1
  187.                                 ;;
  188.  
  189.                                 *)
  190.                                     # Updating white and/or black lists (or other files) requires a remote restart but not a gravity update
  191.                                     echo "`date '+%Y-%m-%d %H:%M:%S'` - Updated $FILE on $REMOTEPI. $REMOTEPI will be restarted." 2>&1 | tee -a $LOGFILE
  192.                                     RESTART=1
  193.                                 ;;
  194.                             esac
  195.  
  196.                         else
  197.                             # no changes so do nothing
  198.                             echo "`date '+%Y-%m-%d %H:%M:%S'` - Local file $FILE matches $FILE on $REMOTEPI. Remote file was not updated." 2>&1 | tee -a $LOGFILE
  199.                         fi
  200.  
  201.                 else
  202.                     # file does not exist, skipping
  203.                     echo "`date '+%Y-%m-%d %H:%M:%S'` - Local file $FILE does not exist. Skipping." 2>&1 | tee -a $LOGFILE
  204.                 fi
  205.             done
  206.     # FILE SYNC - END
  207.  
  208.     # RESTART REMOTEPI (IF NEEDED) - START
  209.         if [ $RESTART -eq 1 ]; then
  210.             echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  211.             echo "`date '+%Y-%m-%d %H:%M:%S'` - Updated files have been copied to $REMOTEPI. Restarting..." 2>&1 | tee -a $LOGFILE
  212.  
  213.             echo "`date '+%Y-%m-%d %H:%M:%S'` - Sending restart command to pihole-FTL on $REMOTEPI." 2>&1 | tee -a $LOGFILE
  214.  
  215.             ssh $HAUSER@$REMOTEPI -p $SSHPORT "sudo -S service pihole-FTL restart"
  216.             if [ $? -ne 0 ]; then
  217.                 echo "* `date '+%Y-%m-%d %H:%M:%S'` - ERROR! - Unable to restart pihole-FTL service on $REMOTEPI." 2>&1 | tee -a $LOGFILE
  218.  
  219.             else
  220.                 echo "`date '+%Y-%m-%d %H:%M:%S'` - Successfully restarted pihole-FTL service on $REMOTEPI." 2>&1 | tee -a $LOGFILE
  221.             fi
  222.         fi
  223.     # RESTART REMOTEPI - END
  224.  
  225.     # UPDATE REMOTE GRAVITY (IF NEEDED) - START
  226.     echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  227.         case $RUNGRAVITY in
  228.             0)
  229.                 # Gravity did not need updating - do nothing
  230.                 echo "`date '+%Y-%m-%d %H:%M:%S'` - Gravity on $REMOTEPI did not need updating." 2>&1 | tee -a $LOGFILE
  231.             ;;
  232.             1)
  233.                 # Gravity needs refreshing, but not a full update - Update gravity without redownloading lists
  234.                 echo "`date '+%Y-%m-%d %H:%M:%S'` - Refreshing gravity on $REMOTEPI. Lists will not be redownloaded." 2>&1 | tee -a $LOGFILE
  235.                 ssh $HAUSER@$REMOTEPI -p $SSHPORT "sudo -S pihole -g --skip-download"
  236.                 if [ $? -ne 0 ]; then
  237.                     echo "* `date '+%Y-%m-%d %H:%M:%S'` - ERROR! - Unable to refresh gravity on $REMOTEPI." 2>&1 | tee -a $LOGFILE
  238.  
  239.                 else
  240.                     echo "`date '+%Y-%m-%d %H:%M:%S'` - Success! Successfully refreshed gravity on $REMOTEPI." 2>&1 | tee -a $LOGFILE
  241.                 fi
  242.             ;;
  243.         esac
  244.     # UPDATE REMOTE GRAVITY - END
  245.  
  246.     # CLEAN OLD LOG FILES - START
  247.         # Check the LOGFILEPATH for outdated log files and delete old logs
  248.         echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  249.         echo "`date '+%Y-%m-%d %H:%M:%S'` - Checking ${LOGFILEPATH} for outdated log files." 2>&1 | tee -a $LOGFILE
  250.  
  251.         look_in="${LOGFILEPATH}/pihole-gemini_*.log"
  252.        
  253.         del_file=`find $look_in ! -name $LOGFILE -daystart -mtime +$LOGKEEPDAYS`
  254.         if [ -z "$del_file" ]; then
  255.             echo "`date '+%Y-%m-%d %H:%M:%S'` - There were no outdated log files to remove." 2>&1 | tee -a $LOGFILE
  256.  
  257.         else
  258.             echo "`date '+%Y-%m-%d %H:%M:%S'` - Outdated log file(s) found. Removing..." 2>&1 | tee -a $LOGFILE
  259.             sudo find $look_in ! -name $LOGFILE -daystart -mtime +$LOGKEEPDAYS -prune -exec rm -rv "{}" \;
  260.             if [ $? -ne 0 ]; then
  261.                 echo "`date '+%Y-%m-%d %H:%M:%S'` - ERROR! Unable to remove outdated log files from $LOGFILEPATH." 2>&1 | tee -a $LOGFILE
  262.             else
  263.                 echo "`date '+%Y-%m-%d %H:%M:%S'` - Outdated log files successfully cleaned." 2>&1 | tee -a $LOGFILE
  264.             fi
  265.         fi
  266.     # CLEAN OLD LOG FILES - END
  267.  
  268.     fi
  269. # UPDATE REMOTE PIHOLE - END
  270.  
  271. # LOG FOOTER - START
  272.     echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  273.     echo "`date '+%Y-%m-%d %H:%M:%S'` - $SCRIPTVER completed update of $REMOTEPI from $LOCALIP." 2>&1 | tee -a $LOGFILE
  274.     echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  275. # LOG FOOTER - END
  276.  
  277. # END OF SCRIPT
RAW Paste Data