Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
freedombone-app-pihole 13.46 KiB
#!/bin/bash
#  _____               _           _
# |   __|___ ___ ___ _| |___ _____| |_ ___ ___ ___
# |   __|  _| -_| -_| . | . |     | . | . |   | -_|
# |__|  |_| |___|___|___|___|_|_|_|___|___|_|_|___|
#
#                              Freedom in the Cloud
#
# pi-hole ad blocker
#
# Adapted from instructions at:
#  http://jacobsalmela.com/block-millions-ads-network-wide-with-a-raspberry-pi-hole-2-0/#manualsetup
#
# License
# =======
#
# Copyright (C) 2016-2019 Bob Mottram <bob@freedombone.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

VARIANTS='full full-vim adblocker'

APP_CATEGORY=other

IN_DEFAULT_INSTALL=0
SHOW_ON_ABOUT=0
SHOW_CLEARNET_ADDRESS_ON_ABOUT=0
SHOW_DOMAIN_IN_WEBADMIN=0
NOT_ON_API=1
REQUIRES_APP=

PIHOLE_IFACE=eth0
PIHOLE_DNS1='91.239.100.100'
PIHOLE_DNS2='89.233.43.71'

piholeBasename=pihole
piholeDir=/etc/$piholeBasename
PIHOLE_CUSTOM_ADLIST=$piholeDir/adlists.list
PIHOLE_BLACKLIST=$piholeDir/blacklist.txt
PIHOLE_WHITELIST=$piholeDir/whitelist.txt

PIHOLE_REPO="https://github.com/pi-hole/pi-hole"
PIHOLE_COMMIT='ddbdb51d209fa9eea2451a1bebfaeaef23a9b77b'

PIHOLE_SHORT_DESCRIPTION=$'Ad blocker'
PIHOLE_DESCRIPTION=$'The Pi-hole is a DNS sinkhole that protects your devices from unwanted content, without installing any client-side software.'
PIHOLE_MOBILE_APP_URL=

pihole_variables=(ONION_ONLY
                  PIHOLE_IFACE
                  PIHOLE_DNS1
                  PIHOLE_DNS2)

function logging_on_pihole {
    echo -n ''
}

function logging_off_pihole {
    echo -n ''
}

function pihole_update_manpages {
    if [ ! -d /usr/local/share/man/man8 ]; then
        mkdir -p /usr/local/share/man/man8
    fi
    if [ ! -d /usr/local/share/man/man5 ]; then
        mkdir -p /usr/local/share/man/man5
    fi
    cp "$INSTALL_DIR/$piholeBasename/manpages/pihole.8" /usr/local/share/man/man8/pihole.8
    cp "$INSTALL_DIR/$piholeBasename/manpages/pihole-FTL.8" /usr/local/share/man/man8/pihole-FTL.8
    cp "$INSTALL_DIR/$piholeBasename/manpages/pihole-FTL.conf.5" /usr/local/share/man/man5/pihole-FTL.conf.5
}

function pihole_copy_files {
    if [ ! -d /etc/.pihole ]; then
        mkdir /etc/.pihole
    fi
    cp "$INSTALL_DIR/pihole/adlists.default" /etc/.pihole/adlists.default
    cp "$INSTALL_DIR/pihole/adlists.default" $piholeDir/adlists.default
    if [ ! -f $PIHOLE_CUSTOM_ADLIST ]; then
        cp "$INSTALL_DIR/pihole/adlists.default" $PIHOLE_CUSTOM_ADLIST
    fi
    cp "$INSTALL_DIR/pihole/advanced/Scripts/"* /opt/$piholeBasename
    if [ -f /etc/dnsmasq.d/01-pihole.conf ]; then
        rm /etc/dnsmasq.d/01-pihole.conf
    fi
    cp "$INSTALL_DIR/pihole/advanced/pihole.cron" /etc/cron.d/pihole
    cp "$INSTALL_DIR/pihole/gravity.sh" /opt/$piholeBasename
    chmod +x /opt/pihole/*.sh
}

function pihole_change_ipv4 {
    new_ipv4="$1"
    if [ -f /usr/local/bin/pihole ]; then
        setupVars=$piholeDir/setupVars.conf
        if [ -f $setupVars ]; then
            sed -i "s|IPv4_address=.*|IPv4_address=${new_ipv4}|g" $setupVars
        fi
    fi
}

function pihole_update {
    if [ ! -f /usr/local/bin/gravity.sh ]; then
        return
    fi

    if [ ! -f "$HOME/${PROJECT_NAME}-wifi.cfg" ]; then
        PIHOLE_IFACE=eth0
    else
        read_config_param WIFI_INTERFACE
        PIHOLE_IFACE=$WIFI_INTERFACE
    fi

    IPv4_address="$(get_ipv4_address)"
    IPv6_address="$(get_ipv6_address)"

    setupVars=$piholeDir/setupVars.conf
    echo "piholeInterface=${PIHOLE_IFACE}" > ${setupVars}
    echo "IPV4_ADDRESS=${IPv4_address}" >> ${setupVars}
    if [ ${#IPv6_address} -gt 0 ]; then
        echo "IPV6_ADDRESS=${IPv6_address}" >> ${setupVars}
    fi
    echo "piholeDNS1=${PIHOLE_DNS1}" >> ${setupVars}
    echo "piholeDNS2=${PIHOLE_DNS1}" >> ${setupVars}

    { echo 'domain-needed';
      echo 'bogus-priv';
      echo 'no-resolv';
      echo "server=${PIHOLE_DNS1}";
      echo "server=${PIHOLE_DNS2}";
      echo "interface=${PIHOLE_IFACE}";
      echo 'listen-address=127.0.0.1'; } > /etc/dnsmasq.conf

    pihole_update_manpages

    pihole -g
    systemctl restart dnsmasq

    # avoid having the tripwire report pihole updates
    if ! grep -q '!/etc/pihole' /etc/tripwire/twpol.txt; then
        sed -i '\|/etc\t\t->.*|a\    !/etc/pihole ;' /etc/tripwire/twpol.txt
    fi
}

function pihole_change_upstream_dns {
    data=$(mktemp 2>/dev/null)
    dialog --backtitle $"Ad Blocker Upstream DNS" \
           --radiolist $"Pick a domain name service (DNS):" 29 50 20 \
           1 $"UncensoredDNS" on \
           2 $"Digital Courage" off \
           3 $"German Privacy Foundation 1" off \
           4 $"German Privacy Foundation 2" off \
           5 $"Chaos Computer Club" off \
           6 $"ClaraNet" off \
           7 $"OpenNIC 1" off \
           8 $"OpenNIC 2" off \
           9 $"OpenNIC 3" off \
           10 $"OpenNIC 4" off \
           11 $"OpenNIC 5" off \
           12 $"OpenNIC 6" off \
           13 $"OpenNIC 7" off \
           14 $"PowerNS" off \
           15 $"ValiDOM" off \
           16 $"Freie Unzensierte" off \
           17 $"DNS.Watch" off \
           18 $"uncensoreddns.org" off \
           19 $"Lorraine Data Network" off \
           20 $"Google" off 2> "$data"
    sel=$?
    case $sel in
        1) rm -f "$data"
           exit 1;;
        255) rm -f "$data"
             exit 1;;
    esac
    case $(cat "$data") in
        1) PIHOLE_DNS1='91.239.100.100'
           PIHOLE_DNS2='89.233.43.71'
           ;;
        2) PIHOLE_DNS1='85.214.73.63'
           PIHOLE_DNS2='213.73.91.35'
           ;;
        3) PIHOLE_DNS1='87.118.100.175'
           PIHOLE_DNS2='94.75.228.29'
           ;;
        4) PIHOLE_DNS1='85.25.251.254'
           PIHOLE_DNS2='2.141.58.13'
           ;;
        5) PIHOLE_DNS1='213.73.91.35'
           PIHOLE_DNS2='85.214.73.63'
           ;;
        6) PIHOLE_DNS1='212.82.225.7'
           PIHOLE_DNS2='212.82.226.212'
           ;;
        7) PIHOLE_DNS1='58.6.115.42'
           PIHOLE_DNS2='58.6.115.43'
           ;;
        8) PIHOLE_DNS1='119.31.230.42'
           PIHOLE_DNS2='200.252.98.162'
           ;;
        9) PIHOLE_DNS1='217.79.186.148'
           PIHOLE_DNS2='81.89.98.6'
           ;;
        10) PIHOLE_DNS1='78.159.101.37'
            PIHOLE_DNS2='203.167.220.153'
            ;;
        11) PIHOLE_DNS1='82.229.244.191'
            PIHOLE_DNS2='82.229.244.191'
            ;;
        12) PIHOLE_DNS1='216.87.84.211'
            PIHOLE_DNS2='66.244.95.20'
            ;;
        13) PIHOLE_DNS1='207.192.69.155'
            PIHOLE_DNS2='72.14.189.120'
            ;;
        14) PIHOLE_DNS1='194.145.226.26'
            PIHOLE_DNS2='77.220.232.44'
            ;;
        15) PIHOLE_DNS1='78.46.89.147'
            PIHOLE_DNS2='88.198.75.145'
            ;;
        16) PIHOLE_DNS1='85.25.149.144'
            PIHOLE_DNS2='87.106.37.196'
            ;;
        17) PIHOLE_DNS1='84.200.69.80'
            PIHOLE_DNS2='84.200.70.40'
            ;;
        18) PIHOLE_DNS1='91.239.100.100'
            PIHOLE_DNS2='89.233.43.71'
            ;;
        19) PIHOLE_DNS1='80.67.188.188'
            PIHOLE_DNS2='89.234.141.66'
            ;;
        20) PIHOLE_DNS1='8.8.8.8'
            PIHOLE_DNS2='4.4.4.4'
            dialog --title $"WARNING" \
                   --msgbox $"\\nGoogle's main purpose for providing DNS resolvers is to spy upon people and know which sites they are visiting.\\n\\nThis is something to consider, and you should only really be using Google DNS as a last resort if other resolvers are unavailable." 12 60
            ;;
        255) rm -f "$data"
             exit 1;;
    esac
    rm -f "$data"
    write_config_param "PIHOLE_DNS1" "$PIHOLE_DNS1"
    write_config_param "PIHOLE_DNS2" "$PIHOLE_DNS2"
}

function update_pihole_interactive {
    clear
    echo $'Updating Ad Blocker Lists'
    echo ''
    pihole_update
}

function configure_firewall_for_pihole {
    firewall_add DNS 53
}

function pihole_pause {
    pihole disable
    dialog --title $"Pause Ad Blocker" \
           --msgbox $"Ad blocking is paused" 6 60
}

function pihole_resume {
    pihole enable
    dialog --title $"Resume Ad Blocker" \
           --msgbox $"Ad blocking has resumed" 6 60
}
function configure_interactive_pihole {
    W=(1 $"Edit ads list"
       2 $"Edit blacklisted domain names"
       3 $"Edit whitelisted domain names"
       4 $"Change upstream DNS servers"
       5 $"Pause blocker"
       6 $"Resume blocker")

    while true
    do
        # shellcheck disable=SC2068
        selection=$(dialog --backtitle $"Freedombone Administrator Control Panel" --title $"Ad blocker" --menu $"Choose an operation, or ESC for main menu:" 13 60 9 "${W[@]}" 3>&2 2>&1 1>&3)

        if [ ! "$selection" ]; then
           break
        fi

        case $selection in
            1) editor $PIHOLE_CUSTOM_ADLIST
               update_pihole_interactive
               ;;
            2) editor $PIHOLE_BLACKLIST
               update_pihole_interactive
               ;;
            3) editor $PIHOLE_WHITELIST
               update_pihole_interactive
               ;;
            4) pihole_change_upstream_dns
               update_pihole_interactive
               ;;
            5) pihole_pause
               ;;
            6) pihole_resume
               ;;
        esac
    done
}

function install_interactive_pihole {
    APP_INSTALLED=1
}

function reconfigure_pihole {
    echo -n ''
}

function upgrade_pihole {
    CURR_PIHOLE_COMMIT=$(get_completion_param "pihole commit")
    if [[ "$CURR_PIHOLE_COMMIT" == "$PIHOLE_COMMIT" ]]; then
        return
    fi

    function_check set_repo_commit
    set_repo_commit "$INSTALL_DIR/pihole" "pihole commit" "$PIHOLE_COMMIT" $PIHOLE_REPO

    pihole_copy_files
    pihole_update
}

function backup_local_pihole {
    function_check backup_directory_to_usb
    backup_directory_to_usb $piholeDir pihole
}

function restore_local_pihole {
    function_check restore_directory_from_usb
    restore_directory_from_usb / pihole
}

function backup_remote_pihole {
    echo -n ''
}

function restore_remote_pihole {
    echo -n ''
}

function remove_pihole {
    $REMOVE_PACKAGES_PURGE dnsmasq

    if [ ! -d /var/www/pihole ]; then
        rm -rf /var/www/pihole
    fi

    if [ -f /usr/local/bin/gravity.sh ]; then
        rm /usr/local/bin/gravity.sh
    fi

    if [ -f /usr/local/bin/pihole ]; then
        rm /usr/local/bin/pihole
    fi

    if [ -d /opt/pihole ]; then
        rm -rf /opt/pihole
    fi

    if [ -d $piholeDir ]; then
        rm -rf $piholeDir
    fi

    if [ -d /etc/.pihole ]; then
        rm -rf /etc/.pihole
    fi

    if [ -f /var/log/pihole.log ]; then
        rm /var/log/pihole.log
    fi

    if [ -f /etc/cron.d/pihole ]; then
        rm /etc/cron.d/pihole
    fi

    if [ -d "$INSTALL_DIR/pihole" ]; then
        rm -rf "$INSTALL_DIR/pihole"
    fi

    firewall_remove 53
    userdel -r pihole
}

function install_pihole {
    increment_app_install_progress

    $INSTALL_PACKAGES dnsmasq curl

    increment_app_install_progress

    adduser --disabled-login --gecos 'pi-hole' pihole
    if [ ! -d /home/pihole ]; then
        echo $"/home/pihole directory not created"
        exit 53
    fi

    increment_app_install_progress

    chmod 600 /etc/shadow
    chmod 600 /etc/gshadow
    usermod -a -G www-data pihole
    chmod 0000 /etc/shadow
    chmod 0000 /etc/gshadow

    systemctl enable dnsmasq

    increment_app_install_progress

    if [ ! -d "$INSTALL_DIR" ]; then
        mkdir -p "$INSTALL_DIR"
    fi

    if [ ! -d "$INSTALL_DIR/pihole" ]; then
        cd "$INSTALL_DIR" || exit 78

        if [ -d /repos/pihole ]; then
            mkdir pihole
            cp -r -p /repos/pihole/. pihole
            cd pihole || exit 24
            git pull
        else
            git_clone $PIHOLE_REPO pihole
        fi

        if [ ! -d "$INSTALL_DIR/pihole" ]; then
            exit 52
        fi
        cd "$INSTALL_DIR/pihole" || exit 26
        git checkout "$PIHOLE_COMMIT" -b "$PIHOLE_COMMIT"
        set_completion_param "pihole commit" "$PIHOLE_COMMIT"
    fi

    increment_app_install_progress

    if [ ! -d /var/www/pihole/htdocs ]; then
        mkdir -p /var/www/pihole/htdocs
    fi

    # blank file which takes the place of ads
    { echo '<html>';
      echo '<body>';
      echo '</body>';
      echo '</html>'; } > /var/www/pihole/htdocs/index.html

    if [ ! -f "$INSTALL_DIR/pihole/gravity.sh" ]; then
        exit 26
    fi
    cp "$INSTALL_DIR/pihole/gravity.sh" /usr/local/bin/gravity.sh
    chmod 755 /usr/local/bin/gravity.sh

    if [ ! -f "$INSTALL_DIR/pihole/pihole" ]; then
        exit 52
    fi
    cp "$INSTALL_DIR/pihole/pihole" /usr/local/bin/pihole
    chmod 755 /usr/local/bin/pihole

    if [ ! -d $piholeDir ]; then
        mkdir $piholeDir
    fi
    if [ ! -d /opt/pihole ]; then
        mkdir -p /opt/pihole
    fi

    increment_app_install_progress

    pihole_copy_files

    increment_app_install_progress

    chown -R www-data:www-data /var/www/pihole/htdocs

    configure_firewall_for_pihole
    increment_app_install_progress

    pihole_update

    increment_app_install_progress

    APP_INSTALLED=1
}

# NOTE: deliberately no exit 0