daily pastebin goal
8%
SHARE
TWEET

Untitled

a guest Jun 18th, 2017 643 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env bash
  2. # Pi-hole and open road warrior mash-up for set-up only
  3.  
  4.  
  5. set -e
  6. ######## VARIABLES #########
  7. tmpLog=/tmp/pihole-install.log
  8. instalLogLoc=/etc/pihole/install.log
  9. setupVars=/etc/pihole/setupVars.conf
  10. lighttpdConfig=/etc/lighttpd/lighttpd.conf
  11.  
  12. webInterfaceGitUrl="https://github.com/pi-hole/AdminLTE.git"
  13. webInterfaceDir="/var/www/html/admin"
  14. piholeGitUrl="https://github.com/pi-hole/pi-hole.git"
  15. PI_HOLE_LOCAL_REPO="/etc/.pihole"
  16. PI_HOLE_FILES=(chronometer list piholeDebug piholeLogFlush setupLCD update version gravity uninstall webpage)
  17. PI_HOLE_INSTALL_DIR="/opt/pihole"
  18. useUpdateVars=false
  19.  
  20. IPV4_ADDRESS=""
  21. IPV6_ADDRESS=""
  22. QUERY_LOGGING=true
  23. INSTALL_WEB=true
  24.  
  25.  
  26. # Find the rows and columns will default to 80x24 is it can not be detected
  27. screen_size=$(stty size 2>/dev/null || echo 24 80)
  28. rows=$(echo "${screen_size}" | awk '{print $1}')
  29. columns=$(echo "${screen_size}" | awk '{print $2}')
  30.  
  31. # Divide by two so the dialogs take up half of the screen, which looks nice.
  32. r=$(( rows / 2 ))
  33. c=$(( columns / 2 ))
  34. # Unless the screen is tiny
  35. r=$(( r < 20 ? 20 : r ))
  36. c=$(( c < 70 ? 70 : c ))
  37.  
  38. ######## Undocumented Flags. Shhh ########
  39. skipSpaceCheck=false
  40. reconfigure=false
  41. runUnattended=false
  42.  
  43. newclient () {
  44.     # Generates the custom client.ovpn
  45.     cp /etc/openvpn/client-common.txt ~/$1.ovpn
  46.     echo "<ca>" >> ~/$1.ovpn
  47.     cat /etc/openvpn/easy-rsa/pki/ca.crt >> ~/$1.ovpn
  48.     echo "</ca>" >> ~/$1.ovpn
  49.     echo "<cert>" >> ~/$1.ovpn
  50.     cat /etc/openvpn/easy-rsa/pki/issued/$1.crt >> ~/$1.ovpn
  51.     echo "</cert>" >> ~/$1.ovpn
  52.     echo "<key>" >> ~/$1.ovpn
  53.     cat /etc/openvpn/easy-rsa/pki/private/$1.key >> ~/$1.ovpn
  54.     echo "</key>" >> ~/$1.ovpn
  55.     echo "<tls-auth>" >> ~/$1.ovpn
  56.     cat /etc/openvpn/ta.key >> ~/$1.ovpn
  57.     echo "</tls-auth>" >> ~/$1.ovpn
  58. }
  59. install_OpenVPN() {
  60. if readlink /proc/$$/exe | grep -qs "dash"; then
  61.     echo "This script needs to be run with bash, not sh"
  62.     exit 1
  63. fi
  64.  
  65. if [[ "$EUID" -ne 0 ]]; then
  66.     echo "Sorry, you need to run this as root"
  67.     exit 2
  68. fi
  69.  
  70. if [[ ! -e /dev/net/tun ]]; then
  71.     echo "The TUN device is not available
  72. You need to enable TUN before running this script"
  73.     exit 3
  74. fi
  75.  
  76. if grep -qs "CentOS release 5" "/etc/redhat-release"; then
  77.     echo "CentOS 5 is too old and not supported"
  78.     exit 4
  79. fi
  80. if [[ -e /etc/debian_version ]]; then
  81.     OS=debian
  82.     GROUPNAME=nogroup
  83.     RCLOCAL='/etc/rc.local'
  84. elif [[ -e /etc/centos-release || -e /etc/redhat-release ]]; then
  85.     OS=centos
  86.     GROUPNAME=nobody
  87.     RCLOCAL='/etc/rc.d/rc.local'
  88. else
  89.     echo "Looks like you aren't running this installer on Debian, Ubuntu or CentOS"
  90.     exit 5
  91. fi
  92.  
  93.  
  94.  
  95. # Try to get our IP from the system and fallback to the Internet.
  96. # I do this to make the script compatible with NATed servers (lowendspirit.com)
  97. # and to avoid getting an IPv6.
  98. IP=$(ip addr | grep 'inet' | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -o -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1)
  99. if [[ "$IP" = "" ]]; then
  100.         IP=$(wget -4qO- "http://whatismyip.akamai.com/")
  101. fi
  102.  
  103.     clear
  104.  
  105.     IP=$IP
  106.     PROTOCOL=udp
  107.     PORT=1194
  108.     CLIENT="mastercert"
  109.     #read -n1 -r -p "Press any key to continue..."
  110.     if [[ "$OS" = 'debian' ]]; then
  111.         apt-get update
  112.         apt-get install openvpn iptables openssl ca-certificates -y
  113.     else
  114.         # Else, the distro is CentOS
  115.         yum install epel-release -y
  116.         yum install openvpn iptables openssl wget ca-certificates -y
  117.     fi
  118.     # An old version of easy-rsa was available by default in some openvpn packages
  119.     if [[ -d /etc/openvpn/easy-rsa/ ]]; then
  120.         rm -rf /etc/openvpn/easy-rsa/
  121.     fi
  122.     # Get easy-rsa
  123.     wget -O ~/EasyRSA-3.0.1.tgz "https://github.com/OpenVPN/easy-rsa/releases/download/3.0.1/EasyRSA-3.0.1.tgz"
  124.     tar xzf ~/EasyRSA-3.0.1.tgz -C ~/
  125.     mv ~/EasyRSA-3.0.1/ /etc/openvpn/
  126.     mv /etc/openvpn/EasyRSA-3.0.1/ /etc/openvpn/easy-rsa/
  127.     chown -R root:root /etc/openvpn/easy-rsa/
  128.     rm -rf ~/EasyRSA-3.0.1.tgz
  129.     cd /etc/openvpn/easy-rsa/
  130.     # Create the PKI, set up the CA, the DH params and the server + client certificates
  131.     ./easyrsa init-pki
  132.     ./easyrsa --batch build-ca nopass
  133.     ./easyrsa gen-dh
  134.     ./easyrsa build-server-full server nopass
  135.     ./easyrsa build-client-full $CLIENT nopass
  136.     ./easyrsa gen-crl
  137.     # Move the stuff we need
  138.     cp pki/ca.crt pki/private/ca.key pki/dh.pem pki/issued/server.crt pki/private/server.key /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn
  139.     # CRL is read with each client connection, when OpenVPN is dropped to nobody
  140.     chown nobody:$GROUPNAME /etc/openvpn/crl.pem
  141.     # Generate key for tls-auth
  142.     openvpn --genkey --secret /etc/openvpn/ta.key
  143.     # Generate server.conf
  144.     echo "port $PORT
  145. proto $PROTOCOL
  146. dev tun
  147. sndbuf 0
  148. rcvbuf 0
  149. ca ca.crt
  150. cert server.crt
  151. key server.key
  152. dh dh.pem
  153. auth SHA512
  154. tls-auth ta.key 0
  155. topology subnet
  156. server 10.8.0.0 255.255.255.0
  157. ifconfig-pool-persist ipp.txt" > /etc/openvpn/server.conf
  158.     echo 'push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server.conf
  159.     echo 'push "dhcp-option DNS 10.8.0.1"' >> /etc/openvpn/server.conf 
  160.     echo "keepalive 10 120
  161. cipher AES-256-CBC
  162. comp-lzo
  163. user nobody
  164. group $GROUPNAME
  165. persist-key
  166. persist-tun
  167. status openvpn-status.log
  168. verb 3
  169. crl-verify crl.pem" >> /etc/openvpn/server.conf
  170.     # Enable net.ipv4.ip_forward for the system
  171.     sed -i '/\<net.ipv4.ip_forward\>/c\net.ipv4.ip_forward=1' /etc/sysctl.conf
  172.     if ! grep -q "\<net.ipv4.ip_forward\>" /etc/sysctl.conf; then
  173.         echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
  174.     fi
  175.     # Avoid an unneeded reboot
  176.     echo 1 > /proc/sys/net/ipv4/ip_forward
  177.     if pgrep firewalld; then
  178.         # Using both permanent and not permanent rules to avoid a firewalld
  179.         # reload.
  180.         # We don't use --add-service=openvpn because that would only work with
  181.         # the default port and protocol.
  182.         firewall-cmd --zone=public --add-port=$PORT/$PROTOCOL
  183.         firewall-cmd --zone=trusted --add-source=10.8.0.0/24
  184.         firewall-cmd --permanent --zone=public --add-port=$PORT/$PROTOCOL
  185.         firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24
  186.         # Set NAT for the VPN subnet
  187.         firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $IP
  188.         firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $IP
  189.     else
  190.         # Needed to use rc.local with some systemd distros
  191.         if [[ "$OS" = 'debian' && ! -e $RCLOCAL ]]; then
  192.             echo '#!/bin/sh -e
  193. exit 0' > $RCLOCAL
  194.         fi
  195.         chmod +x $RCLOCAL
  196.         # Set NAT for the VPN subnet
  197.         iptables -t nat -A POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $IP
  198.         sed -i "1 a\iptables -t nat -A POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $IP" $RCLOCAL
  199.         if iptables -L -n | grep -qE '^(REJECT|DROP)'; then
  200.             # If iptables has at least one REJECT rule, we asume this is needed.
  201.             # Not the best approach but I can't think of other and this shouldn't
  202.             # cause problems.
  203.             iptables -I INPUT -p $PROTOCOL --dport $PORT -j ACCEPT
  204.             iptables -I FORWARD -s 10.8.0.0/24 -j ACCEPT
  205.             iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
  206.             sed -i "1 a\iptables -I INPUT -p $PROTOCOL --dport $PORT -j ACCEPT" $RCLOCAL
  207.             sed -i "1 a\iptables -I FORWARD -s 10.8.0.0/24 -j ACCEPT" $RCLOCAL
  208.             sed -i "1 a\iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT" $RCLOCAL
  209.         fi
  210.     fi
  211.     # If SELinux is enabled and a custom port or TCP was selected, we need this
  212.     if hash sestatus 2>/dev/null; then
  213.         if sestatus | grep "Current mode" | grep -qs "enforcing"; then
  214.             if [[ "$PORT" != '1194' || "$PROTOCOL" = 'tcp' ]]; then
  215.                 # semanage isn't available in CentOS 6 by default
  216.                 if ! hash semanage 2>/dev/null; then
  217.                     yum install policycoreutils-python -y
  218.                 fi
  219.                 semanage port -a -t openvpn_port_t -p $PROTOCOL $PORT
  220.             fi
  221.         fi
  222.     fi
  223.     # And finally, restart OpenVPN
  224.     if [[ "$OS" = 'debian' ]]; then
  225.         # Little hack to check for systemd
  226.         if pgrep systemd-journal; then
  227.             systemctl restart openvpn@server.service
  228.         else
  229.             /etc/init.d/openvpn restart
  230.         fi
  231.     else
  232.         if pgrep systemd-journal; then
  233.             systemctl restart openvpn@server.service
  234.             systemctl enable openvpn@server.service
  235.         else
  236.             service openvpn restart
  237.             chkconfig openvpn on
  238.         fi
  239.     fi
  240.     # Try to detect a NATed connection and ask about it to potential LowEndSpirit users
  241.     EXTERNALIP=$(wget -4qO- "http://whatismyip.akamai.com/")
  242.     if [[ "$IP" != "$EXTERNALIP" ]]; then
  243.         echo ""
  244.         echo "Looks like your server is behind a NAT!"
  245.         echo ""
  246.         echo "If your server is NATed (e.g. LowEndSpirit), I need to know the external IP"
  247.         echo "If that's not the case, just ignore this and leave the next field blank"
  248.         read -p "External IP: " -e USEREXTERNALIP
  249.         if [[ "$USEREXTERNALIP" != "" ]]; then
  250.             IP=$USEREXTERNALIP
  251.         fi
  252.     fi
  253.     # client-common.txt is created so we have a template to add further users later
  254.     echo "client
  255. dev tun
  256. proto $PROTOCOL
  257. sndbuf 0
  258. rcvbuf 0
  259. remote $IP $PORT
  260. resolv-retry infinite
  261. nobind
  262. persist-key
  263. persist-tun
  264. remote-cert-tls server
  265. auth SHA512
  266. cipher AES-256-CBC
  267. comp-lzo
  268. setenv opt block-outside-dns
  269. key-direction 1
  270. verb 3" > /etc/openvpn/client-common.txt
  271.     # Generates the custom client.ovpn
  272.     newclient "$CLIENT"
  273.     echo ""
  274.     echo "Finished!"
  275.  
  276.  
  277. }
  278.  
  279.  
  280. # Compatibility
  281. distro_check() {
  282. if command -v apt-get &> /dev/null; then
  283.   #Debian Family
  284.   #############################################
  285.   PKG_MANAGER="apt-get"
  286.   UPDATE_PKG_CACHE="test_dpkg_lock; ${PKG_MANAGER} update"
  287.   PKG_INSTALL=(${PKG_MANAGER} --yes --no-install-recommends install)
  288.   # grep -c will return 1 retVal on 0 matches, block this throwing the set -e with an OR TRUE
  289.   PKG_COUNT="${PKG_MANAGER} -s -o Debug::NoLocking=true upgrade | grep -c ^Inst || true"
  290.   # #########################################
  291.   # fixes for dependency differences
  292.   # Debian 7 doesn't have iproute2 use iproute
  293.   if ${PKG_MANAGER} install --dry-run iproute2 > /dev/null 2>&1; then
  294.     iproute_pkg="iproute2"
  295.   else
  296.     iproute_pkg="iproute"
  297.   fi
  298.   # Prefer the php metapackage if it's there, fall back on the php5 packages
  299.   if ${PKG_MANAGER} install --dry-run php > /dev/null 2>&1; then
  300.     phpVer="php"
  301.   else
  302.     phpVer="php5"
  303.   fi
  304.   # #########################################
  305.   INSTALLER_DEPS=(apt-utils dialog debconf dhcpcd5 git ${iproute_pkg} whiptail)
  306.   PIHOLE_DEPS=(bc cron curl dnsmasq dnsutils iputils-ping lsof netcat sudo unzip wget)
  307.   PIHOLE_WEB_DEPS=(lighttpd ${phpVer}-common ${phpVer}-cgi)
  308.   LIGHTTPD_USER="www-data"
  309.   LIGHTTPD_GROUP="www-data"
  310.   LIGHTTPD_CFG="lighttpd.conf.debian"
  311.   DNSMASQ_USER="dnsmasq"
  312.  
  313.   test_dpkg_lock() {
  314.     i=0
  315.     while fuser /var/lib/dpkg/lock >/dev/null 2>&1 ; do
  316.       sleep 0.5
  317.       ((i=i+1))
  318.     done
  319.     # Always return success, since we only return if there is no
  320.     # lock (anymore)
  321.     return 0
  322.   }
  323.  
  324. elif command -v rpm &> /dev/null; then
  325.   # Fedora Family
  326.   if command -v dnf &> /dev/null; then
  327.     PKG_MANAGER="dnf"
  328.   else
  329.     PKG_MANAGER="yum"
  330.   fi
  331.  
  332. # Fedora and family update cache on every PKG_INSTALL call, no need for a separate update.
  333.   UPDATE_PKG_CACHE=":"
  334.   PKG_INSTALL=(${PKG_MANAGER} install -y)
  335.   PKG_COUNT="${PKG_MANAGER} check-update | egrep '(.i686|.x86|.noarch|.arm|.src)' | wc -l"
  336.   INSTALLER_DEPS=(dialog git iproute net-tools newt procps-ng)
  337.   PIHOLE_DEPS=(bc bind-utils cronie curl dnsmasq findutils nmap-ncat sudo unzip wget)
  338.   PIHOLE_WEB_DEPS=(lighttpd lighttpd-fastcgi php php-common php-cli)
  339.   if ! grep -q 'Fedora' /etc/redhat-release; then
  340.     INSTALLER_DEPS=("${INSTALLER_DEPS[@]}" "epel-release");
  341.   fi
  342.     LIGHTTPD_USER="lighttpd"
  343.     LIGHTTPD_GROUP="lighttpd"
  344.     LIGHTTPD_CFG="lighttpd.conf.fedora"
  345.     DNSMASQ_USER="nobody"
  346.  
  347. else
  348.   echo "OS distribution not supported"
  349.   exit
  350. fi
  351. }
  352.  
  353. is_repo() {
  354.   # Use git to check if directory is currently under VCS, return the value 128
  355.   # if directory is not a repo. Return 1 if directory does not exist.
  356.   local directory="${1}"
  357.   local curdir
  358.   local rc
  359.  
  360.   curdir="${PWD}"
  361.   if [[ -d "${directory}" ]]; then
  362.     # git -C is not used here to support git versions older than 1.8.4
  363.     cd "${directory}"
  364.     git status --short &> /dev/null || rc=$?
  365.   else
  366.     # non-zero return code if directory does not exist
  367.     rc=1
  368.   fi
  369.   cd "${curdir}"
  370.   return "${rc:-0}"
  371. }
  372.  
  373. make_repo() {
  374.   local directory="${1}"
  375.   local remoteRepo="${2}"
  376.  
  377.   echo -n ":::    Cloning ${remoteRepo} into ${directory}..."
  378.   # Clean out the directory if it exists for git to clone into
  379.   if [[ -d "${directory}" ]]; then
  380.     rm -rf "${directory}"
  381.   fi
  382.   git clone -q --depth 1 "${remoteRepo}" "${directory}" &> /dev/null || return $?
  383.   echo " done!"
  384.   return 0
  385. }
  386.  
  387. update_repo() {
  388.   local directory="${1}"
  389.   local curdir
  390.  
  391.   curdir="${PWD}"
  392.   cd "${directory}" &> /dev/null || return 1
  393.   # Pull the latest commits
  394.   echo -n ":::    Updating repo in ${1}..."
  395.   git stash --all --quiet &> /dev/null || true # Okay for stash failure
  396.   git clean --force -d || true # Okay for already clean directory
  397.   git pull --quiet &> /dev/null || return $?
  398.   echo " done!"
  399.   cd "${curdir}" &> /dev/null || return 1
  400.   return 0
  401. }
  402.  
  403. getGitFiles() {
  404.   # Setup git repos for directory and repository passed
  405.   # as arguments 1 and 2
  406.   local directory="${1}"
  407.   local remoteRepo="${2}"
  408.   echo ":::"
  409.   echo "::: Checking for existing repository..."
  410.   if is_repo "${directory}"; then
  411.     update_repo "${directory}" || { echo "*** Error: Could not update local repository. Contact support."; exit 1; }
  412.     echo " done!"
  413.   else
  414.     make_repo "${directory}" "${remoteRepo}" || { echo "Unable to clone repository, please contact support"; exit 1; }
  415.     echo " done!"
  416.   fi
  417.   return 0
  418. }
  419.  
  420. find_IPv4_information() {
  421.   local route
  422.   # Find IP used to route to outside world
  423.   route=$(ip route get 8.8.8.8)
  424.   IPv4dev=$(awk '{for (i=1; i<=NF; i++) if ($i~/dev/) print $(i+1)}' <<< "${route}")
  425.   IPv4bare=$(awk '{print $7}' <<< "${route}")
  426.   #-add
  427.   #IPV4_ADDRESS=$(ip -o -f inet addr show | grep "${IPv4bare}" |  awk '{print $4}' | awk 'END {print}')
  428.   IPV4_ADDRESS=10.8.0.1/24
  429.   IPv4gw=$(awk '{print $3}' <<< "${route}")
  430.  
  431. }
  432.  
  433.  
  434.  
  435.  
  436.  
  437. verifyFreeDiskSpace() {
  438.  
  439.  
  440. }
  441.  
  442.  
  443. useIPv6dialog() {
  444.   # Show the IPv6 address used for blocking
  445.   IPV6_ADDRESS=$(ip -6 route get 2001:4860:4860::8888 | grep -v "unreachable" | awk -F " " '{ for(i=1;i<=NF;i++) if ($i == "src") print $(i+1) }')
  446.  
  447.   #if [[ ! -z "${IPV6_ADDRESS}" ]]; then
  448.     #whiptail --msgbox --backtitle "IPv6..." --title "IPv6 Supported" "$IPV6_ADDRESS will be used to block ads." ${r} ${c}
  449.   #fi
  450. }
  451.  
  452.  
  453. use4andor6() {
  454.   local useIPv4
  455.   local useIPv6
  456.   # Let use select IPv4 and/or IPv6
  457.   #cmd=(whiptail --separate-output --checklist "Select Protocols (press space to select)" ${r} ${c} 2)
  458.   #options=(IPv4 "Block ads over IPv4" on
  459.   #IPv6 "Block ads over IPv6" on)
  460.   #choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty) || { echo "::: Cancel selected. Exiting"; exit 1; }
  461.   #for choice in ${choices}
  462.   #do
  463.     #case ${choice} in
  464.     #IPv4  )   useIPv4=true;;
  465.     #IPv6  )   useIPv6=true;;
  466.     #esac
  467.   #done
  468.   # -
  469.   useIPv4=true
  470.   useIPv6=true
  471.   if [[ ${useIPv4} ]]; then
  472.     find_IPv4_information
  473.     #getStaticIPv4Settings
  474.     setStaticIPv4
  475.   fi
  476.   if [[ ${useIPv6} ]]; then
  477.     useIPv6dialog
  478.   fi
  479.     echo "::: IPv4 address: ${IPV4_ADDRESS}"
  480.     echo "::: IPv6 address: ${IPV6_ADDRESS}"
  481.   if [ ! ${useIPv4} ] && [ ! ${useIPv6} ]; then
  482.     echo "::: Cannot continue, neither IPv4 or IPv6 selected"
  483.     echo "::: Exiting"
  484.     exit 1
  485.   fi
  486. }
  487.  
  488.  
  489.  
  490. setDHCPCD() {
  491.   # Append these lines to dhcpcd.conf to enable a static IP
  492.   echo "interface ${PIHOLE_INTERFACE}
  493.   static ip_address=${IPV4_ADDRESS}
  494.   static routers=${IPv4gw}
  495.   static domain_name_servers=${IPv4gw}" | tee -a /etc/dhcpcd.conf >/dev/null
  496. }
  497.  
  498. setStaticIPv4() {
  499.   local IFCFG_FILE
  500.   local IPADDR
  501.   local CIDR
  502.   if [[ -f /etc/dhcpcd.conf ]]; then
  503.     # Debian Family
  504.     if grep -q "${IPV4_ADDRESS}" /etc/dhcpcd.conf; then
  505.       echo "::: Static IP already configured"
  506.     else
  507.       setDHCPCD
  508.       ip addr replace dev "${PIHOLE_INTERFACE}" "${IPV4_ADDRESS}"
  509.       echo ":::"
  510.       echo "::: Setting IP to ${IPV4_ADDRESS}.  You may need to restart after the install is complete."
  511.       echo ":::"
  512.     fi
  513.   elif [[ -f /etc/sysconfig/network-scripts/ifcfg-${PIHOLE_INTERFACE} ]];then
  514.     # Fedora Family
  515.     IFCFG_FILE=/etc/sysconfig/network-scripts/ifcfg-${PIHOLE_INTERFACE}
  516.     if grep -q "${IPV4_ADDRESS}" "${IFCFG_FILE}"; then
  517.       echo "::: Static IP already configured"
  518.     else
  519.       IPADDR=$(echo "${IPV4_ADDRESS}" | cut -f1 -d/)
  520.       CIDR=$(echo "${IPV4_ADDRESS}" | cut -f2 -d/)
  521.       # Backup existing interface configuration:
  522.       cp "${IFCFG_FILE}" "${IFCFG_FILE}".pihole.orig
  523.       # Build Interface configuration file:
  524.       {
  525.         echo "# Configured via Pi-hole installer"
  526.         echo "DEVICE=$PIHOLE_INTERFACE"
  527.         echo "BOOTPROTO=none"
  528.         echo "ONBOOT=yes"
  529.         echo "IPADDR=$IPADDR"
  530.         echo "PREFIX=$CIDR"
  531.         echo "GATEWAY=$IPv4gw"
  532.         echo "DNS1=$PIHOLE_DNS_1"
  533.         echo "DNS2=$PIHOLE_DNS_2"
  534.         echo "USERCTL=no"
  535.       }> "${IFCFG_FILE}"
  536.       ip addr replace dev "${PIHOLE_INTERFACE}" "${IPV4_ADDRESS}"
  537.       if command -v nmcli &> /dev/null;then
  538.         # Tell NetworkManager to read our new sysconfig file
  539.         nmcli con load "${IFCFG_FILE}" > /dev/null
  540.       fi
  541.       echo ":::"
  542.       echo "::: Setting IP to ${IPV4_ADDRESS}.  You may need to restart after the install is complete."
  543.       echo ":::"
  544.     fi
  545.   else
  546.     echo "::: Warning: Unable to locate configuration file to set static IPv4 address!"
  547.     exit 1
  548.   fi
  549. }
  550.  
  551. valid_ip() {
  552.   local ip=${1}
  553.   local stat=1
  554.  
  555.   if [[ ${ip} =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
  556.     OIFS=$IFS
  557.     IFS='.'
  558.     ip=(${ip})
  559.     IFS=${OIFS}
  560.     [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
  561.     && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
  562.     stat=$?
  563.   fi
  564.   return ${stat}
  565. }
  566.  
  567.  
  568.  
  569.  
  570. version_check_dnsmasq() {
  571.   # Check if /etc/dnsmasq.conf is from pihole.  If so replace with an original and install new in .d directory
  572.   local dnsmasq_conf="/etc/dnsmasq.conf"
  573.   local dnsmasq_conf_orig="/etc/dnsmasq.conf.orig"
  574.   local dnsmasq_pihole_id_string="addn-hosts=/etc/pihole/gravity.list"
  575.   local dnsmasq_original_config="${PI_HOLE_LOCAL_REPO}/advanced/dnsmasq.conf.original"
  576.   local dnsmasq_pihole_01_snippet="${PI_HOLE_LOCAL_REPO}/advanced/01-pihole.conf"
  577.   local dnsmasq_pihole_01_location="/etc/dnsmasq.d/01-pihole.conf"
  578.  
  579.   if [ -f ${dnsmasq_conf} ]; then
  580.     echo -n ":::    Existing dnsmasq.conf found..."
  581.     if grep -q ${dnsmasq_pihole_id_string} ${dnsmasq_conf}; then
  582.       echo " it is from a previous Pi-hole install."
  583.       echo -n ":::    Backing up dnsmasq.conf to dnsmasq.conf.orig..."
  584.       mv -f ${dnsmasq_conf} ${dnsmasq_conf_orig}
  585.       echo " done."
  586.       echo -n ":::    Restoring default dnsmasq.conf..."
  587.       cp ${dnsmasq_original_config} ${dnsmasq_conf}
  588.       echo " done."
  589.     else
  590.       echo " it is not a Pi-hole file, leaving alone!"
  591.     fi
  592.   else
  593.     echo -n ":::    No dnsmasq.conf found.. restoring default dnsmasq.conf..."
  594.     cp ${dnsmasq_original_config} ${dnsmasq_conf}
  595.     echo " done."
  596.   fi
  597.  
  598.   echo -n ":::    Copying 01-pihole.conf to /etc/dnsmasq.d/01-pihole.conf..."
  599.   cp ${dnsmasq_pihole_01_snippet} ${dnsmasq_pihole_01_location}
  600.   echo " done."
  601.   sed -i "s/@INT@/$PIHOLE_INTERFACE/" ${dnsmasq_pihole_01_location}
  602.   if [[ "${PIHOLE_DNS_1}" != "" ]]; then
  603.     sed -i "s/@DNS1@/$PIHOLE_DNS_1/" ${dnsmasq_pihole_01_location}
  604.   else
  605.     sed -i '/^server=@DNS1@/d' ${dnsmasq_pihole_01_location}
  606.   fi
  607.   if [[ "${PIHOLE_DNS_2}" != "" ]]; then
  608.     sed -i "s/@DNS2@/$PIHOLE_DNS_2/" ${dnsmasq_pihole_01_location}
  609.   else
  610.     sed -i '/^server=@DNS2@/d' ${dnsmasq_pihole_01_location}
  611.   fi
  612.  
  613.   sed -i 's/^#conf-dir=\/etc\/dnsmasq.d$/conf-dir=\/etc\/dnsmasq.d/' ${dnsmasq_conf}
  614.  
  615.   if [[ "${QUERY_LOGGING}" == false ]] ; then
  616.         #Disable Logging
  617.         sed -i 's/^log-queries/#log-queries/' ${dnsmasq_pihole_01_location}
  618.     else
  619.         #Enable Logging
  620.         sed -i 's/^#log-queries/log-queries/' ${dnsmasq_pihole_01_location}
  621.     fi
  622. }
  623.  
  624. clean_existing() {
  625.   # Clean an exiting installation to prepare for upgrade/reinstall
  626.   # ${1} Directory to clean; ${2} Array of files to remove
  627.   local clean_directory="${1}"
  628.   shift
  629.   local old_files=( "$@" )
  630.  
  631.   for script in "${old_files[@]}"; do
  632.     rm -f "${clean_directory}/${script}.sh"
  633.   done
  634. }
  635.  
  636. installScripts() {
  637.   # Install the scripts from repository to their various locations
  638.  
  639.   echo ":::"
  640.   echo -n "::: Installing scripts from ${PI_HOLE_LOCAL_REPO}..."
  641.  
  642.   # Clear out script files from Pi-hole scripts directory.
  643.   clean_existing "${PI_HOLE_INSTALL_DIR}" "${PI_HOLE_FILES[@]}"
  644.  
  645.   # Install files from local core repository
  646.   if is_repo "${PI_HOLE_LOCAL_REPO}"; then
  647.     cd "${PI_HOLE_LOCAL_REPO}"
  648.     install -o "${USER}" -Dm755 -d "${PI_HOLE_INSTALL_DIR}"
  649.     install -o "${USER}" -Dm755 -t "${PI_HOLE_INSTALL_DIR}" gravity.sh
  650.     install -o "${USER}" -Dm755 -t "${PI_HOLE_INSTALL_DIR}" ./advanced/Scripts/*.sh
  651.     install -o "${USER}" -Dm755 -t "${PI_HOLE_INSTALL_DIR}" ./automated\ install/uninstall.sh
  652.     install -o "${USER}" -Dm755 -t /usr/local/bin/ pihole
  653.     install -Dm644 ./advanced/bash-completion/pihole /etc/bash_completion.d/pihole
  654.     echo " done."
  655.   else
  656.     echo " *** ERROR: Local repo ${PI_HOLE_LOCAL_REPO} not found, exiting."
  657.     exit 1
  658.   fi
  659. }
  660.  
  661. installConfigs() {
  662.   # Install the configs from PI_HOLE_LOCAL_REPO to their various locations
  663.   echo ":::"
  664.   echo "::: Installing configs from ${PI_HOLE_LOCAL_REPO}..."
  665.   version_check_dnsmasq
  666.  
  667.   #Only mess with lighttpd configs if user has chosen to install web interface
  668.   if [[ ${INSTALL_WEB} == true ]]; then
  669.     if [ ! -d "/etc/lighttpd" ]; then
  670.       mkdir /etc/lighttpd
  671.       chown "${USER}":root /etc/lighttpd
  672.     elif [ -f "/etc/lighttpd/lighttpd.conf" ]; then
  673.       mv /etc/lighttpd/lighttpd.conf /etc/lighttpd/lighttpd.conf.orig
  674.     fi
  675.     cp ${PI_HOLE_LOCAL_REPO}/advanced/${LIGHTTPD_CFG} /etc/lighttpd/lighttpd.conf
  676.     mkdir -p /var/run/lighttpd
  677.     chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} /var/run/lighttpd
  678.     mkdir -p /var/cache/lighttpd/compress
  679.     chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} /var/cache/lighttpd/compress
  680.     mkdir -p /var/cache/lighttpd/uploads
  681.     chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} /var/cache/lighttpd/uploads
  682.   fi
  683. }
  684.  
  685. stop_service() {
  686.   # Stop service passed in as argument.
  687.   # Can softfail, as process may not be installed when this is called
  688.   echo ":::"
  689.   echo -n "::: Stopping ${1} service..."
  690.   if command -v systemctl &> /dev/null; then
  691.     systemctl stop "${1}" &> /dev/null || true
  692.   else
  693.     service "${1}" stop &> /dev/null || true
  694.   fi
  695.   echo " done."
  696. }
  697.  
  698. start_service() {
  699.   # Start/Restart service passed in as argument
  700.   # This should not fail, it's an error if it does
  701.   echo ":::"
  702.   echo -n "::: Starting ${1} service..."
  703.   if command -v systemctl &> /dev/null; then
  704.     systemctl restart "${1}" &> /dev/null
  705.   else
  706.     service "${1}" restart &> /dev/null
  707.   fi
  708.   echo " done."
  709. }
  710.  
  711. enable_service() {
  712.   # Enable service so that it will start with next reboot
  713.   echo ":::"
  714.   echo -n "::: Enabling ${1} service to start on reboot..."
  715.   if command -v systemctl &> /dev/null; then
  716.     systemctl enable "${1}" &> /dev/null
  717.   else
  718.     update-rc.d "${1}" defaults &> /dev/null
  719.   fi
  720.   echo " done."
  721. }
  722.  
  723. update_package_cache() {
  724.   #Running apt-get update/upgrade with minimal output can cause some issues with
  725.   #requiring user input (e.g password for phpmyadmin see #218)
  726.  
  727.   #Update package cache on apt based OSes. Do this every time since
  728.   #it's quick and packages can be updated at any time.
  729.  
  730.   echo ":::"
  731.   echo -n "::: Updating local cache of available packages..."
  732.   if eval "${UPDATE_PKG_CACHE}" &> /dev/null; then
  733.     echo " done!"
  734.   else
  735.     echo -en "\n!!! ERROR - Unable to update package cache. Please try \"${UPDATE_PKG_CACHE}\""
  736.     return 1
  737.   fi
  738. }
  739.  
  740. notify_package_updates_available() {
  741.   # Let user know if they have outdated packages on their system and
  742.   # advise them to run a package update at soonest possible.
  743.   echo ":::"
  744.   echo -n "::: Checking ${PKG_MANAGER} for upgraded packages...."
  745.   updatesToInstall=$(eval "${PKG_COUNT}")
  746.   echo " done!"
  747.   echo ":::"
  748.   if [[ -d "/lib/modules/$(uname -r)" ]]; then
  749.     if [[ ${updatesToInstall} -eq "0" ]]; then
  750.       echo "::: Your system is up to date! Continuing with Pi-hole installation..."
  751.     else
  752.       echo "::: There are ${updatesToInstall} updates available for your system!"
  753.       echo "::: We recommend you update your OS after installing Pi-hole! "
  754.       echo ":::"
  755.     fi
  756.   else
  757.     echo "::: Kernel update detected, please reboot your system and try again if your installation fails."
  758.   fi
  759. }
  760.  
  761. install_dependent_packages() {
  762.   # Install packages passed in via argument array
  763.   # No spinner - conflicts with set -e
  764.   declare -a argArray1=("${!1}")
  765.   declare -a installArray
  766.  
  767.   # Debian based package install - debconf will download the entire package list
  768.   # so we just create an array of packages not currently installed to cut down on the
  769.   # amount of download traffic.
  770.   # NOTE: We may be able to use this installArray in the future to create a list of package that were
  771.   # installed by us, and remove only the installed packages, and not the entire list.
  772.   if command -v debconf-apt-progress &> /dev/null; then
  773.     for i in "${argArray1[@]}"; do
  774.       echo -n ":::    Checking for $i..."
  775.       if dpkg-query -W -f='${Status}' "${i}" 2>/dev/null | grep "ok installed" &> /dev/null; then
  776.         echo " installed!"
  777.       else
  778.         echo " added to install list!"
  779.         installArray+=("${i}")
  780.       fi
  781.     done
  782.     if [[ ${#installArray[@]} -gt 0 ]]; then
  783.       test_dpkg_lock
  784.       debconf-apt-progress -- "${PKG_INSTALL[@]}" "${installArray[@]}"
  785.       return
  786.     fi
  787.       return 0
  788.   fi
  789.  
  790.   #Fedora/CentOS
  791.   for i in "${argArray1[@]}"; do
  792.     echo -n ":::    Checking for $i..."
  793.     if ${PKG_MANAGER} -q list installed "${i}" &> /dev/null; then
  794.       echo " installed!"
  795.     else
  796.       echo " added to install list!"
  797.       installArray+=("${i}")
  798.     fi
  799.   done
  800.     if [[ ${#installArray[@]} -gt 0 ]]; then
  801.       "${PKG_INSTALL[@]}" "${installArray[@]}" &> /dev/null
  802.       return
  803.     fi
  804.     return 0
  805. }
  806.  
  807. CreateLogFile() {
  808.   # Create logfiles if necessary
  809.   echo ":::"
  810.   echo -n "::: Creating log file and changing owner to dnsmasq..."
  811.   if [ ! -f /var/log/pihole.log ]; then
  812.     touch /var/log/pihole.log
  813.     chmod 644 /var/log/pihole.log
  814.     chown "${DNSMASQ_USER}":root /var/log/pihole.log
  815.     echo " done!"
  816.   else
  817.     echo " already exists!"
  818.   fi
  819. }
  820.  
  821. installPiholeWeb() {
  822.   # Install the web interface
  823.   echo ":::"
  824.   echo "::: Installing pihole custom index page..."
  825.   if [ -d "/var/www/html/pihole" ]; then
  826.     if [ -f "/var/www/html/pihole/index.php" ]; then
  827.       echo ":::     Existing index.php detected, not overwriting"
  828.     else
  829.       echo -n ":::     index.php missing, replacing... "
  830.       cp ${PI_HOLE_LOCAL_REPO}/advanced/index.php /var/www/html/pihole/
  831.       echo " done!"
  832.     fi
  833.  
  834.     if [ -f "/var/www/html/pihole/index.js" ]; then
  835.       echo ":::     Existing index.js detected, not overwriting"
  836.     else
  837.       echo -n ":::     index.js missing, replacing... "
  838.       cp ${PI_HOLE_LOCAL_REPO}/advanced/index.js /var/www/html/pihole/
  839.       echo " done!"
  840.     fi
  841.  
  842.     if [ -f "/var/www/html/pihole/blockingpage.css" ]; then
  843.       echo ":::     Existing blockingpage.css detected, not overwriting"
  844.     else
  845.       echo -n ":::     blockingpage.css missing, replacing... "
  846.       cp ${PI_HOLE_LOCAL_REPO}/advanced/blockingpage.css /var/www/html/pihole
  847.       echo " done!"
  848.     fi
  849.  
  850.   else
  851.     echo ":::     Creating directory for blocking page"
  852.     install -d /var/www/html/pihole
  853.     install -D ${PI_HOLE_LOCAL_REPO}/advanced/{index,blockingpage}.* /var/www/html/pihole/
  854.     if [ -f /var/www/html/index.lighttpd.html ]; then
  855.       mv /var/www/html/index.lighttpd.html /var/www/html/index.lighttpd.orig
  856.     else
  857.       printf "\n:::\tNo default index.lighttpd.html file found... not backing up"
  858.     fi
  859.     echo " done!"
  860.   fi
  861.  
  862.   # Install Sudoer file
  863.   echo ":::"
  864.   echo -n "::: Installing sudoer file..."
  865.   mkdir -p /etc/sudoers.d/
  866.   cp ${PI_HOLE_LOCAL_REPO}/advanced/pihole.sudo /etc/sudoers.d/pihole
  867.   # Add lighttpd user (OS dependent) to sudoers file
  868.   echo "${LIGHTTPD_USER} ALL=NOPASSWD: /usr/local/bin/pihole" >> /etc/sudoers.d/pihole
  869.  
  870.   if [[ "$LIGHTTPD_USER" == "lighttpd" ]]; then
  871.     # Allow executing pihole via sudo with Fedora
  872.     # Usually /usr/local/bin is not permitted as directory for sudoable programms
  873.     echo "Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin" >> /etc/sudoers.d/pihole
  874.   fi
  875.  
  876.   chmod 0440 /etc/sudoers.d/pihole
  877.   echo " done!"
  878. }
  879.  
  880. installCron() {
  881.   # Install the cron job
  882.   echo ":::"
  883.   echo -n "::: Installing latest Cron script..."
  884.   cp ${PI_HOLE_LOCAL_REPO}/advanced/pihole.cron /etc/cron.d/pihole
  885.   echo " done!"
  886. }
  887.  
  888. runGravity() {
  889.   # Run gravity.sh to build blacklists
  890.   echo ":::"
  891.   echo "::: Preparing to run gravity.sh to refresh hosts..."
  892.   if ls /etc/pihole/list* 1> /dev/null 2>&1; then
  893.     echo "::: Cleaning up previous install (preserving whitelist/blacklist)"
  894.     rm /etc/pihole/list.*
  895.   fi
  896.   # Test if /etc/pihole/adlists.default exists
  897.   if [[ ! -e /etc/pihole/adlists.default ]]; then
  898.     cp ${PI_HOLE_LOCAL_REPO}/adlists.default /etc/pihole/adlists.default
  899.   fi
  900.   echo "::: Running gravity.sh"
  901.   { /opt/pihole/gravity.sh; }
  902. }
  903.  
  904. create_pihole_user() {
  905.   # Check if user pihole exists and create if not
  906.   echo "::: Checking if user 'pihole' exists..."
  907.   if id -u pihole &> /dev/null; then
  908.     echo "::: User 'pihole' already exists"
  909.   else
  910.     echo "::: User 'pihole' doesn't exist. Creating..."
  911.     useradd -r -s /usr/sbin/nologin pihole
  912.   fi
  913. }
  914.  
  915. configureFirewall() {
  916.   # Allow HTTP and DNS traffic
  917.   if firewall-cmd --state &> /dev/null; then
  918.     whiptail --title "Firewall in use" --yesno "We have detected a running firewall\n\nPi-hole currently requires HTTP and DNS port access.\n\n\n\nInstall Pi-hole default firewall rules?" ${r} ${c} || \
  919.     { echo -e ":::\n::: Not installing firewall rulesets."; return 0; }
  920.     echo -e ":::\n:::\n Configuring FirewallD for httpd and dnsmasq."
  921.     firewall-cmd --permanent --add-service=http --add-service=dns
  922.     firewall-cmd --reload
  923.     return 0
  924.   # Check for proper kernel modules to prevent failure
  925.   elif modinfo ip_tables &> /dev/null && command -v iptables &> /dev/null; then
  926.     # If chain Policy is not ACCEPT or last Rule is not ACCEPT
  927.     # then check and insert our Rules above the DROP/REJECT Rule.
  928.     if iptables -S INPUT | head -n1 | grep -qv '^-P.*ACCEPT$' || iptables -S INPUT | tail -n1 | grep -qv '^-\(A\|P\).*ACCEPT$'; then
  929.       whiptail --title "Firewall in use" --yesno "We have detected a running firewall\n\nPi-hole currently requires HTTP and DNS port access.\n\n\n\nInstall Pi-hole default firewall rules?" ${r} ${c} || \
  930.       { echo -e ":::\n::: Not installing firewall rulesets."; return 0; }
  931.       echo -e ":::\n::: Installing new IPTables firewall rulesets."
  932.       # Check chain first, otherwise a new rule will duplicate old ones
  933.       iptables -C INPUT -p tcp -m tcp --dport 80 -j ACCEPT &> /dev/null || iptables -I INPUT 1 -p tcp -m tcp --dport 80 -j ACCEPT
  934.       iptables -C INPUT -p tcp -m tcp --dport 53 -j ACCEPT &> /dev/null || iptables -I INPUT 1 -p tcp -m tcp --dport 53 -j ACCEPT
  935.       iptables -C INPUT -p udp -m udp --dport 53 -j ACCEPT &> /dev/null || iptables -I INPUT 1 -p udp -m udp --dport 53 -j ACCEPT
  936.       return 0
  937.     fi
  938.   else
  939.     echo -e ":::\n::: No active firewall detected.. skipping firewall configuration."
  940.     return 0
  941.   fi
  942.   echo -e ":::\n::: Skipping firewall configuration."
  943. }
  944.  
  945. finalExports() {
  946.  
  947.   if [[ ${INSTALL_WEB} == false ]]; then
  948.     #No web interface installed, and therefore no block page set IPV4/6 to 0.0.0.0 and ::/0
  949.     if [ ${IPV4_ADDRESS} ]; then
  950.       IPV4_ADDRESS="0.0.0.0"
  951.     fi
  952.     if [ ${IPV6_ADDRESS} ]; then
  953.       IPV6_ADDRESS="::/0"
  954.     fi
  955.   fi
  956.  
  957.   # Update variables in setupVars.conf file
  958.   if [ -e "${setupVars}" ]; then
  959.     sed -i.update.bak '/PIHOLE_INTERFACE/d;/IPV4_ADDRESS/d;/IPV6_ADDRESS/d;/PIHOLE_DNS_1/d;/PIHOLE_DNS_2/d;/QUERY_LOGGING/d;/INSTALL_WEB/d;' "${setupVars}"
  960.   fi
  961.     {
  962.   echo "PIHOLE_INTERFACE=${PIHOLE_INTERFACE}"
  963.   echo "IPV4_ADDRESS=${IPV4_ADDRESS}"
  964.   echo "IPV6_ADDRESS=${IPV6_ADDRESS}"
  965.   echo "PIHOLE_DNS_1=${PIHOLE_DNS_1}"
  966.   #-add
  967.   echo "DNSSEC=true"
  968.   echo "PIHOLE_DNS_2=${PIHOLE_DNS_2}"
  969.   echo "QUERY_LOGGING=${QUERY_LOGGING}"
  970.   echo "INSTALL_WEB=${INSTALL_WEB}"
  971.     }>> "${setupVars}"
  972.  
  973.   # Look for DNS server settings which would have to be reapplied
  974.   source "${setupVars}"
  975.   source "${PI_HOLE_LOCAL_REPO}/advanced/Scripts/webpage.sh"
  976.  
  977.   if [[ "${DNS_FQDN_REQUIRED}" != "" ]] ; then
  978.     ProcessDNSSettings
  979.   fi
  980.  
  981.   if [[ "${DHCP_ACTIVE}" != "" ]] ; then
  982.     ProcessDHCPSettings
  983.   fi
  984. }
  985.  
  986. installLogrotate() {
  987.   # Install the logrotate script
  988.   echo ":::"
  989.   echo -n "::: Installing latest logrotate script..."
  990.   cp ${PI_HOLE_LOCAL_REPO}/advanced/logrotate /etc/pihole/logrotate
  991.   # Different operating systems have different user / group
  992.   # settings for logrotate that makes it impossible to create
  993.   # a static logrotate file that will work with e.g.
  994.   # Rasbian and Ubuntu at the same time. Hence, we have to
  995.   # customize the logrotate script here in order to reflect
  996.   # the local properties of the /var/log directory
  997.   logusergroup="$(stat -c '%U %G' /var/log)"
  998.   if [[ ! -z $logusergroup ]]; then
  999.     sed -i "s/# su #/su ${logusergroup}/" /etc/pihole/logrotate
  1000.   fi
  1001.   echo " done!"
  1002. }
  1003.  
  1004. installPihole() {
  1005.   # Install base files and web interface
  1006.   create_pihole_user
  1007.  
  1008.   if [[ ${INSTALL_WEB} == true ]]; then
  1009.     if [ ! -d "/var/www/html" ]; then
  1010.       mkdir -p /var/www/html
  1011.     fi
  1012.     chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} /var/www/html
  1013.     chmod 775 /var/www/html
  1014.     usermod -a -G ${LIGHTTPD_GROUP} pihole
  1015.     if [ -x "$(command -v lighty-enable-mod)" ]; then
  1016.       lighty-enable-mod fastcgi fastcgi-php > /dev/null || true
  1017.     else
  1018.       printf "\n:::\tWarning: 'lighty-enable-mod' utility not found. Please ensure fastcgi is enabled if you experience issues.\n"
  1019.     fi
  1020.   fi
  1021.   installScripts
  1022.   installConfigs
  1023.   CreateLogFile
  1024.   if [[ ${INSTALL_WEB} == true ]]; then
  1025.     installPiholeWeb
  1026.   fi
  1027.   installCron
  1028.   installLogrotate
  1029.   FTLdetect || echo "::: FTL Engine not installed."
  1030.   configureFirewall
  1031.   finalExports
  1032.   #runGravity
  1033. }
  1034.  
  1035. accountForRefactor() {
  1036.   # At some point in the future this list can be pruned, for now we'll need it to ensure updates don't break.
  1037.  
  1038.   # Refactoring of install script has changed the name of a couple of variables. Sort them out here.
  1039.  
  1040.   sed -i 's/piholeInterface/PIHOLE_INTERFACE/g' ${setupVars}
  1041.   sed -i 's/IPv4_address/IPV4_ADDRESS/g' ${setupVars}
  1042.   sed -i 's/IPv4addr/IPV4_ADDRESS/g' ${setupVars}
  1043.   sed -i 's/IPv6_address/IPV6_ADDRESS/g' ${setupVars}
  1044.   sed -i 's/piholeIPv6/IPV6_ADDRESS/g' ${setupVars}
  1045.   sed -i 's/piholeDNS1/PIHOLE_DNS_1/g' ${setupVars}
  1046.   sed -i 's/piholeDNS2/PIHOLE_DNS_2/g' ${setupVars}
  1047.  
  1048. }
  1049.  
  1050. updatePihole() {
  1051.   accountForRefactor
  1052.   # Install base files and web interface
  1053.   installScripts
  1054.   installConfigs
  1055.   CreateLogFile
  1056.   if [[ ${INSTALL_WEB} == true ]]; then
  1057.     installPiholeWeb
  1058.   fi
  1059.   installCron
  1060.   installLogrotate
  1061.   FTLdetect || echo "::: FTL Engine not installed."
  1062.   finalExports #re-export setupVars.conf to account for any new vars added in new versions
  1063.   #runGravity
  1064. }
  1065.  
  1066.  
  1067.  
  1068. checkSelinux() {
  1069.   if command -v getenforce &> /dev/null; then
  1070.     echo ":::"
  1071.     echo -n "::: SELinux Support Detected... Mode: "
  1072.     enforceMode=$(getenforce)
  1073.     echo "${enforceMode}"
  1074.     if [[ "${enforceMode}" == "Enforcing" ]]; then
  1075.       whiptail --title "SELinux Enforcing Detected" --yesno "SELinux is being Enforced on your system!\n\nPi-hole currently does not support SELinux, but you may still continue with the installation.\n\nNote: Admin UI Will not function fully without setting your policies correctly\n\nContinue installing Pi-hole?" ${r} ${c} || \
  1076.       { echo ":::"; echo "::: Not continuing install after SELinux Enforcing detected."; exit 1; }
  1077.       echo ":::"
  1078.       echo "::: Continuing installation with SELinux Enforcing."
  1079.       echo "::: Please refer to official SELinux documentation to create a custom policy."
  1080.     fi
  1081.   fi
  1082. }
  1083.  
  1084.  
  1085.  
  1086. update_dialogs() {
  1087.   # reconfigure
  1088.   if [ "${reconfigure}" = true ]; then
  1089.     opt1a="Repair"
  1090.     opt1b="This will retain existing settings"
  1091.     strAdd="You will remain on the same version"
  1092.   else
  1093.     opt1a="Update"
  1094.     opt1b="This will retain existing settings."
  1095.     strAdd="You will be updated to the latest version."
  1096.   fi
  1097.   opt2a="Reconfigure"
  1098.   opt2b="This will allow you to enter new settings"
  1099.  
  1100.   UpdateCmd=$(whiptail --title "Existing Install Detected!" --menu "\n\nWe have detected an existing install.\n\nPlease choose from the following options: \n($strAdd)" ${r} ${c} 2 \
  1101.   "${opt1a}"  "${opt1b}" \
  1102.   "${opt2a}"  "${opt2b}" 3>&2 2>&1 1>&3) || \
  1103.   { echo "::: Cancel selected. Exiting"; exit 1; }
  1104.  
  1105.   case ${UpdateCmd} in
  1106.     ${opt1a})
  1107.       echo "::: ${opt1a} option selected."
  1108.       useUpdateVars=true
  1109.       ;;
  1110.     ${opt2a})
  1111.       echo "::: ${opt2a} option selected"
  1112.       useUpdateVars=false
  1113.       ;;
  1114.     esac
  1115. }
  1116.  
  1117. clone_or_update_repos() {
  1118. if [[ "${reconfigure}" == true ]]; then
  1119.       echo "::: --reconfigure passed to install script. Not downloading/updating local repos"
  1120.     else
  1121.       # Get Git files for Core and Admin
  1122.       getGitFiles ${PI_HOLE_LOCAL_REPO} ${piholeGitUrl} || \
  1123.         { echo "!!! Unable to clone ${piholeGitUrl} into ${PI_HOLE_LOCAL_REPO}, unable to continue."; \
  1124.           exit 1; \
  1125.         }
  1126.  
  1127.       if [[ ${INSTALL_WEB} == true ]]; then
  1128.         getGitFiles ${webInterfaceDir} ${webInterfaceGitUrl} || \
  1129.         { echo "!!! Unable to clone ${webInterfaceGitUrl} into ${webInterfaceDir}, unable to continue."; \
  1130.           exit 1; \
  1131.         }
  1132.       fi
  1133.     fi
  1134. }
  1135.  
  1136. FTLinstall() {
  1137.   # Download and install FTL binary
  1138.   local binary="${1}"
  1139.   local latesttag
  1140.   local orig_dir
  1141.   echo -n ":::  Installing FTL... "
  1142.  
  1143.   orig_dir="${PWD}"
  1144.   latesttag=$(curl -sI https://github.com/pi-hole/FTL/releases/latest | grep "Location" | awk -F '/' '{print $NF}')
  1145.   # Tags should always start with v, check for that.
  1146.   if [[ ! "${latesttag}" == v* ]]; then
  1147.     echo "failed (error in getting latest release location from GitHub)"
  1148.     return 1
  1149.   fi
  1150.   if curl -sSL --fail "https://github.com/pi-hole/FTL/releases/download/${latesttag%$'\r'}/${binary}" -o "/tmp/${binary}"; then
  1151.     # Get sha1 of the binary we just downloaded for verification.
  1152.     curl -sSL --fail "https://github.com/pi-hole/FTL/releases/download/${latesttag%$'\r'}/${binary}.sha1" -o "/tmp/${binary}.sha1"
  1153.     # Check if we just downloaded text, or a binary file.
  1154.     cd /tmp
  1155.     if sha1sum --status --quiet -c "${binary}".sha1; then
  1156.       echo -n "transferred... "
  1157.       stop_service pihole-FTL &> /dev/null
  1158.       install -T -m 0755 /tmp/${binary} /usr/bin/pihole-FTL
  1159.       cd "${orig_dir}"
  1160.       install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/pihole-FTL.service" "/etc/init.d/pihole-FTL"
  1161.       echo "done."
  1162.       return 0
  1163.     else
  1164.       echo "failed (download of binary from Github failed)"
  1165.       cd "${orig_dir}"
  1166.       return 1
  1167.     fi
  1168.   else
  1169.     cd "${orig_dir}"
  1170.     echo "failed (URL not found.)"
  1171.   fi
  1172. }
  1173.  
  1174. FTLdetect() {
  1175.   # Detect suitable FTL binary platform
  1176.   echo ":::"
  1177.   echo "::: Downloading latest version of FTL..."
  1178.  
  1179.   local machine
  1180.   local binary
  1181.  
  1182.   machine=$(uname -m)
  1183.  
  1184.   if [[ $machine == arm* || $machine == *aarch* ]]; then
  1185.     # ARM
  1186.     local rev=$(uname -m | sed "s/[^0-9]//g;")
  1187.     local lib=$(ldd /bin/ls | grep -E '^\s*/lib' | awk '{ print $1 }')
  1188.     if [[ "$lib" == "/lib/ld-linux-aarch64.so.1" ]]; then
  1189.       echo ":::  Detected ARM-aarch64 architecture"
  1190.       binary="pihole-FTL-aarch64-linux-gnu"
  1191.     elif [[ "$lib" == "/lib/ld-linux-armhf.so.3" ]]; then
  1192.       if [ "$rev" -gt "6" ]; then
  1193.         echo ":::  Detected ARM-hf architecture (armv7+)"
  1194.         binary="pihole-FTL-arm-linux-gnueabihf"
  1195.       else
  1196.         echo ":::  Detected ARM-hf architecture (armv6 or lower)"
  1197.         echo ":::  Using ARM binary"
  1198.         binary="pihole-FTL-arm-linux-gnueabi"
  1199.       fi
  1200.     else
  1201.       echo ":::  Detected ARM architecture"
  1202.       binary="pihole-FTL-arm-linux-gnueabi"
  1203.     fi
  1204.   elif [[ $machine == x86_64 ]]; then
  1205.     # 64bit
  1206.     echo ":::  Detected x86_64 architecture"
  1207.     binary="pihole-FTL-linux-x86_64"
  1208.   else
  1209.     # Something else - we try to use 32bit executable and warn the user
  1210.     if [[ ! $machine == i686 ]]; then
  1211.       echo ":::  Not able to detect architecture (unknown: ${machine}), trying 32bit executable"
  1212.       echo ":::  Contact Pi-hole support if you experience problems (like FTL not running)"
  1213.     else
  1214.       echo ":::  Detected 32bit (i686) architecture"
  1215.     fi
  1216.     binary="pihole-FTL-linux-x86_32"
  1217.   fi
  1218.  
  1219.   FTLinstall "${binary}" || return 1
  1220.  
  1221. }
  1222.  
  1223. main() {
  1224.  
  1225.   ######## FIRST CHECK ########
  1226.   # Must be root to install
  1227.  
  1228.   #echo ":::"
  1229.   #if [[ ${EUID} -eq 0 ]]; then
  1230.     #echo "::: You are root."
  1231.   #else
  1232.     #echo "::: Script called with non-root privileges. The Pi-hole installs server packages and configures"
  1233.     #echo "::: system networking, it requires elevated rights. Please check the contents of the script for"
  1234.     #echo "::: any concerns with this requirement. Please be sure to download this script from a trusted source."
  1235.     #echo ":::"
  1236.     #echo "::: Detecting the presence of the sudo utility for continuation of this install..."
  1237.  
  1238.     #if command -v sudo &> /dev/null; then
  1239.       #echo "::: Utility sudo located."
  1240.       #exec curl -sSL https://raw.githubusercontent.com/pi-hole/pi-hole/master/automated%20install/basic-install.sh | sudo bash "$@"
  1241.       #exit $?
  1242.     #else
  1243.       #echo "::: sudo is needed for the Web interface to run pihole commands.  Please run this script as root and it will be automatically installed."
  1244.       #exit 1
  1245.     #fi
  1246.   #fi
  1247.     install_OpenVPN
  1248.   # Check for supported distribution - LEAVE IN
  1249.   distro_check
  1250.  
  1251.   # Check arguments for the undocumented flags - CHECK UNATTENDED
  1252.   for var in "$@"; do
  1253.     case "$var" in
  1254.       "--reconfigure"  ) reconfigure=true;;
  1255.       "--i_do_not_follow_recommendations"   ) skipSpaceCheck=false;;
  1256.       "--unattended"     ) runUnattended=true;;
  1257.     esac
  1258.   done
  1259.  
  1260.   if [[ -f ${setupVars} ]]; then
  1261.     if [[ "${runUnattended}" == true ]]; then
  1262.       echo "::: --unattended passed to install script, no whiptail dialogs will be displayed"
  1263.       useUpdateVars=true
  1264.     else
  1265.       update_dialogs
  1266.     fi
  1267.   fi
  1268.  
  1269.   # Start the installer
  1270.   # Verify there is enough disk space for the install
  1271.   if [[ "${skipSpaceCheck}" == true ]]; then
  1272.     echo "::: --i_do_not_follow_recommendations passed to script, skipping free disk space verification!"
  1273.   else
  1274.     verifyFreeDiskSpace
  1275.   fi
  1276.  
  1277.   # Update package cache - LEAVE IN
  1278.   update_package_cache || exit 1
  1279.  
  1280.   # Notify user of package availability - CHECK NEEDED
  1281.   notify_package_updates_available
  1282.  
  1283.   # Install packages used by this installation script - LEAVE IN
  1284.   install_dependent_packages INSTALLER_DEPS[@]
  1285.  
  1286.    # Check if SELinux is Enforcing - CHECK NEEDED
  1287.   checkSelinux
  1288.  
  1289.  
  1290.   if [[ ${useUpdateVars} == false ]]; then
  1291.     # Display welcome dialogs
  1292.    
  1293.     # Create directory for Pi-hole storage
  1294.     mkdir -p /etc/pihole/
  1295.  
  1296.     stop_service dnsmasq
  1297.     if [[ ${INSTALL_WEB} == true ]]; then
  1298.       stop_service lighttpd
  1299.     fi
  1300.    
  1301.     #chooseInterface - CHECK NEEDED
  1302.     PIHOLE_INTERFACE="tun0"
  1303.     # Decide what upstream DNS Servers to use
  1304.     PIHOLE_DNS_1="8.8.8.8"
  1305.     PIHOLE_DNS_2="8.8.4.4"
  1306.     # Let the user decide if they want to block ads over IPv4 and/or IPv6
  1307.     use4andor6
  1308.     #setAdminFlag
  1309.     INSTALL_WEB=false
  1310.     #setLogging
  1311.     QUERY_LOGGING=false
  1312.     # Clone/Update the repos
  1313.     clone_or_update_repos
  1314.  
  1315.        # Install packages used by the Pi-hole
  1316.     if [[ ${INSTALL_WEB} == true ]]; then
  1317.       DEPS=("${PIHOLE_DEPS[@]}" "${PIHOLE_WEB_DEPS[@]}")
  1318.     else
  1319.       DEPS=("${PIHOLE_DEPS[@]}")
  1320.     fi
  1321.     install_dependent_packages DEPS[@]
  1322.  
  1323.  
  1324.     # Install and log everything to a file
  1325.     installPihole | tee ${tmpLog}
  1326.   else
  1327.     # Clone/Update the repos
  1328.     clone_or_update_repos
  1329.  
  1330.     # Source ${setupVars} for use in the rest of the functions.
  1331.     source ${setupVars}
  1332.  
  1333.     # Install packages used by the Pi-hole
  1334.     if [[ ${INSTALL_WEB} == true ]]; then
  1335.       DEPS=("${PIHOLE_DEPS[@]}" "${PIHOLE_WEB_DEPS[@]}")
  1336.     else
  1337.       DEPS=("${PIHOLE_DEPS[@]}")
  1338.     fi
  1339.     install_dependent_packages DEPS[@]
  1340.  
  1341.     updatePihole | tee ${tmpLog}
  1342.   fi
  1343.  
  1344.   # Move the log file into /etc/pihole for storage
  1345.   mv ${tmpLog} ${instalLogLoc}
  1346.  
  1347.   if [[ ${INSTALL_WEB} == true ]]; then
  1348.     # Add password to web UI if there is none
  1349.     pw=""
  1350.     if [[ $(grep 'WEBPASSWORD' -c /etc/pihole/setupVars.conf) == 0 ]] ; then
  1351.         pw=$(tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 8)
  1352.         . /opt/pihole/webpage.sh
  1353.         echo "WEBPASSWORD=$(HashPassword ${pw})" >> ${setupVars}
  1354.     fi
  1355.   fi
  1356.   echo "Updating system"
  1357.     sudo apt-get update && sudo apt-get -y upgrade
  1358.  
  1359.   echo "::: Restarting services..."
  1360.   #restart openvpn
  1361.   sudo systemctl restart openvpn@server
  1362.   # Start services
  1363.   start_service dnsmasq
  1364.   enable_service dnsmasq
  1365.  
  1366.   if [[ ${INSTALL_WEB} == true ]]; then
  1367.     start_service lighttpd
  1368.     enable_service lighttpd
  1369.   fi
  1370.  
  1371.   runGravity
  1372.  
  1373.   start_service pihole-FTL
  1374.   enable_service pihole-FTL
  1375.  
  1376.  
  1377.  
  1378.   #download full openroad warrior script for further use
  1379.   wget https://git.io/vpn -O openvpn-install.sh
  1380.   #and full orignal pihole script for good measure
  1381.   wget https://install.pi-hole.net
  1382.  
  1383.  
  1384.  
  1385.   echo "::: Update complete!"
  1386.  
  1387.   echo "::: The install log is located at: /etc/pihole/install.log"
  1388. }
  1389.  
  1390. if [[ "${PH_TEST}" != true ]] ; then
  1391.   main "$@"
  1392. fi
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top