Advertisement
Guest User

Untitled

a guest
Mar 11th, 2017
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.96 KB | None | 0 0
  1. #!/usr/bin/env bash
  2. # Pi-hole: A black hole for Internet advertisements
  3. # (c) 2017 Pi-hole, LLC (https://pi-hole.net)
  4. # Network-wide ad blocking via your own hardware.
  5. #
  6. # Generates pihole_debug.log to be used for troubleshooting.
  7. #
  8. # This file is copyright under the latest version of the EUPL.
  9. # Please see LICENSE file for your rights under this license.
  10.  
  11.  
  12.  
  13. set -o pipefail
  14.  
  15. ######## GLOBAL VARS ########
  16. VARSFILE="/etc/pihole/setupVars.conf"
  17. DEBUG_LOG="/var/log/pihole_debug.log"
  18. DNSMASQFILE="/etc/dnsmasq.conf"
  19. DNSMASQCONFDIR="/etc/dnsmasq.d/*"
  20. LIGHTTPDFILE="/etc/lighttpd/lighttpd.conf"
  21. LIGHTTPDERRFILE="/var/log/lighttpd/error.log"
  22. GRAVITYFILE="/etc/pihole/gravity.list"
  23. WHITELISTFILE="/etc/pihole/whitelist.txt"
  24. BLACKLISTFILE="/etc/pihole/blacklist.txt"
  25. ADLISTFILE="/etc/pihole/adlists.list"
  26. PIHOLELOG="/var/log/pihole.log"
  27. WHITELISTMATCHES="/tmp/whitelistmatches.list"
  28.  
  29. TIMEOUT=60
  30. # Header info and introduction
  31. cat << EOM
  32. ::: Beginning Pi-hole debug at $(date)!
  33. :::
  34. ::: This process collects information from your Pi-hole, and optionally uploads
  35. ::: it to a unique and random directory on tricorder.pi-hole.net.
  36. :::
  37. ::: NOTE: All log files auto-delete after 48 hours and ONLY the Pi-hole developers
  38. ::: can access your data via the given token. We have taken these extra steps to
  39. ::: secure your data and will work to further reduce any personal information gathered.
  40. :::
  41. ::: Please read and note any issues, and follow any directions advised during this process.
  42. EOM
  43.  
  44. # Ensure the file exists, create if not, clear if exists.
  45. truncate --size=0 "${DEBUG_LOG}"
  46. chmod 644 ${DEBUG_LOG}
  47. chown "$USER":pihole ${DEBUG_LOG}
  48.  
  49. source ${VARSFILE}
  50.  
  51. ### Private functions exist here ###
  52. log_write() {
  53. echo "${1}" >> "${DEBUG_LOG}"
  54. }
  55.  
  56. log_echo() {
  57. case ${1} in
  58. -n)
  59. echo -n "::: ${2}"
  60. log_write "${2}"
  61. ;;
  62. -r)
  63. echo "::: ${2}"
  64. log_write "${2}"
  65. ;;
  66. -l)
  67. echo "${2}"
  68. log_write "${2}"
  69. ;;
  70. *)
  71. echo "::: ${1}"
  72. log_write "${1}"
  73. esac
  74. }
  75.  
  76. header_write() {
  77. log_echo ""
  78. log_echo "${1}"
  79. log_write ""
  80. }
  81.  
  82. file_parse() {
  83. while read -r line; do
  84. if [ ! -z "${line}" ]; then
  85. [[ "${line}" =~ ^#.*$ || ! "${line}" ]] && continue
  86. log_write "${line}"
  87. fi
  88. done < "${1}"
  89. log_write ""
  90. }
  91.  
  92. block_parse() {
  93. log_write "${1}"
  94. }
  95.  
  96. lsof_parse() {
  97. local user
  98. local process
  99.  
  100. user=$(echo ${1} | cut -f 3 -d ' ' | cut -c 2-)
  101. process=$(echo ${1} | cut -f 2 -d ' ' | cut -c 2-)
  102. [[ ${2} -eq ${process} ]] \
  103. && echo "::: Correctly configured." \
  104. || log_echo "::: Failure: Incorrectly configured daemon."
  105.  
  106. log_write "Found user ${user} with process ${process}"
  107. }
  108.  
  109.  
  110. version_check() {
  111. header_write "Detecting Installed Package Versions:"
  112.  
  113. local error_found
  114. error_found=0
  115.  
  116. local pi_hole_ver="$(cd /etc/.pihole/ && git describe --tags --abbrev=0)" \
  117. && log_echo -r "Pi-hole: $pi_hole_ver" || (log_echo "Pi-hole git repository not detected." && error_found=1)
  118. local admin_ver="$(cd /var/www/html/admin && git describe --tags --abbrev=0)" \
  119. && log_echo -r "WebUI: $admin_ver" || (log_echo "Pi-hole Admin Pages git repository not detected." && error_found=1)
  120. local light_ver="$(lighttpd -v |& head -n1 | cut -d " " -f1)" \
  121. && log_echo -r "${light_ver}" || (log_echo "lighttpd not installed." && error_found=1)
  122. local php_ver="$(php -v |& head -n1)" \
  123. && log_echo -r "${php_ver}" || (log_echo "PHP not installed." && error_found=1)
  124.  
  125. (local pi_hole_branch="$(cd /etc/.pihole/ && git rev-parse --abbrev-ref HEAD)" && log_echo -r "Pi-hole branch: ${pi_hole_branch}") || log_echo "Unable to obtain Pi-hole branch"
  126. (local pi_hole_rev="$(cd /etc/.pihole/ && git describe --long --dirty --tags)" && log_echo -r "Pi-hole rev: ${pi_hole_rev}") || log_echo "Unable to obtain Pi-hole revision"
  127.  
  128. (local admin_branch="$(cd /var/www/html/admin && git rev-parse --abbrev-ref HEAD)" && log_echo -r "AdminLTE branch: ${admin_branch}") || log_echo "Unable to obtain AdminLTE branch"
  129. (local admin_rev="$(cd /var/www/html/admin && git describe --long --dirty --tags)" && log_echo -r "AdminLTE rev: ${admin_rev}") || log_echo "Unable to obtain AdminLTE revision"
  130.  
  131. return "${error_found}"
  132. }
  133.  
  134. dir_check() {
  135. header_write "Detecting contents of ${1}:"
  136. for file in $1*; do
  137. header_write "File ${file} found"
  138. echo -n "::: Parsing..."
  139. file_parse "${file}"
  140. echo "done"
  141. done
  142. echo ":::"
  143. }
  144.  
  145. files_check() {
  146. #Check non-zero length existence of ${1}
  147. header_write "Detecting existence of ${1}:"
  148. local search_file="${1}"
  149. if [[ -s ${search_file} ]]; then
  150. echo -n "::: File exists, parsing..."
  151. file_parse "${search_file}"
  152. echo "done"
  153. return 0
  154. else
  155. log_echo "${1} not found!"
  156. return 1
  157. fi
  158. echo ":::"
  159. }
  160.  
  161. source_file() {
  162. local file_found=$(files_check "${1}") \
  163. && (source "${1}" &> /dev/null && echo "${file_found} and was successfully sourced") \
  164. || log_echo -l "${file_found} and could not be sourced"
  165. }
  166.  
  167. distro_check() {
  168. local soft_fail
  169. header_write "Detecting installed OS Distribution"
  170. soft_fail=0
  171. local distro="$(cat /etc/*release)" && block_parse "${distro}" || (log_echo "Distribution details not found." && soft_fail=1)
  172. return "${soft_fail}"
  173. }
  174.  
  175. processor_check() {
  176. header_write "Checking processor variety"
  177. log_write $(uname -m) && return 0 || return 1
  178. }
  179.  
  180. ipv6_check() {
  181. # Check if system is IPv6 enabled, for use in other functions
  182. if [[ $IPV6_ADDRESS ]]; then
  183. ls /proc/net/if_inet6 &>/dev/null
  184. return 0
  185. else
  186. return 1
  187. fi
  188. }
  189.  
  190. ip_check() {
  191. local protocol=${1}
  192. local gravity=${2}
  193.  
  194. local ip_addr_list="$(ip -${protocol} addr show dev ${PIHOLE_INTERFACE} | awk -F ' ' '{ for(i=1;i<=NF;i++) if ($i ~ '/^inet/') print $(i+1) }')"
  195. if [[ -n ${ip_addr_list} ]]; then
  196. log_write "IPv${protocol} on ${PIHOLE_INTERFACE}"
  197. log_write "Gravity configured for: ${2:-NOT CONFIGURED}"
  198. log_write "----"
  199. log_write "${ip_addr_list}"
  200. echo "::: IPv${protocol} addresses located on ${PIHOLE_INTERFACE}"
  201. ip_ping_check ${protocol}
  202. return $(( 0 + $? ))
  203. else
  204. log_echo "No IPv${protocol} found on ${PIHOLE_INTERFACE}"
  205. return 1
  206. fi
  207. }
  208.  
  209. ip_ping_check() {
  210. local protocol=${1}
  211. local cmd
  212.  
  213. if [[ ${protocol} == "6" ]]; then
  214. cmd="ping6"
  215. g_addr="2001:4860:4860::8888"
  216. else
  217. cmd="ping"
  218. g_addr="8.8.8.8"
  219. fi
  220.  
  221. local ip_def_gateway=$(ip -${protocol} route | grep default | cut -d ' ' -f 3)
  222. if [[ -n ${ip_def_gateway} ]]; then
  223. echo -n "::: Pinging default IPv${protocol} gateway: "
  224. if ! ping_gateway="$(${cmd} -q -W 3 -c 3 -n ${ip_def_gateway} -I ${PIHOLE_INTERFACE} | tail -n 3)"; then
  225. echo "Gateway did not respond."
  226. return 1
  227. else
  228. echo "Gateway responded."
  229. log_write "${ping_gateway}"
  230. fi
  231. echo -n "::: Pinging Internet via IPv${protocol}: "
  232. if ! ping_inet="$(${cmd} -q -W 3 -c 3 -n ${g_addr} -I ${PIHOLE_INTERFACE} | tail -n 3)"; then
  233. echo "Query did not respond."
  234. return 1
  235. else
  236. echo "Query responded."
  237. log_write "${ping_inet}"
  238. fi
  239. else
  240. log_echo " No gateway detected."
  241. fi
  242. return 0
  243. }
  244.  
  245. port_check() {
  246. local lsof_value
  247.  
  248. lsof_value=$(lsof -i ${1}:${2} -FcL | tr '\n' ' ') \
  249. && lsof_parse "${lsof_value}" "${3}" \
  250. || log_echo "Failure: IPv${1} Port not in use"
  251. }
  252.  
  253. daemon_check() {
  254. # Check for daemon ${1} on port ${2}
  255. header_write "Daemon Process Information"
  256.  
  257. echo "::: Checking ${2} port for ${1} listener."
  258.  
  259. if [[ ${IPV6_READY} ]]; then
  260. port_check 6 "${2}" "${1}"
  261. fi
  262. lsof_value=$(lsof -i 4:${2} -FcL | tr '\n' ' ') \
  263. port_check 4 "${2}" "${1}"
  264. }
  265.  
  266. testResolver() {
  267. header_write "Resolver Functions Check"
  268.  
  269. # Find a blocked url that has not been whitelisted.
  270. TESTURL="doubleclick.com"
  271. if [ -s "${WHITELISTMATCHES}" ]; then
  272. while read -r line; do
  273. CUTURL=${line#*" "}
  274. if [ "${CUTURL}" != "Pi-Hole.IsWorking.OK" ]; then
  275. while read -r line2; do
  276. CUTURL2=${line2#*" "}
  277. if [ "${CUTURL}" != "${CUTURL2}" ]; then
  278. TESTURL="${CUTURL}"
  279. break 2
  280. fi
  281. done < "${WHITELISTMATCHES}"
  282. fi
  283. done < "${GRAVITYFILE}"
  284. fi
  285.  
  286. log_write "Resolution of ${TESTURL} from Pi-hole:"
  287. LOCALDIG=$(dig "${TESTURL}" @127.0.0.1)
  288. if [[ $? = 0 ]]; then
  289. log_write "${LOCALDIG}"
  290. else
  291. log_write "Failed to resolve ${TESTURL} on Pi-hole"
  292. fi
  293. log_write ""
  294.  
  295.  
  296. log_write "Resolution of ${TESTURL} from 8.8.8.8:"
  297. REMOTEDIG=$(dig "${TESTURL}" @8.8.8.8)
  298. if [[ $? = 0 ]]; then
  299. log_write "${REMOTEDIG}"
  300. else
  301. log_write "Failed to resolve ${TESTURL} on 8.8.8.8"
  302. fi
  303. log_write ""
  304.  
  305. log_write "Pi-hole dnsmasq specific records lookups"
  306. log_write "Cache Size:"
  307. dig +short chaos txt cachesize.bind >> ${DEBUG_LOG}
  308. log_write "Upstream Servers:"
  309. dig +short chaos txt servers.bind >> ${DEBUG_LOG}
  310. log_write ""
  311. }
  312.  
  313. checkProcesses() {
  314. header_write "Processes Check"
  315.  
  316. echo "::: Logging status of lighttpd and dnsmasq..."
  317. PROCESSES=( lighttpd dnsmasq )
  318. for i in "${PROCESSES[@]}"; do
  319. log_write ""
  320. log_write "${i}"
  321. log_write " processes status:"
  322. systemctl -l status "${i}" >> "${DEBUG_LOG}"
  323. done
  324. log_write ""
  325. }
  326.  
  327. debugLighttpd() {
  328. echo "::: Checking for necessary lighttpd files."
  329. files_check "${LIGHTTPDFILE}"
  330. files_check "${LIGHTTPDERRFILE}"
  331. echo ":::"
  332. }
  333.  
  334. countdown() {
  335. local tuvix
  336. tuvix=${TIMEOUT}
  337. printf "::: Logging will automatically teminate in %s seconds\n" "${TIMEOUT}"
  338. while [ $tuvix -ge 1 ]
  339. do
  340. printf ":::\t%s seconds left. " "${tuvix}"
  341. if [[ -z "${WEBCALL}" ]]; then
  342. printf "\r"
  343. else
  344. printf "\n"
  345. fi
  346. sleep 5
  347. tuvix=$(( tuvix - 5 ))
  348. done
  349. }
  350. ### END FUNCTIONS ###
  351.  
  352. # Gather version of required packages / repositories
  353. version_check || echo "REQUIRED FILES MISSING"
  354. # Check for newer setupVars storage file
  355. source_file "/etc/pihole/setupVars.conf"
  356. # Gather information about the running distribution
  357. distro_check || echo "Distro Check soft fail"
  358. # Gather processor type
  359. processor_check || echo "Processor Check soft fail"
  360.  
  361. ip_check 6 ${IPV6_ADDRESS}
  362. ip_check 4 ${IPV4_ADDRESS}
  363.  
  364. daemon_check lighttpd http
  365. daemon_check dnsmasq domain
  366. checkProcesses
  367. testResolver
  368. debugLighttpd
  369.  
  370. files_check "${DNSMASQFILE}"
  371. dir_check "${DNSMASQCONFDIR}"
  372. files_check "${WHITELISTFILE}"
  373. files_check "${BLACKLISTFILE}"
  374. files_check "${ADLISTFILE}"
  375.  
  376.  
  377. header_write "Analyzing gravity.list"
  378.  
  379. gravity_length=$(grep -c ^ "${GRAVITYFILE}") \
  380. && log_write "${GRAVITYFILE} is ${gravity_length} lines long." \
  381. || log_echo "Warning: No gravity.list file found!"
  382.  
  383. header_write "Analyzing pihole.log"
  384.  
  385. pihole_length=$(grep -c ^ "${PIHOLELOG}") \
  386. && log_write "${PIHOLELOG} is ${pihole_length} lines long." \
  387. || log_echo "Warning: No pihole.log file found!"
  388.  
  389. pihole_size=$(du -h "${PIHOLELOG}" | awk '{ print $1 }') \
  390. && log_write "${PIHOLELOG} is ${pihole_size}." \
  391. || log_echo "Warning: No pihole.log file found!"
  392.  
  393.  
  394. # Continuously append the pihole.log file to the pihole_debug.log file
  395. dumpPiHoleLog() {
  396. trap '{ echo -e "\n::: Finishing debug write from interrupt... Quitting!" ; exit 1; }' INT
  397. echo "::: "
  398. echo "::: --= User Action Required =--"
  399. echo -e "::: Try loading a site that you are having trouble with now from a client web browser.. \n:::\t(Press CTRL+C to finish logging.)"
  400. header_write "pihole.log"
  401. if [ -e "${PIHOLELOG}" ]; then
  402. # Dummy process to use for flagging down tail to terminate
  403. countdown &
  404. tail -n0 -f --pid=$! "${PIHOLELOG}" >> ${DEBUG_LOG}
  405. else
  406. log_write "No pihole.log file found!"
  407. printf ":::\tNo pihole.log file found!\n"
  408. fi
  409. }
  410.  
  411. # Anything to be done after capturing of pihole.log terminates
  412. finalWork() {
  413. local tricorder
  414. echo "::: Finshed debugging!"
  415. echo "::: The debug log can be uploaded to tricorder.pi-hole.net for sharing with developers only."
  416. if [[ "${AUTOMATED}" ]]; then
  417. echo "::: Debug script running in automated mode, uploading log to tricorder..."
  418. tricorder=$(cat /var/log/pihole_debug.log | nc tricorder.pi-hole.net 9999)
  419. else
  420. read -r -p "::: Would you like to upload the log? [y/N] " response
  421. case ${response} in
  422. [yY][eE][sS]|[yY])
  423. tricorder=$(cat /var/log/pihole_debug.log | nc tricorder.pi-hole.net 9999)
  424. ;;
  425. *)
  426. echo "::: Log will NOT be uploaded to tricorder."
  427. ;;
  428. esac
  429. fi
  430. # Check if tricorder.pi-hole.net is reachable and provide token.
  431. if [ -n "${tricorder}" ]; then
  432. echo "::: ---=== Your debug token is : ${tricorder} Please make a note of it. ===---"
  433. echo "::: Contact the Pi-hole team with your token for assistance."
  434. echo "::: Thank you."
  435. else
  436. echo "::: There was an error uploading your debug log."
  437. echo "::: Please try again or contact the Pi-hole team for assistance."
  438. fi
  439. echo "::: A local copy of the Debug log can be found at : /var/log/pihole_debug.log"
  440. }
  441.  
  442. trap finalWork EXIT
  443.  
  444. ### Method calls for additional logging ###
  445. dumpPiHoleLog
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement