From 5902be2a49214f614b29c114c810dda4d3c047f9 Mon Sep 17 00:00:00 2001 From: Jacob Salmela Date: Wed, 24 May 2017 22:07:15 -0500 Subject: [PATCH] comments for every line --- advanced/Scripts/piholeDebug.sh | 145 ++++++++++++++++++++++++++++++-- 1 file changed, 138 insertions(+), 7 deletions(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index d484354a..5e280e62 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -32,6 +32,7 @@ WHITELISTMATCHES="/tmp/whitelistmatches.list" readonly FTLLOG="/var/log/pihole-FTL.log" coltable=/opt/pihole/COL_TABLE +# These provide the colors we need for making the log more readable if [[ -f ${coltable} ]]; then source ${coltable} else @@ -47,7 +48,7 @@ else fi echo_succes_or_fail() { - # Set the first argument passed to tihs function as a named variable for better readability + # Set the first argument passed to this function as a named variable for better readability local message="${1}" # If the command was successful (a zero), if [[ $? -eq 0 ]]; then @@ -102,80 +103,133 @@ if_directory_exists() { } check_core_version() { + # Checks the core version of the Pi-hole codebase echo_current_diagnostic "Pi-hole Versions" + # Store the error message in a variable in case we want to change and/or reuse it local error_msg="git status failed" + # If the pihole git directory exists, if_directory_exists "${PIHOLEGITDIR}" && \ + # move into it cd "${PIHOLEGITDIR}" || \ + # if not, report an error echo -e "pihole repo does not exist" 2>&1 | tee -a "${DEBUG_LOG}" + # If the git status command completes successfully, + # we can assume we can get the information we want if git status &> /dev/null; then + # The current version the user is on PI_HOLE_VERSION=$(git describe --tags --abbrev=0); + # What branch they are on PI_HOLE_BRANCH=$(git rev-parse --abbrev-ref HEAD); + # The commit they are on PI_HOLE_COMMIT=$(git describe --long --dirty --tags --always) + # echo this information out to the user in a nice format echo -e " ${INFO} Core: ${PI_HOLE_VERSION} ${INFO} Branch: ${PI_HOLE_BRANCH} ${INFO} Commit: ${PI_HOLE_COMMIT}" 2>&1 | tee -a "${DEBUG_LOG}" + # If git status failed, else + # Return an error message echo -e "${error_msg}" 2>&1 | tee -a "${DEBUG_LOG}" + # and exit with a non zero code return 1 fi } check_web_version() { + # Local variable for the error message local error_msg="git status failed" + # If the directory exists, if_directory_exists "${ADMINGITDIR}" && \ + # move into it cd "${ADMINGITDIR}" || \ + # if not, give an error message echo -e "repo does not exist" 2>&1 | tee -a "${DEBUG_LOG}" + # If the git status command completes successfully, + # we can assume we can get the information we want if git status &> /dev/null; then + # The current version the user is on WEB_VERSION=$(git describe --tags --abbrev=0); + # What branch they are on WEB_BRANCH=$(git rev-parse --abbrev-ref HEAD); + # The commit they are on WEB_COMMIT=$(git describe --long --dirty --tags --always) + # echo this information out to the user in a nice format echo -e " ${INFO} Web: ${WEB_VERSION} ${INFO} Branch: ${WEB_BRANCH} ${INFO} Commit: ${WEB_COMMIT}" 2>&1 | tee -a "${DEBUG_LOG}" + # If git status failed, else + # Return an error message echo -e "${error_msg}" 2>&1 | tee -a "${DEBUG_LOG}" + # and exit with a non zero code return 1 fi } check_ftl_version() { + # Use the built in command to check FTL's version FTL_VERSION=$(pihole-FTL version) + # and display it to the user echo -e " ${INFO} FTL: ${FTL_VERSION}" 2>&1 | tee -a "${DEBUG_LOG}" } +# Check the current version of the Web server check_web_server_version() { + # Store the name in a variable in case we ever want to change it WEB_SERVER="lighttpd" + # Parse out just the version number WEB_SERVER_VERSON="$(lighttpd -v |& head -n1 | cut -d '/' -f2 | cut -d ' ' -f1)" + # Display the information to the user echo -e " ${INFO} ${WEB_SERVER}" 2>&1 | tee -a "${DEBUG_LOG}" + # If the Web server does not have a version (the variable is empty) if [[ -z "${WEB_SERVER_VERSON}" ]]; then + # Display and error echo -e " ${CROSS} ${WEB_SERVER} version could not be detected." 2>&1 | tee -a "${DEBUG_LOG}" + # Otherwise, else + # display the version echo -e " ${TICK} ${WEB_SERVER_VERSON}" 2>&1 | tee -a "${DEBUG_LOG}" fi } +# Check the current version of the DNS server check_resolver_version() { + # Store the name in a variable in case we ever want to change it RESOLVER="dnsmasq" + # Parse out just the version number RESOVLER_VERSON="$(dnsmasq -v |& head -n1 | awk '{print $3}')" + # Display the information to the user echo -e " ${INFO} ${RESOLVER}" 2>&1 | tee -a "${DEBUG_LOG}" + # If the DNS server does not have a version (the variable is empty) if [[ -z "${RESOVLER_VERSON}" ]]; then + # Display and error echo -e " ${CROSS} ${RESOLVER} version could not be detected." 2>&1 | tee -a "${DEBUG_LOG}" + # Otherwise, else + # display the version echo -e " ${TICK} ${RESOVLER_VERSON}" 2>&1 | tee -a "${DEBUG_LOG}" fi } check_php_version() { + # Parse out just the version number PHP_VERSION=$(php -v |& head -n1 | cut -d '-' -f1 | cut -d ' ' -f2) + # Display the info to the user echo -e " ${INFO} PHP" 2>&1 | tee -a "${DEBUG_LOG}" + # If no version is detected, if [[ -z "${PHP_VERSION}" ]]; then + # show an error echo -e " ${CROSS} PHP version could not be detected." 2>&1 | tee -a "${DEBUG_LOG}" + # otherwise, else + # Show the version echo -e " ${TICK} ${PHP_VERSION}" 2>&1 | tee -a "${DEBUG_LOG}" fi } +# These are the most critical dependencies of Pi-hole, so we check for them +# and their versions, using the functions above. check_critical_dependencies() { echo_current_diagnostic "Versions of critical dependencies" check_web_server_version @@ -210,14 +264,16 @@ get_distro_attributes() { } diagnose_operating_system() { + # local variable for system requirements local faq_url="https://discourse.pi-hole.net/t/hardware-software-requirements/273" + # error message in a variable so we can easily modify it later (or re-use it) local error_msg="Distribution unknown -- most likely you are on an unsupported platform and may run into issues." # Display the current test that is running echo_current_diagnostic "Operating system" # If there is a /etc/*release file, it's probably a supported operating system, so we can file_exists /etc/*release && \ - # display the attributes to the user + # display the attributes to the user from the function made earlier get_distro_attributes || \ # If it doesn't exist, it's not a system we currently support and link to FAQ echo -e " ${CROSS} ${COL_LIGHT_RED}${error_msg}${COL_NC} @@ -226,10 +282,15 @@ diagnose_operating_system() { processor_check() { echo_current_diagnostic "Processor" + # Store the processor type in a variable PROCESSOR=$(uname -m) + # If it does not contain a value, if [[ -z "${PROCESSOR}" ]]; then + # we couldn't detect it, so show an error echo -e " ${CROSS} Processor could not be identified." 2>&1 | tee -a "${DEBUG_LOG}" + # Otherwise, else + # Show the processor type echo -e " ${INFO} ${PROCESSOR}" 2>&1 | tee -a "${DEBUG_LOG}" fi } @@ -246,12 +307,16 @@ detect_ip_addresses() { if [[ -n ${ip_addr_list} ]]; then # Local iterator local i + # Display the protocol and interface echo -e " ${TICK} IPv${protocol} on ${PIHOLE_INTERFACE}" 2>&1 | tee -a "${DEBUG_LOG}" + # Since there may be more than one IP address, store them in an array for i in "${!ip_addr_list[@]}"; do + # For each one in the list, print it out using the iterator as a numbered list echo -e " [$i] ${ip_addr_list[$i]}" 2>&1 | tee -a "${DEBUG_LOG}" done - # Othwerwise explain that the protocol is not configured + # Othwerwise, else + # explain that the protocol is not configured echo -e " ${CROSS} No IPv${protocol} found on ${PIHOLE_INTERFACE}" 2>&1 | tee -a "${DEBUG_LOG}" return 1 fi @@ -302,6 +367,7 @@ ping_gateway() { } ping_internet() { + # Give the first argument a readable name local protocol="${1}" # If the protocol is 6, if [[ ${protocol} == "6" ]]; then @@ -317,30 +383,42 @@ ping_internet() { local public_address="8.8.8.8" fi echo -n " ${INFO} Trying three pings on IPv${protocol} to reach the Internet..." 2>&1 | tee -a "${DEBUG_LOG}" + # Try to ping the address 3 times if ! ping_inet="$(${cmd} -q -W 3 -c 3 -n ${public_address} -I ${PIHOLE_INTERFACE} | tail -n 3)"; then + # if it's unsuccessful, show an error echo -e " ${CROSS} Cannot reach the Internet" 2>&1 | tee -a "${DEBUG_LOG}" return 1 + # Otherwise, else + # show success echo -e " ${TICK} Query responded." 2>&1 | tee -a "${DEBUG_LOG}" return 0 fi } check_required_ports() { + # Since Pi-hole needs 53, 80, and 4711, check what they are being used by + # so we can detect any issues echo -e " ${INFO} Ports in use:" 2>&1 | tee -a "${DEBUG_LOG}" + # Create an array for these ports in use ports_in_use=() + # Sort the addresses and remove duplicates while IFS= read -r line; do ports_in_use+=( "$line" ) done < <( lsof -i -P -n | awk -F' ' '/LISTEN/ {print $9, $1}' | sort | uniq | cut -d':' -f2 ) + # Now that we have the values stored, for i in ${!ports_in_use[@]}; do local port_number="$(echo "${ports_in_use[$i]}" | awk '{print $1}')" local service_name=$(echo "${ports_in_use[$i]}" | awk '{print $2}') + # display the information nicely to the user echo -e " [${port_number}] is in use by ${service_name}" 2>&1 | tee -a "${DEBUG_LOG}" done } check_networking() { + # Runs through several of the functions made earlier; we just clump them + # together since they are all related to the networking aspect of things echo_current_diagnostic "Networking" detect_ip_addresses "4" ping_gateway "4" @@ -350,17 +428,27 @@ check_networking() { } check_x_headers() { + # The X-Headers allow us to determine from the command line if the Web + # server is operating correctly echo_current_diagnostic "Dashboard and block page" + # Use curl -I to get the header and parse out just the X-Pi-hole one local block_page=$(curl -Is localhost | awk '/X-Pi-hole/' | tr -d '\r') + # Do it for the dashboard as well, as the header is different than above local dashboard=$(curl -Is localhost/admin/ | awk '/X-Pi-hole/' | tr -d '\r') + # Store what the X-Header shoud be in variables for comparision later local block_page_working="X-Pi-hole: A black hole for Internet advertisements." local dashboard_working="X-Pi-hole: The Pi-hole Web interface is working!" + # If the X-header found by curl matches what is should be, if [[ $block_page == $block_page_working ]]; then + # display a success message echo -e " $TICK ${block_page}" 2>&1 | tee -a "${DEBUG_LOG}" + # Otherwise, else + # show an error echo -e " $CROSS X-Header does not match or could not be retrieved" 2>&1 | tee -a "${DEBUG_LOG}" fi + # Same logic applies to the dashbord as above if [[ $dashboard == $dashboard_working ]]; then echo -e " $TICK ${dashboard}" 2>&1 | tee -a "${DEBUG_LOG}" else @@ -369,20 +457,29 @@ check_x_headers() { } dig_at() { + # We need to test if Pi-hole can properly resolve domain names as it is an + # essential piece of the software that needs to work + + # Store the arguments as variables with names local protocol="${1}" local IP="${2}" echo_current_diagnostic "Domain name resolution (IPv${protocol}) using a random blocked domain" + # Set more local variables local url local local_dig local pihole_dig local remote_dig + # If the protocol (4 or 6) is 6, if [[ ${protocol} == "6" ]]; then + # Set the IPv6 variables and record type local local_address="::1" local pihole_address="${IPV6_ADDRESS%/*}" local remote_address="2001:4860:4860::8888" local record_type="AAAA" + # Othwerwise, it should be 4 else + # so use the IPv4 values local local_address="127.0.0.1" local pihole_address="${IPV4_ADDRESS%/*}" local remote_address="8.8.8.8" @@ -392,33 +489,45 @@ dig_at() { # Find a random blocked url that has not been whitelisted. local random_url=$(shuf -n 1 "${GRAVITYFILE}" | awk -F ' ' '{ print $2 }') - local remote_url="doubleclick.com" - + # First do a dig on localhost, to see if Pi-hole can use itself to block a domain if local_dig=$(dig -"${protocol}" "${random_url}" @${local_address} +short "${record_type}"); then + # If it can, show sucess echo -e " ${TICK} ${random_url} is ${local_dig} via localhost (${local_address})" 2>&1 | tee -a "${DEBUG_LOG}" + # Otherwise, else + # show a failure echo -e " ${CROSS} Failed to resolve ${random_url} via localhot (${local_address})" 2>&1 | tee -a "${DEBUG_LOG}" fi + # Next we need to check if Pi-hole can resolve a domain when the query is sent to it's IP address + # This better emulates how clients will interact with Pi-hole as opposed to above where Pi-hole is + # just asing itself locally if pihole_dig=$(dig -"${protocol}" "${random_url}" @${pihole_address} +short "${record_type}"); then echo -e " ${TICK} ${random_url} is ${pihole_dig} via Pi-hole (${pihole_address})" 2>&1 | tee -a "${DEBUG_LOG}" else echo -e " ${CROSS} Failed to resolve ${random_url} via Pi-hole (${pihole_address})" 2>&1 | tee -a "${DEBUG_LOG}" fi + # Finally, we need to make sure legitimate sites can out if using an external, public DNS server if remote_dig=$(dig -"${protocol}" "${remote_url}" @${remote_address} +short "${record_type}" | head -n1); then + # If successful, the real IP of the domain will be returned instead of Pi-hole's IP echo -e " ${TICK} ${random_url} is ${remote_dig} via a remote, public DNS server (${remote_address})" 2>&1 | tee -a "${DEBUG_LOG}" else - echo -e " ${CROSS} Failed to resolve ${remote_url} via a remote, public DNS server (${remote_address})" 2>&1 | tee -a "${DEBUG_LOG}" + echo -e " ${CROSS} Failed to resolve ${random_url} via a remote, public DNS server (${remote_address})" 2>&1 | tee -a "${DEBUG_LOG}" fi } process_status(){ + # Check to make sure Pi-hole's services are running and active echo_current_diagnostic "Pi-hole processes" + # Store them in an array for easy use PROCESSES=( dnsmasq lighttpd pihole-FTL ) local i + # For each process, for i in "${PROCESSES[@]}"; do + # get it's status local status_of_process=$(systemctl is-active "${i}") + # and print it out to the user echo -e " [i] ${i} daemon is ${status_of_process}" 2>&1 | tee -a "${DEBUG_LOG}" done } @@ -461,6 +570,7 @@ diagnose_setup_variables() { check_name_resolution() { # Check name resoltion from localhost, Pi-hole's IP, and Google's name severs + # using the function we created earlier dig_at 4 "${IPV4_ADDRESS%/*}" # If IPv6 enabled, check resolution if [[ "${IPV6_ADDRESS}" ]]; then @@ -537,16 +647,24 @@ check_http_directory() { } analyze_gravity_list() { + # It's helpful to know how big a user's gravity file is gravity_length=$(grep -c ^ "${GRAVITYFILE}") && \ echo -e " ${INFO} ${GRAVITYFILE} is ${gravity_length} lines long." 2>&1 | tee -a "${DEBUG_LOG}" || \ + # If the previous command failed, something is wrong with the file echo -e " ${CROSS} ${GRAVITYFILE} not found!" 2>&1 | tee -a "${DEBUG_LOG}" } tricorder_nc_or_ssl() { + # Users can submit their debug logs using nc (unencrypted) or opensll (enrypted) if available + # Check fist for openssl since encryption is a good thing if command -v openssl &> /dev/null; then + # If successful echo -e " ${INFO} Using openssl for transmission." 2>&1 | tee -a "${DEBUG_LOG}" + # transmit the log and store the token returned in the tricorder variable tricorder=$(cat /var/log/pihole_debug.log | openssl s_client -quiet -connect tricorder.pi-hole.net:9998 2> /dev/null) + # Otherwise, else + # use net cat echo -e " ${INFO} Using netcat for transmission." 2>&1 | tee -a "${DEBUG_LOG}" tricorder=$(cat /var/log/pihole_debug.log | nc tricorder.pi-hole.net 9999) fi @@ -558,13 +676,18 @@ upload_to_tricorder() { chmod 644 ${DEBUG_LOG} chown "$USER":pihole ${DEBUG_LOG} + # Let the user know debugging is complete echo "" echo -e "${TICK} Finshed debugging!" 2>&1 | tee -a "${DEBUG_LOG}" + # Provide information on what they should do with their token echo -e " ${INFO} The debug log can be uploaded to tricorder.pi-hole.net for sharing with developers only." echo -e " For more information, see: https://pi-hole.net/2016/11/07/crack-our-medical-tricorder-win-a-raspberry-pi-3/" + # If pihole -d is running automatically (usually throught the dashboard) if [[ "${AUTOMATED}" ]]; then + # let the user know echo -e " ${INFO} Debug script running in automated mode" 2>&1 | tee -a "${DEBUG_LOG}" + # and then decide again which tool to use to submit it if command -v openssl &> /dev/null; then echo -e " ${INFO} Using openssl for transmission." 2>&1 | tee -a "${DEBUG_LOG}" openssl s_client -quiet -connect tricorder.pi-hole.net:9998 2> /dev/null < /dev/stdin @@ -574,13 +697,18 @@ upload_to_tricorder() { fi else echo "" + # Give the user a choice of uploading it or not + # Users can review the log file locally and try to self-diagnose their problem read -r -p "[?] Would you like to upload the log? [y/N] " response case ${response} in + # If they say yes, run our function for uploading the log [yY][eE][sS]|[yY]) tricorder_nc_or_ssl;; + # If they choose no, just exit out of the script *) echo -e " ${INFO} Log will NOT be uploaded to tricorder.";exit; esac fi - # Check if tricorder.pi-hole.net is reachable and provide token. + # Check if tricorder.pi-hole.net is reachable and provide token + # along with some additional useful information if [[ -n "${tricorder}" ]]; then echo "" echo -e "${COL_LIGHT_PURPLE}***********************************${COL_NC}" @@ -599,10 +727,13 @@ upload_to_tricorder() { echo "" } +# Run through all the functions we made initiate_debug check_core_version check_web_version check_ftl_version +# setupVars.conf needs to be sourced before the networking so the values are +# available to the check_networking function diagnose_setup_variables diagnose_operating_system processor_check