You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1658 lines
51 KiB

  1. #!/bin/sh
  2. # dns based ad/abuse domain blocking
  3. # Copyright (c) 2015-2020 Dirk Brenken (dev@brenken.org)
  4. # This is free software, licensed under the GNU General Public License v3.
  5. # set (s)hellcheck exceptions
  6. # shellcheck disable=1091,2016,2039,2059,2086,2143,2181,2188
  7. # set initial defaults
  8. #
  9. export LC_ALL=C
  10. export PATH="/usr/sbin:/usr/bin:/sbin:/bin"
  11. set -o pipefail
  12. adb_ver="4.0.6"
  13. adb_enabled=0
  14. adb_debug=0
  15. adb_forcedns=0
  16. adb_maxqueue=4
  17. adb_dnsfilereset=0
  18. adb_dnsflush=0
  19. adb_dnstimeout=20
  20. adb_safesearch=0
  21. adb_safesearchlist=""
  22. adb_safesearchmod=0
  23. adb_report=0
  24. adb_trigger=""
  25. adb_triggerdelay=0
  26. adb_backup=1
  27. adb_mail=0
  28. adb_mailcnt=0
  29. adb_jail=0
  30. adb_dns=""
  31. adb_dnsprefix="adb_list"
  32. adb_locallist="blacklist whitelist"
  33. adb_tmpbase="/tmp"
  34. adb_backupdir="/tmp"
  35. adb_reportdir="/tmp"
  36. adb_jaildir="/tmp"
  37. adb_pidfile="/var/run/adblock.pid"
  38. adb_blacklist="/etc/adblock/adblock.blacklist"
  39. adb_whitelist="/etc/adblock/adblock.whitelist"
  40. adb_ubusservice="/etc/adblock/adblock.monitor"
  41. adb_mailservice="/etc/adblock/adblock.mail"
  42. adb_dnsfile="${adb_dnsprefix}.overall"
  43. adb_dnsjail="${adb_dnsprefix}.jail"
  44. adb_srcarc="/etc/adblock/adblock.sources.gz"
  45. adb_srcfile="${adb_tmpbase}/adb_sources.json"
  46. adb_rtfile="${adb_tmpbase}/adb_runtime.json"
  47. adb_loggercmd="$(command -v logger)"
  48. adb_dumpcmd="$(command -v tcpdump)"
  49. adb_lookupcmd="$(command -v nslookup)"
  50. adb_fetchutil=""
  51. adb_portlist="53 853 5353"
  52. adb_repiface=""
  53. adb_replisten="53"
  54. adb_repchunkcnt="5"
  55. adb_repchunksize="1"
  56. adb_lookupdomain="example.com"
  57. adb_action="${1:-"start"}"
  58. adb_packages=""
  59. adb_sources=""
  60. adb_cnt=""
  61. # load & check adblock environment
  62. #
  63. f_load()
  64. {
  65. adb_sysver="$(ubus -S call system board 2>/dev/null | jsonfilter -e '@.model' -e '@.release.description' | \
  66. "${adb_awk}" 'BEGIN{ORS=", "}{print $0}' | "${adb_awk}" '{print substr($0,1,length($0)-2)}')"
  67. f_conf
  68. if [ "${adb_action}" != "report" ]
  69. then
  70. f_dns
  71. f_fetch
  72. fi
  73. if [ "${adb_enabled}" -eq 0 ]
  74. then
  75. f_extconf
  76. f_temp
  77. f_rmdns
  78. f_bgserv "stop"
  79. f_jsnup "disabled"
  80. f_log "info" "adblock is currently disabled, please set the config option 'adb_enabled' to '1' to use this service"
  81. exit 0
  82. fi
  83. }
  84. # check & set environment
  85. #
  86. f_env()
  87. {
  88. adb_starttime="$(date "+%s")"
  89. f_log "info" "adblock instance started ::: action: ${adb_action}, priority: ${adb_nice:-"0"}, pid: ${$}"
  90. f_jsnup "running"
  91. f_extconf
  92. f_temp
  93. if [ "${adb_dnsflush}" -eq 1 ]
  94. then
  95. printf "${adb_dnsheader}" > "${adb_dnsdir}/${adb_dnsfile}"
  96. f_dnsup
  97. fi
  98. if [ ! -r "${adb_srcfile}" ]
  99. then
  100. if [ -r "${adb_srcarc}" ]
  101. then
  102. zcat "${adb_srcarc}" > "${adb_srcfile}"
  103. else
  104. f_log "err" "adblock source archive not found"
  105. fi
  106. fi
  107. if [ -r "${adb_srcfile}" ]
  108. then
  109. json_load_file "${adb_srcfile}"
  110. else
  111. f_log "err" "adblock source file not found"
  112. fi
  113. }
  114. # load adblock config
  115. #
  116. f_conf()
  117. {
  118. local cnt=0 cnt_max=10
  119. if [ ! -r "/etc/config/adblock" ] || [ -n "$(uci -q show adblock.@source[0])" ]
  120. then
  121. if { [ -r "/etc/config/adblock-opkg" ] && [ -z "$(uci -q show adblock-opkg.@source[0])" ]; } || \
  122. { [ -r "/rom/etc/config/adblock" ] && [ -z "$(uci -q show /rom/etc/config/adblock.@source[0])" ]; }
  123. then
  124. if [ -r "/etc/config/adblock" ]
  125. then
  126. cp -pf "/etc/config/adblock" "/etc/config/adblock-backup"
  127. fi
  128. if [ -r "/etc/config/adblock-opkg" ]
  129. then
  130. cp -pf "/etc/config/adblock-opkg" "/etc/config/adblock"
  131. elif [ -r "/rom/etc/config/adblock" ]
  132. then
  133. cp -pf "/rom/etc/config/adblock" "/etc/config/adblock"
  134. fi
  135. f_log "info" "missing or old adblock config replaced with new valid default config"
  136. else
  137. f_log "err" "unrecoverable adblock config error, please re-install the package via opkg with the '--force-reinstall --force-maintainer' options"
  138. fi
  139. fi
  140. config_cb()
  141. {
  142. option_cb()
  143. {
  144. local option="${1}"
  145. local value="${2}"
  146. eval "${option}=\"${value}\""
  147. }
  148. list_cb()
  149. {
  150. local option="${1}"
  151. local value="${2}"
  152. if [ "${option}" = "adb_sources" ]
  153. then
  154. eval "${option}=\"$(printf "%s" "${adb_sources}") ${value}\""
  155. elif [ "${option}" = "adb_safesearchlist" ]
  156. then
  157. eval "${option}=\"$(printf "%s" "${adb_safesearchlist}") ${value}\""
  158. fi
  159. }
  160. }
  161. config_load adblock
  162. if [ -z "${adb_fetchutil}" ] || [ -z "${adb_dns}" ]
  163. then
  164. while [ -z "${adb_packages}" ] && [ "${cnt}" -le "${cnt_max}" ]
  165. do
  166. adb_packages="$(opkg list-installed 2>/dev/null)"
  167. cnt=$((cnt+1))
  168. sleep 1
  169. done
  170. if [ -z "${adb_packages}" ]
  171. then
  172. f_log "err" "local opkg package repository is not available, please set 'adb_fetchutil' and 'adb_dns' manually"
  173. fi
  174. fi
  175. }
  176. # load dns backend config
  177. #
  178. f_dns()
  179. {
  180. local util utils dns_up cnt=0
  181. if [ -z "${adb_dns}" ]
  182. then
  183. utils="knot-resolver named unbound dnsmasq raw"
  184. for util in ${utils}
  185. do
  186. if [ "${util}" = "raw" ] || [ -n "$(printf "%s" "${adb_packages}" | grep "^${util}")" ]
  187. then
  188. if [ "${util}" = "knot-resolver" ]
  189. then
  190. util="kresd"
  191. fi
  192. if [ "${util}" = "raw" ] || [ -x "$(command -v "${util}")" ]
  193. then
  194. adb_dns="${util}"
  195. uci_set adblock global adb_dns "${util}"
  196. f_uci "adblock"
  197. break
  198. fi
  199. fi
  200. done
  201. elif [ "${adb_dns}" != "raw" ] && [ ! -x "$(command -v "${adb_dns}")" ]
  202. then
  203. unset adb_dns
  204. fi
  205. if [ -n "${adb_dns}" ]
  206. then
  207. case "${adb_dns}" in
  208. "dnsmasq")
  209. adb_dnsinotify="${adb_dnsinotify:-"0"}"
  210. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  211. adb_dnsuser="${adb_dnsuser:-"dnsmasq"}"
  212. adb_dnsdir="${adb_dnsdir:-"/tmp/dnsmasq.d"}"
  213. adb_dnsheader="${adb_dnsheader}"
  214. adb_dnsdeny="${adb_dnsdeny:-"${adb_awk} '{print \"address=/\"\$0\"/\"}'"}"
  215. adb_dnsallow="${adb_dnsallow:-"${adb_awk} '{print \"local=/\"\$0\"/#\"}'"}"
  216. adb_dnssafesearch="${adb_dnssafesearch:-"${adb_awk} -v item=\"\$item\" '{print \"address=/\"\$0\"/\"item\"\"}'"}"
  217. adb_dnsstop="${adb_dnsstop:-"address=/#/"}"
  218. ;;
  219. "unbound")
  220. adb_dnsinotify="${adb_dnsinotify:-"0"}"
  221. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  222. adb_dnsuser="${adb_dnsuser:-"unbound"}"
  223. adb_dnsdir="${adb_dnsdir:-"/var/lib/unbound"}"
  224. adb_dnsheader="${adb_dnsheader}"
  225. adb_dnsdeny="${adb_dnsdeny:-"${adb_awk} '{print \"local-zone: \\042\"\$0\"\\042 static\"}'"}"
  226. adb_dnsallow="${adb_dnsallow:-"${adb_awk} '{print \"local-zone: \\042\"\$0\"\\042 transparent\"}'"}"
  227. adb_dnssafesearch="${adb_dnssafesearch:-"${adb_awk} -v item=\"\$item\" '{type=\"AAAA\";if(match(item,/^([0-9]{1,3}\.){3}[0-9]{1,3}$/)){type=\"A\"}}{print \"local-data: \\042\"\$0\" \"type\" \"item\"\\042\"}'"}"
  228. adb_dnsstop="${adb_dnsstop:-"local-zone: \".\" static"}"
  229. ;;
  230. "named")
  231. adb_dnsinotify="${adb_dnsinotify:-"0"}"
  232. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  233. adb_dnsuser="${adb_dnsuser:-"bind"}"
  234. adb_dnsdir="${adb_dnsdir:-"/var/lib/bind"}"
  235. adb_dnsheader="${adb_dnsheader:-"\$TTL 2h\n@ IN SOA localhost. root.localhost. (1 6h 1h 1w 2h)\n IN NS localhost.\n"}"
  236. adb_dnsdeny="${adb_dnsdeny:-"${adb_awk} '{print \"\"\$0\" CNAME .\\n*.\"\$0\" CNAME .\"}'"}"
  237. adb_dnsallow="${adb_dnsallow:-"${adb_awk} '{print \"\"\$0\" CNAME rpz-passthru.\\n*.\"\$0\" CNAME rpz-passthru.\"}'"}"
  238. adb_dnssafesearch="${adb_dnssafesearch:-"${adb_awk} -v item=\"\$item\" '{print \"\"\$0\" CNAME \"item\".\\n*.\"\$0\" CNAME \"item\".\"}'"}"
  239. adb_dnsstop="${adb_dnsstop:-"* CNAME ."}"
  240. ;;
  241. "kresd")
  242. adb_dnsinotify="${adb_dnsinotify:-"0"}"
  243. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  244. adb_dnsuser="${adb_dnsuser:-"root"}"
  245. adb_dnsdir="${adb_dnsdir:-"/etc/kresd"}"
  246. adb_dnsheader="${adb_dnsheader:-"\$TTL 2h\n@ IN SOA localhost. root.localhost. (1 6h 1h 1w 2h)\n"}"
  247. adb_dnsdeny="${adb_dnsdeny:-"${adb_awk} '{print \"\"\$0\" CNAME .\\n*.\"\$0\" CNAME .\"}'"}"
  248. adb_dnsallow="${adb_dnsallow:-"${adb_awk} '{print \"\"\$0\" CNAME rpz-passthru.\\n*.\"\$0\" CNAME rpz-passthru.\"}'"}"
  249. adb_dnssafesearch="${adb_dnssafesearch:-"${adb_awk} -v item=\"\$item\" '{type=\"AAAA\";if(match(item,/^([0-9]{1,3}\.){3}[0-9]{1,3}$/)){type=\"A\"}}{print \"\"\$0\" \"type\" \"item\"\"}'"}"
  250. adb_dnsstop="${adb_dnsstop:-"* CNAME ."}"
  251. ;;
  252. "raw")
  253. adb_dnsinotify="${adb_dnsinotify:-"0"}"
  254. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  255. adb_dnsuser="${adb_dnsuser:-"root"}"
  256. adb_dnsdir="${adb_dnsdir:-"/tmp"}"
  257. adb_dnsheader="${adb_dnsheader}"
  258. adb_dnsdeny="${adb_dnsdeny:-"0"}"
  259. adb_dnsallow="${adb_dnsallow:-"1"}"
  260. adb_dnssafesearch="${adb_dnssafesearch:-"0"}"
  261. adb_dnsstop="${adb_dnsstop:-"0"}"
  262. ;;
  263. esac
  264. fi
  265. if [ "${adb_dns}" != "raw" ] && { [ -z "${adb_dns}" ] || [ ! -x "$(command -v "${adb_dns}")" ]; }
  266. then
  267. f_log "err" "dns backend not found, please set 'adb_dns' manually"
  268. fi
  269. if [ "${adb_dns}" != "raw" ] && { [ "${adb_dnsdir}" = "${adb_tmpbase}" ] || [ "${adb_dnsdir}" = "${adb_backupdir}" ] || \
  270. [ "${adb_dnsdir}" = "${adb_reportdir}" ] || [ "${adb_dnsdir}" = "${adb_jaildir}" ]; }
  271. then
  272. f_log "err" "dns directory '${adb_dnsdir}' has been misconfigured, it must not point to the 'adb_tmpbase', 'adb_backupdir', 'adb_reportdir' or 'adb_jaildir'"
  273. fi
  274. if [ "${adb_action}" = "start" ] && [ -z "${adb_trigger}" ]
  275. then
  276. sleep ${adb_triggerdelay}
  277. fi
  278. if [ "${adb_dns}" != "raw" ] && [ "${adb_action}" != "stop" ]
  279. then
  280. while [ "${cnt}" -le 30 ]
  281. do
  282. dns_up="$(ubus -S call service list "{\"name\":\"${adb_dns}\"}" 2>/dev/null | jsonfilter -l1 -e "@[\"${adb_dns}\"].instances.*.running" 2>/dev/null)"
  283. if [ "${dns_up}" = "true" ]
  284. then
  285. break
  286. fi
  287. sleep 1
  288. cnt=$((cnt+1))
  289. done
  290. if [ -n "${adb_dnsdir}" ] && [ ! -d "${adb_dnsdir}" ]
  291. then
  292. mkdir -p "${adb_dnsdir}"
  293. if [ "${?}" -eq 0 ]
  294. then
  295. f_log "info" "dns backend directory '${adb_dnsdir}' created"
  296. else
  297. f_log "err" "dns backend directory '${adb_dnsdir}' could not be created"
  298. fi
  299. fi
  300. if [ ! -f "${adb_dnsdir}/${adb_dnsfile}" ]
  301. then
  302. printf "${adb_dnsheader}" > "${adb_dnsdir}/${adb_dnsfile}"
  303. fi
  304. if [ "${dns_up}" != "true" ]
  305. then
  306. f_dnsup 4
  307. if [ "${?}" -ne 0 ]
  308. then
  309. f_log "err" "dns backend '${adb_dns}' not running or executable"
  310. fi
  311. fi
  312. if [ "${adb_backup}" -eq 1 ] && [ -n "${adb_backupdir}" ] && [ ! -d "${adb_backupdir}" ]
  313. then
  314. mkdir -p "${adb_backupdir}"
  315. if [ "${?}" -eq 0 ]
  316. then
  317. f_log "info" "backup directory '${adb_backupdir}' created"
  318. else
  319. f_log "err" "backup backend directory '${adb_backupdir}' could not be created"
  320. fi
  321. fi
  322. if [ -n "${adb_jaildir}" ] && [ ! -d "${adb_jaildir}" ]
  323. then
  324. mkdir -p "${adb_jaildir}"
  325. if [ "${?}" -eq 0 ]
  326. then
  327. f_log "info" "jail directory '${adb_jaildir}' created"
  328. else
  329. f_log "err" "jail directory '${adb_jaildir}' could not be created"
  330. fi
  331. fi
  332. fi
  333. f_log "debug" "f_dns ::: dns: ${adb_dns}, dns_dir: ${adb_dnsdir}, dns_file: ${adb_dnsfile}, dns_user: ${adb_dnsuser}, dns_inotify: ${adb_dnsinotify}, dns_instance: ${adb_dnsinstance}, backup: ${adb_backup}, backup_dir: ${adb_backupdir}, jail_dir: ${adb_jaildir}"
  334. }
  335. # load fetch utility
  336. #
  337. f_fetch()
  338. {
  339. local util utils cnt=0
  340. if [ -z "${adb_fetchutil}" ]
  341. then
  342. utils="aria2c curl wget uclient-fetch"
  343. for util in ${utils}
  344. do
  345. if { [ "${util}" = "uclient-fetch" ] && [ -n "$(printf "%s" "${adb_packages}" | grep "^libustream-")" ]; } || \
  346. { [ "${util}" = "wget" ] && [ -n "$(printf "%s" "${adb_packages}" | grep "^wget -")" ]; } || \
  347. [ "${util}" = "curl" ] || [ "${util}" = "aria2c" ]
  348. then
  349. if [ -x "$(command -v "${util}")" ]
  350. then
  351. adb_fetchutil="${util}"
  352. uci_set adblock global adb_fetchutil "${util}"
  353. f_uci "adblock"
  354. break
  355. fi
  356. fi
  357. done
  358. elif [ ! -x "$(command -v "${adb_fetchutil}")" ]
  359. then
  360. unset adb_fetchutil
  361. fi
  362. case "${adb_fetchutil}" in
  363. "aria2c")
  364. adb_fetchparm="${adb_fetchparm:-"--timeout=20 --allow-overwrite=true --auto-file-renaming=false --check-certificate=true --dir= -o"}"
  365. ;;
  366. "curl")
  367. adb_fetchparm="${adb_fetchparm:-"--connect-timeout 20 --silent --show-error --location -o"}"
  368. ;;
  369. "uclient-fetch")
  370. adb_fetchparm="${adb_fetchparm:-"--timeout=20 -O"}"
  371. ;;
  372. "wget")
  373. adb_fetchparm="${adb_fetchparm:-"--no-cache --no-cookies --max-redirect=0 --timeout=20 -O"}"
  374. ;;
  375. esac
  376. if [ -n "${adb_fetchutil}" ] && [ -n "${adb_fetchparm}" ]
  377. then
  378. adb_fetchutil="$(command -v "${adb_fetchutil}")"
  379. else
  380. f_log "err" "download utility with SSL support not found, please install 'uclient-fetch' with a 'libustream-*' variant or another download utility like 'wget', 'curl' or 'aria2'"
  381. fi
  382. f_log "debug" "f_fetch ::: fetch_util: ${adb_fetchutil:-"-"}, fetch_parm: ${adb_fetchparm:-"-"}"
  383. }
  384. # create temporary files, directories and set dependent options
  385. #
  386. f_temp()
  387. {
  388. local cpu core cores
  389. cpu="$(grep -c '^processor' /proc/cpuinfo 2>/dev/null)"
  390. core="$(grep -cm1 '^core id' /proc/cpuinfo 2>/dev/null)"
  391. if [ "${cpu}" -eq 0 ]
  392. then
  393. cpu=1
  394. fi
  395. if [ "${core}" -eq 0 ]
  396. then
  397. core=1
  398. fi
  399. cores=$((cpu*core))
  400. if [ -d "${adb_tmpbase}" ]
  401. then
  402. adb_tmpdir="$(mktemp -p "${adb_tmpbase}" -d)"
  403. adb_tmpload="$(mktemp -p "${adb_tmpdir}" -tu)"
  404. adb_tmpfile="$(mktemp -p "${adb_tmpdir}" -tu)"
  405. adb_srtopts="--temporary-directory=${adb_tmpdir} --compress-program=gzip --batch-size=32 --parallel=${cores}"
  406. else
  407. f_log "err" "the temp base directory '${adb_tmpbase}' does not exist/is not mounted yet, please create the directory or raise the 'adb_triggerdelay' to defer the adblock start"
  408. fi
  409. if [ ! -s "${adb_pidfile}" ]
  410. then
  411. printf "%s" "${$}" > "${adb_pidfile}"
  412. fi
  413. f_log "debug" "f_temp ::: tmp_base: ${adb_tmpbase:-"-"}, tmp_dir: ${adb_tmpdir:-"-"}, cores: ${cores:-"-"}, sort_options: ${adb_srtopts}, pid_file: ${adb_pidfile:-"-"}"
  414. }
  415. # remove temporary files and directories
  416. #
  417. f_rmtemp()
  418. {
  419. if [ -d "${adb_tmpdir}" ]
  420. then
  421. rm -rf "${adb_tmpdir}"
  422. fi
  423. rm -f "${adb_srcfile}"
  424. > "${adb_pidfile}"
  425. f_log "debug" "f_rmtemp ::: tmp_dir: ${adb_tmpdir:-"-"}, src_file: ${adb_srcfile:-"-"}, pid_file: ${adb_pidfile:-"-"}"
  426. }
  427. # remove dns related files
  428. #
  429. f_rmdns()
  430. {
  431. local status
  432. status="$(ubus -S call service list '{"name":"adblock"}' 2>/dev/null | jsonfilter -l1 -e '@["adblock"].instances.*.running' 2>/dev/null)"
  433. if [ "${adb_dns}" = "raw" ] || { [ -n "${adb_dns}" ] && [ -n "${status}" ]; }
  434. then
  435. > "${adb_rtfile}"
  436. if [ "${adb_backup}" -eq 1 ]
  437. then
  438. rm -f "${adb_backupdir}/${adb_dnsprefix}".*.gz
  439. fi
  440. printf "${adb_dnsheader}" > "${adb_dnsdir}/${adb_dnsfile}"
  441. f_dnsup 4
  442. fi
  443. f_rmtemp
  444. f_log "debug" "f_rmdns ::: dns: ${adb_dns}, status: ${status:-"-"}, dns_dir: ${adb_dnsdir}, dns_file: ${adb_dnsfile}, rt_file: ${adb_rtfile}, backup_dir: ${adb_backupdir:-"-"}"
  445. }
  446. # commit uci changes
  447. #
  448. f_uci()
  449. {
  450. local change config="${1}"
  451. if [ -n "${config}" ]
  452. then
  453. change="$(uci -q changes "${config}" | "${adb_awk}" '{ORS=" "; print $0}')"
  454. if [ -n "${change}" ]
  455. then
  456. uci_commit "${config}"
  457. case "${config}" in
  458. "firewall")
  459. "/etc/init.d/firewall" reload >/dev/null 2>&1
  460. ;;
  461. "resolver")
  462. printf "${adb_dnsheader}" > "${adb_dnsdir}/${adb_dnsfile}"
  463. f_count
  464. f_jsnup "running"
  465. "/etc/init.d/${adb_dns}" reload >/dev/null 2>&1
  466. ;;
  467. esac
  468. fi
  469. f_log "debug" "f_uci ::: config: ${config}, change: ${change}"
  470. fi
  471. }
  472. # get list counter
  473. #
  474. f_count()
  475. {
  476. local file mode="${1}" name="${2}"
  477. adb_cnt=0
  478. case "${mode}" in
  479. "blacklist")
  480. if [ -s "${adb_tmpfile}.${name}" ]
  481. then
  482. adb_cnt="$(wc -l 2>/dev/null < "${adb_tmpfile}.${name}")"
  483. fi
  484. ;;
  485. "whitelist")
  486. if [ -s "${adb_tmpdir}/tmp.raw.${name}" ]
  487. then
  488. adb_cnt="$(wc -l 2>/dev/null < "${adb_tmpdir}/tmp.raw.${name}")"
  489. rm -f "${adb_tmpdir}/tmp.raw.${name}"
  490. fi
  491. ;;
  492. "safesearch")
  493. if [ -s "${adb_tmpdir}/tmp.safesearch.${name}" ]
  494. then
  495. adb_cnt="$(wc -l 2>/dev/null < "${adb_tmpdir}/tmp.safesearch.${name}")"
  496. fi
  497. ;;
  498. "merge")
  499. if [ -s "${adb_tmpdir}/${adb_dnsfile}" ]
  500. then
  501. adb_cnt="$(wc -l 2>/dev/null < "${adb_tmpdir}/${adb_dnsfile}")"
  502. fi
  503. ;;
  504. "download"|"backup"|"restore")
  505. if [ -s "${src_tmpfile}" ]
  506. then
  507. adb_cnt="$(wc -l 2>/dev/null < "${src_tmpfile}")"
  508. fi
  509. ;;
  510. "final")
  511. if [ -s "${adb_dnsdir}/${adb_dnsfile}" ]
  512. then
  513. adb_cnt="$(wc -l 2>/dev/null < "${adb_dnsdir}/${adb_dnsfile}")"
  514. if [ -s "${adb_tmpdir}/tmp.add.whitelist" ]
  515. then
  516. adb_cnt=$((adb_cnt-$(wc -l 2>/dev/null < "${adb_tmpdir}/tmp.add.whitelist")))
  517. fi
  518. for file in "${adb_tmpdir}/tmp.safesearch".*
  519. do
  520. if [ -r "${file}" ]
  521. then
  522. adb_cnt=$((adb_cnt-$(wc -l 2>/dev/null < "${file}")))
  523. fi
  524. done
  525. if [ -n "${adb_dnsheader}" ]
  526. then
  527. adb_cnt=$(((adb_cnt-$(printf "${adb_dnsheader}" | grep -c "^"))/2))
  528. fi
  529. fi
  530. ;;
  531. esac
  532. }
  533. # set external config options
  534. #
  535. f_extconf()
  536. {
  537. local config config_dir config_file port fwcfg
  538. case "${adb_dns}" in
  539. "dnsmasq")
  540. config="dhcp"
  541. config_dir="$(uci_get dhcp "@dnsmasq[${adb_dnsinstance}]" confdir | grep -Fo "${adb_dnsdir}")"
  542. if [ "${adb_enabled}" -eq 1 ] && [ -z "${config_dir}" ]
  543. then
  544. uci_set dhcp "@dnsmasq[${adb_dnsinstance}]" confdir "${adb_dnsdir}" 2>/dev/null
  545. fi
  546. ;;
  547. "kresd")
  548. config="resolver"
  549. config_file="$(uci_get resolver kresd rpz_file | grep -Fo "${adb_dnsdir}/${adb_dnsfile}")"
  550. if [ "${adb_enabled}" -eq 1 ] && [ -z "${config_file}" ]
  551. then
  552. uci -q add_list resolver.kresd.rpz_file="${adb_dnsdir}/${adb_dnsfile}"
  553. elif [ "${adb_enabled}" -eq 0 ] && [ -n "${config_file}" ]
  554. then
  555. uci -q del_list resolver.kresd.rpz_file="${adb_dnsdir}/${adb_dnsfile}"
  556. fi
  557. ;;
  558. esac
  559. f_uci "${config}"
  560. config="firewall"
  561. fwcfg="$(uci -qNX show "${config}")"
  562. if [ "${adb_enabled}" -eq 1 ] && [ "${adb_forcedns}" -eq 1 ] && \
  563. [ "$(/etc/init.d/firewall enabled; printf "%u" ${?})" -eq 0 ]
  564. then
  565. for port in ${adb_portlist}
  566. do
  567. if [ -z "$(printf "%s" "${fwcfg}" | grep -Fo -m1 "adblock_dns_${port}")" ]
  568. then
  569. uci -q batch <<-EOC
  570. set firewall."adblock_dns_${port}"="redirect"
  571. set firewall."adblock_dns_${port}".name="Adblock DNS, port ${port}"
  572. set firewall."adblock_dns_${port}".src="lan"
  573. set firewall."adblock_dns_${port}".proto="tcp udp"
  574. set firewall."adblock_dns_${port}".src_dport="${port}"
  575. set firewall."adblock_dns_${port}".dest_port="${port}"
  576. set firewall."adblock_dns_${port}".target="DNAT"
  577. EOC
  578. fi
  579. done
  580. elif [ "${adb_enabled}" -eq 0 ] || [ "${adb_forcedns}" -eq 0 ]
  581. then
  582. for port in ${adb_portlist}
  583. do
  584. if [ -n "$(printf "%s" "${fwcfg}" | grep -Fo -m1 "adblock_dns_${port}")" ]
  585. then
  586. uci_remove firewall "adblock_dns_${port}"
  587. fi
  588. done
  589. fi
  590. f_uci "${config}"
  591. }
  592. # restart dns backend
  593. #
  594. f_dnsup()
  595. {
  596. local dns_service dns_up dns_pid dns_procfile restart_rc cnt=0 out_rc=4 in_rc="${1:-0}"
  597. if [ "${adb_dns}" = "raw" ] || { [ "${in_rc}" -eq 0 ] && [ "${adb_dnsinotify}" -eq 1 ]; }
  598. then
  599. out_rc=0
  600. else
  601. "/etc/init.d/${adb_dns}" restart >/dev/null 2>&1
  602. restart_rc="${?}"
  603. fi
  604. if [ "${restart_rc}" = "0" ]
  605. then
  606. while [ "${cnt}" -le "${adb_dnstimeout}" ]
  607. do
  608. dns_service="$(ubus -S call service list "{\"name\":\"${adb_dns}\"}")"
  609. dns_up="$(printf "%s" "${dns_service}" | jsonfilter -l1 -e "@[\"${adb_dns}\"].instances.*.running")"
  610. dns_pid="$(printf "%s" "${dns_service}" | jsonfilter -l1 -e "@[\"${adb_dns}\"].instances.*.pid")"
  611. dns_procfile="$(ls -l "/proc/${dns_pid}/fd" 2>/dev/null | grep -Fo "${adb_dnsdir}/${adb_dnsfile}")"
  612. if [ "${dns_up}" = "true" ] && [ -n "${dns_pid}" ] && [ -z "${dns_procfile}" ]
  613. then
  614. if [ -x "${adb_lookupcmd}" ] && [ "${adb_lookupdomain}" != "false" ]
  615. then
  616. "${adb_lookupcmd}" "${adb_lookupdomain}" >/dev/null 2>&1
  617. if [ "${?}" -eq 0 ]
  618. then
  619. out_rc=0
  620. break
  621. fi
  622. else
  623. sleep ${adb_dnstimeout}
  624. cnt=${adb_dnstimeout}
  625. out_rc=0
  626. break
  627. fi
  628. fi
  629. cnt=$((cnt+1))
  630. sleep 1
  631. done
  632. fi
  633. f_log "debug" "f_dnsup ::: lookup_util: ${adb_lookupcmd:-"-"}, lookup_domain: ${adb_lookupdomain:-"-"}, restart_rc: ${restart_rc:-"-"}, dns_timeout: ${adb_dnstimeout}, dns_cnt: ${cnt}, in_rc: ${in_rc}, out_rc: ${out_rc}"
  634. return "${out_rc}"
  635. }
  636. # backup/restore/remove blocklists
  637. #
  638. f_list()
  639. {
  640. local hold file rset item array safe_url safe_ips safe_cname safe_domains out_rc mode="${1}" src_name="${2:-"${src_name}"}" in_rc="${src_rc:-0}" cnt=1 ffiles="-maxdepth 1 -name ${adb_dnsprefix}.*.gz"
  641. case "${mode}" in
  642. "blacklist"|"whitelist")
  643. src_name="${mode}"
  644. if [ "${src_name}" = "blacklist" ] && [ -s "${adb_blacklist}" ]
  645. then
  646. rset="/^([[:alnum:]_-]{1,63}\\.)+[[:alpha:]]+([[:space:]]|$)/{print tolower(\$1)}"
  647. "${adb_awk}" "${rset}" "${adb_blacklist}" | \
  648. "${adb_awk}" 'BEGIN{FS="."}{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' > "${adb_tmpdir}/tmp.raw.${src_name}"
  649. sort ${adb_srtopts} -u "${adb_tmpdir}/tmp.raw.${src_name}" 2>/dev/null > "${adb_tmpfile}.${src_name}"
  650. out_rc="${?}"
  651. rm -f "${adb_tmpdir}/tmp.raw.${src_name}"
  652. elif [ "${src_name}" = "whitelist" ] && [ -s "${adb_whitelist}" ]
  653. then
  654. rset="/^([[:alnum:]_-]{1,63}\\.)+[[:alpha:]]+([[:space:]]|$)/{print tolower(\$1)}"
  655. "${adb_awk}" "${rset}" "${adb_whitelist}" > "${adb_tmpdir}/tmp.raw.${src_name}"
  656. out_rc="${?}"
  657. if [ "${out_rc}" -eq 0 ]
  658. then
  659. rset="/^([[:alnum:]_-]{1,63}\\.)+[[:alpha:]]+([[:space:]]|$)/{gsub(\"\\\\.\",\"\\\\.\",\$1);print tolower(\"^(|.*\\\\.)\"\$1\"$\")}"
  660. "${adb_awk}" "${rset}" "${adb_tmpdir}/tmp.raw.${src_name}" > "${adb_tmpdir}/tmp.rem.${src_name}"
  661. out_rc="${?}"
  662. if [ "${out_rc}" -eq 0 ] && [ "${adb_dnsallow}" != "1" ]
  663. then
  664. eval "${adb_dnsallow}" "${adb_tmpdir}/tmp.raw.${src_name}" > "${adb_tmpdir}/tmp.add.${src_name}"
  665. out_rc="${?}"
  666. if [ "${out_rc}" -eq 0 ] && [ "${adb_jail}" = "1" ] && [ "${adb_dnsstop}" != "0" ]
  667. then
  668. > "${adb_jaildir}/${adb_dnsjail}"
  669. if [ -n "${adb_dnsheader}" ]
  670. then
  671. printf "${adb_dnsheader}" >> "${adb_jaildir}/${adb_dnsjail}"
  672. fi
  673. cat "${adb_tmpdir}/tmp.add.${src_name}" >> "${adb_jaildir}/${adb_dnsjail}"
  674. printf "%s\n" "${adb_dnsstop}" >> "${adb_jaildir}/${adb_dnsjail}"
  675. fi
  676. fi
  677. fi
  678. fi
  679. ;;
  680. "safesearch")
  681. case "${src_name}" in
  682. "google")
  683. rset="/^(\\.[[:alnum:]_-]{1,63}\\.)+[[:alpha:]]+([[:space:]]|$)/{printf \"%s\n%s\n\",tolower(\"www\"\$1),tolower(substr(\$1,2,length(\$1)))}"
  684. safe_url="https://www.google.com/supported_domains"
  685. safe_ips="216.239.38.120 2001:4860:4802:32::78"
  686. safe_cname="forcesafesearch.google.com"
  687. safe_domains="${adb_tmpdir}/tmp.load.safesearch.${src_name}"
  688. if [ "${adb_backup}" -eq 1 ] && [ -s "${adb_backupdir}/safesearch.${src_name}.gz" ]
  689. then
  690. zcat "${adb_backupdir}/safesearch.${src_name}.gz" > "${safe_domains}"
  691. out_rc="${?}"
  692. else
  693. "${adb_fetchutil}" ${adb_fetchparm} "${safe_domains}" "${safe_url}" 2>/dev/null
  694. out_rc="${?}"
  695. if [ "${adb_backup}" -eq 1 ] && [ "${out_rc}" -eq 0 ]
  696. then
  697. gzip -cf "${safe_domains}" > "${adb_backupdir}/safesearch.${src_name}.gz"
  698. fi
  699. fi
  700. if [ "${out_rc}" -eq 0 ]
  701. then
  702. "${adb_awk}" "${rset}" "${safe_domains}" > "${adb_tmpdir}/tmp.raw.safesearch.${src_name}"
  703. out_rc="${?}"
  704. fi
  705. ;;
  706. "bing")
  707. safe_ips="204.79.197.220 ::FFFF:CC4F:C5DC"
  708. safe_cname="strict.bing.com"
  709. safe_domains="www.bing.com"
  710. printf "%s\n" ${safe_domains} > "${adb_tmpdir}/tmp.raw.safesearch.${src_name}"
  711. out_rc="${?}"
  712. ;;
  713. "duckduckgo")
  714. safe_ips="50.16.250.179 54.208.102.2 52.204.96.252"
  715. safe_cname="safe.duckduckgo.com"
  716. safe_domains="duckduckgo.com"
  717. printf "%s\n" ${safe_domains} > "${adb_tmpdir}/tmp.raw.safesearch.${src_name}"
  718. out_rc="${?}"
  719. ;;
  720. "pixabay")
  721. safe_ips="104.18.82.97 2606:4700::6812:8d57 2606:4700::6812:5261"
  722. safe_cname="safesearch.pixabay.com"
  723. safe_domains="pixabay.com"
  724. printf "%s\n" ${safe_domains} > "${adb_tmpdir}/tmp.raw.safesearch.${src_name}"
  725. out_rc="${?}"
  726. ;;
  727. "yandex")
  728. safe_ips="213.180.193.56"
  729. safe_cname="familysearch.yandex.ru"
  730. safe_domains="ya.ru yandex.ru yandex.com yandex.com.tr yandex.ua yandex.by yandex.ee yandex.lt yandex.lv yandex.md yandex.uz yandex.tm yandex.tj yandex.az"
  731. printf "%s\n" ${safe_domains} > "${adb_tmpdir}/tmp.raw.safesearch.${src_name}"
  732. out_rc="${?}"
  733. ;;
  734. "youtube")
  735. if [ "${adb_safesearchmod}" -eq 0 ]
  736. then
  737. safe_ips="216.239.38.120 2001:4860:4802:32::78"
  738. safe_cname="restrict.youtube.com"
  739. else
  740. safe_ips="216.239.38.119 2001:4860:4802:32::77"
  741. safe_cname="restrictmoderate.youtube.com"
  742. fi
  743. safe_domains="www.youtube.com m.youtube.com youtubei.googleapis.com youtube.googleapis.com www.youtube-nocookie.com"
  744. printf "%s\n" ${safe_domains} > "${adb_tmpdir}/tmp.raw.safesearch.${src_name}"
  745. out_rc="${?}"
  746. ;;
  747. esac
  748. if [ "${out_rc}" -eq 0 ]
  749. then
  750. > "${adb_tmpdir}/tmp.safesearch.${src_name}"
  751. if [ "${adb_dns}" = "named" ]
  752. then
  753. array="${safe_cname}"
  754. else
  755. array="${safe_ips}"
  756. fi
  757. for item in ${array}
  758. do
  759. eval "${adb_dnssafesearch}" "${adb_tmpdir}/tmp.raw.safesearch.${src_name}" >> "${adb_tmpdir}/tmp.safesearch.${src_name}"
  760. if [ "${?}" -ne 0 ]
  761. then
  762. rm -f "${adb_tmpdir}/tmp.safesearch.${src_name}"
  763. break
  764. fi
  765. done
  766. out_rc="${?}"
  767. rm -f "${adb_tmpdir}/tmp.raw.safesearch.${src_name}"
  768. fi
  769. ;;
  770. "backup")
  771. (
  772. gzip -cf "${src_tmpfile}" > "${adb_backupdir}/${adb_dnsprefix}.${src_name}.gz"
  773. out_rc="${?}"
  774. )&
  775. ;;
  776. "restore")
  777. if [ -n "${src_name}" ] && [ -s "${adb_backupdir}/${adb_dnsprefix}.${src_name}.gz" ]
  778. then
  779. zcat "${adb_backupdir}/${adb_dnsprefix}.${src_name}.gz" > "${src_tmpfile}"
  780. out_rc="${?}"
  781. elif [ -z "${src_name}" ]
  782. then
  783. for file in "${adb_backupdir}/${adb_dnsprefix}".*.gz
  784. do
  785. if [ -r "${file}" ]
  786. then
  787. name="${file##*/}"
  788. name="${name%.*}"
  789. zcat "${file}" > "${adb_tmpfile}.${name}" &
  790. hold=$((cnt%adb_maxqueue))
  791. if [ "${hold}" -eq 0 ]
  792. then
  793. wait
  794. fi
  795. cnt=$((cnt+1))
  796. fi
  797. done
  798. wait
  799. out_rc="${?}"
  800. else
  801. out_rc=4
  802. fi
  803. if [ "${adb_action}" != "start" ] && [ "${adb_action}" != "resume" ] && [ -n "${src_name}" ] && [ "${out_rc}" -ne 0 ]
  804. then
  805. adb_sources="${adb_sources/${src_name}}"
  806. fi
  807. ;;
  808. "remove")
  809. if [ "${adb_backup}" -eq 1 ]
  810. then
  811. rm "${adb_backupdir}/${adb_dnsprefix}.${src_name}.gz" 2>/dev/null
  812. fi
  813. out_rc="${?}"
  814. adb_sources="${adb_sources/${src_name}}"
  815. ;;
  816. "merge")
  817. if [ "${adb_backup}" -eq 1 ]
  818. then
  819. for src_name in ${adb_sources}
  820. do
  821. ffiles="${ffiles} -a ! -name ${adb_dnsprefix}.${src_name}.gz"
  822. done
  823. if [ "${adb_safesearch}" -eq 1 ] && [ "${adb_dnssafesearch}" != "0" ]
  824. then
  825. ffiles="${ffiles} -a ! -name safesearch.google.gz"
  826. fi
  827. find "${adb_backupdir}" ${ffiles} -print0 2>/dev/null | xargs -0 rm 2>/dev/null
  828. fi
  829. unset src_name
  830. sort ${adb_srtopts} -mu "${adb_tmpfile}".* 2>/dev/null > "${adb_tmpdir}/${adb_dnsfile}"
  831. out_rc="${?}"
  832. rm -f "${adb_tmpfile}".*
  833. ;;
  834. "final")
  835. unset src_name
  836. if [ -n "${adb_dnsheader}" ]
  837. then
  838. printf "${adb_dnsheader}" > "${adb_dnsdir}/${adb_dnsfile}"
  839. else
  840. > "${adb_dnsdir}/${adb_dnsfile}"
  841. fi
  842. if [ -s "${adb_tmpdir}/tmp.add.whitelist" ]
  843. then
  844. cat "${adb_tmpdir}/tmp.add.whitelist" >> "${adb_dnsdir}/${adb_dnsfile}"
  845. fi
  846. for file in "${adb_tmpdir}/tmp.safesearch".*
  847. do
  848. if [ -r "${file}" ]
  849. then
  850. cat "${file}" >> "${adb_dnsdir}/${adb_dnsfile}"
  851. fi
  852. done
  853. if [ "${adb_dnsdeny}" != "0" ]
  854. then
  855. eval "${adb_dnsdeny}" "${adb_tmpdir}/${adb_dnsfile}" >> "${adb_dnsdir}/${adb_dnsfile}"
  856. else
  857. mv "${adb_tmpdir}/${adb_dnsfile}" "${adb_dnsdir}/${adb_dnsfile}"
  858. fi
  859. out_rc="${?}"
  860. ;;
  861. esac
  862. f_count "${mode}" "${src_name}"
  863. out_rc="${out_rc:-"${in_rc}"}"
  864. f_log "debug" "f_list ::: name: ${src_name:-"-"}, mode: ${mode}, cnt: ${adb_cnt}, in_rc: ${in_rc}, out_rc: ${out_rc}"
  865. return "${out_rc}"
  866. }
  867. # top level domain compression
  868. #
  869. f_tld()
  870. {
  871. local cnt cnt_tld source="${1}" temp_tld="${1}.tld"
  872. "${adb_awk}" '{if(NR==1){tld=$NF};while(getline){if(index($NF,tld".")==0){print tld;tld=$NF}}print tld}' "${source}" | \
  873. "${adb_awk}" 'BEGIN{FS="."}{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' > "${temp_tld}"
  874. if [ "${?}" -eq 0 ]
  875. then
  876. mv -f "${temp_tld}" "${source}"
  877. cnt_tld="$(wc -l 2>/dev/null < "${source}")"
  878. else
  879. rm -f "${temp_tld}"
  880. fi
  881. f_log "debug" "f_tld ::: source: ${source}, cnt: ${adb_cnt:-"-"}, cnt_tld: ${cnt_tld:-"-"}"
  882. }
  883. # suspend/resume adblock processing
  884. #
  885. f_switch()
  886. {
  887. local status entry done="false" mode="${1}"
  888. json_load_file "${adb_rtfile}" >/dev/null 2>&1
  889. json_select "data" >/dev/null 2>&1
  890. json_get_var status "adblock_status"
  891. if [ "${mode}" = "suspend" ] && [ "${status}" = "enabled" ]
  892. then
  893. f_env
  894. printf "${adb_dnsheader}" > "${adb_dnsdir}/${adb_dnsfile}"
  895. f_count
  896. done="true"
  897. elif [ "${mode}" = "resume" ] && [ "${status}" = "paused" ]
  898. then
  899. f_env
  900. f_main
  901. done="true"
  902. fi
  903. if [ "${done}" = "true" ]
  904. then
  905. if [ "${mode}" = "suspend" ]
  906. then
  907. f_bgserv "stop"
  908. f_dnsup
  909. fi
  910. if [ "${mode}" = "resume" ]
  911. then
  912. f_bgserv "start"
  913. fi
  914. f_jsnup "${mode}"
  915. f_log "info" "${mode} adblock processing"
  916. fi
  917. f_rmtemp
  918. }
  919. # query blocklist for certain (sub-)domains
  920. #
  921. f_query()
  922. {
  923. local search result prefix suffix field query_start query_end query_timeout=30 domain="${1}" tld="${1#*.}"
  924. if [ -z "${domain}" ] || [ "${domain}" = "${tld}" ]
  925. then
  926. printf "%s\\n" "::: invalid input, please submit a single (sub-)domain :::"
  927. else
  928. case "${adb_dns}" in
  929. "dnsmasq")
  930. prefix=".*[\\/\\.]"
  931. suffix="(\\/)"
  932. field=2
  933. ;;
  934. "unbound")
  935. prefix=".*[\"\\.]"
  936. suffix="(static)"
  937. field=3
  938. ;;
  939. "named")
  940. prefix="[^\\*].*[\\.]"
  941. suffix="( \\.)"
  942. field=1
  943. ;;
  944. "kresd")
  945. prefix="[^\\*].*[\\.]"
  946. suffix="( \\.)"
  947. field=1
  948. ;;
  949. "raw")
  950. prefix=".*[\\.]"
  951. suffix=""
  952. field=1
  953. ;;
  954. esac
  955. query_start="$(date "+%s")"
  956. if [ "${adb_dnsfilereset}" -eq 0 ]
  957. then
  958. while [ "${domain}" != "${tld}" ]
  959. do
  960. search="${domain//[+*~%\$&\"\']/}"
  961. search="${search//./\\.}"
  962. result="$("${adb_awk}" -F '/|\"|\t| ' "/^(${search}|${prefix}+${search}.*${suffix})$/{i++;if(i<=9){printf \" + %s\\n\",\$${field}}else if(i==10){printf \" + %s\\n\",\"[...]\";exit}}" "${adb_dnsdir}/${adb_dnsfile}")"
  963. printf "%s\\n%s\\n%s\\n" ":::" "::: domain '${domain}' in active blocklist" ":::"
  964. printf "%s\\n\\n" "${result:-" - no match"}"
  965. domain="${tld}"
  966. tld="${domain#*.}"
  967. done
  968. fi
  969. if [ "${adb_backup}" -eq 1 ] && [ -d "${adb_backupdir}" ]
  970. then
  971. search="${1//[+*~%\$&\"\']/}"
  972. search="${search//./\\.}"
  973. printf "%s\\n%s\\n%s\\n" ":::" "::: domain '${1}' in backups and black-/whitelist" ":::"
  974. for file in "${adb_backupdir}/${adb_dnsprefix}".*.gz "${adb_blacklist}" "${adb_whitelist}"
  975. do
  976. suffix="${file##*.}"
  977. if [ "${suffix}" = "gz" ]
  978. then
  979. zcat "${file}" 2>/dev/null | \
  980. "${adb_awk}" 'BEGIN{FS="."}{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' | "${adb_awk}" -v f="${file##*/}" "BEGIN{rc=1};/^($search|.*\\.${search})$/{i++;if(i<=3){printf \" + %-30s%s\\n\",f,\$1;rc=0}else if(i==4){printf \" + %-30s%s\\n\",f,\"[...]\"}};END{exit rc}"
  981. else
  982. "${adb_awk}" -v f="${file##*/}" "BEGIN{rc=1};/^($search|.*\\.${search})$/{i++;if(i<=3){printf \" + %-30s%s\\n\",f,\$1;rc=0}else if(i==4){printf \" + %-30s%s\\n\",f,\"[...]\"}};END{exit rc}" "${file}"
  983. fi
  984. if [ "${?}" -eq 0 ]
  985. then
  986. result="true"
  987. query_end="$(date "+%s")"
  988. if [ "$((query_end-query_start))" -gt "${query_timeout}" ]
  989. then
  990. printf "%s\\n\\n" " - [...]"
  991. break
  992. fi
  993. fi
  994. done
  995. if [ "${result}" != "true" ]
  996. then
  997. printf "%s\\n\\n" " - no match"
  998. fi
  999. fi
  1000. fi
  1001. }
  1002. # update runtime information
  1003. #
  1004. f_jsnup()
  1005. {
  1006. local runtime utils memory bg_pid status="${1:-"enabled"}"
  1007. case "${status}" in
  1008. "enabled"|"error")
  1009. adb_endtime="$(date "+%s")"
  1010. memory="$("${adb_awk}" '/^MemTotal|^MemFree|^MemAvailable/{ORS="/"; print int($2/1000)}' "/proc/meminfo" 2>/dev/null | "${adb_awk}" '{print substr($0,1,length($0)-1)}')"
  1011. if [ "$(( (adb_endtime-adb_starttime)/60 ))" -lt 60 ]
  1012. then
  1013. runtime="${adb_action}, $(( (adb_endtime-adb_starttime)/60 ))m $(( (adb_endtime-adb_starttime)%60 ))s, ${memory:-0}, $(date "+%d.%m.%Y %H:%M:%S")"
  1014. else
  1015. runtime="${adb_action}, n/a, ${memory:-0}, $(date "+%d.%m.%Y %H:%M:%S")"
  1016. fi
  1017. if [ "${status}" = "error" ]
  1018. then
  1019. adb_cnt=0
  1020. fi
  1021. ;;
  1022. "suspend")
  1023. status="paused"
  1024. ;;
  1025. "resume")
  1026. status=""
  1027. ;;
  1028. esac
  1029. json_load_file "${adb_rtfile}" >/dev/null 2>&1
  1030. json_select "data" >/dev/null 2>&1
  1031. if [ "${?}" -eq 0 ]
  1032. then
  1033. if [ -z "${adb_fetchutil}" ] || [ -z "${adb_awk}" ]
  1034. then
  1035. json_get_var utils "utilities"
  1036. else
  1037. utils="${adb_fetchutil}, ${adb_awk}"
  1038. fi
  1039. if [ -z "${adb_cnt}" ]
  1040. then
  1041. json_get_var adb_cnt "blocked_domains"
  1042. adb_cnt="${adb_cnt%% *}"
  1043. fi
  1044. if [ -z "${runtime}" ]
  1045. then
  1046. json_get_var runtime "last_run"
  1047. fi
  1048. fi
  1049. > "${adb_rtfile}"
  1050. json_load_file "${adb_rtfile}" >/dev/null 2>&1
  1051. json_init
  1052. json_add_object "data"
  1053. json_add_string "adblock_status" "${status:-"enabled"}"
  1054. json_add_string "adblock_version" "${adb_ver}"
  1055. json_add_string "blocked_domains" "${adb_cnt:-0}"
  1056. json_add_array "active_sources"
  1057. for entry in ${adb_sources}
  1058. do
  1059. json_add_object
  1060. json_add_string "source" "${entry}"
  1061. json_close_object
  1062. done
  1063. json_close_array
  1064. json_add_string "dns_backend" "${adb_dns:-"-"}, ${adb_dnsdir:-"-"}"
  1065. json_add_string "run_utils" "${utils:-"-"}"
  1066. json_add_string "run_ifaces" "trigger: ${adb_trigger:-"-"}, report: ${adb_repiface:-"-"}"
  1067. json_add_string "run_directories" "base: ${adb_tmpbase}, backup: ${adb_backupdir}, report: ${adb_reportdir}, jail: ${adb_jaildir}"
  1068. json_add_string "run_flags" "backup: ${adb_backup}, reset: ${adb_dnsfilereset}, flush: ${adb_dnsflush}, force: ${adb_forcedns}, search: ${adb_safesearch}, report: ${adb_report}, mail: ${adb_mail}, jail: ${adb_jail}"
  1069. json_add_string "last_run" "${runtime:-"-"}"
  1070. json_add_string "system" "${adb_sysver}"
  1071. json_close_object
  1072. json_dump > "${adb_rtfile}"
  1073. if [ "${adb_mail}" -eq 1 ] && [ -x "${adb_mailservice}" ] && \
  1074. { [ "${status}" = "error" ] || { [ "${status}" = "enabled" ] && [ "${adb_cnt}" -le "${adb_mailcnt}" ]; } }
  1075. then
  1076. ( "${adb_mailservice}" "${adb_ver}" >/dev/null 2>&1 )&
  1077. bg_pid="${!}"
  1078. fi
  1079. f_log "debug" "f_jsnup ::: status: ${status:-"-"}, cnt: ${adb_cnt}, mail: ${adb_mail}, mail_service: ${adb_mailservice}, mail_cnt: ${adb_mailcnt}, mail_pid: ${bg_pid:-"-"}"
  1080. }
  1081. # write to syslog
  1082. #
  1083. f_log()
  1084. {
  1085. local class="${1}" log_msg="${2}"
  1086. if [ -n "${log_msg}" ] && { [ "${class}" != "debug" ] || [ "${adb_debug}" -eq 1 ]; }
  1087. then
  1088. if [ -x "${adb_loggercmd}" ]
  1089. then
  1090. "${adb_loggercmd}" -p "${class}" -t "adblock-${adb_ver}[${$}]" "${log_msg}"
  1091. else
  1092. printf "%s %s %s\\n" "${class}" "adblock-${adb_ver}[${$}]" "${log_msg}"
  1093. fi
  1094. if [ "${class}" = "err" ]
  1095. then
  1096. f_rmdns
  1097. f_bgserv "stop"
  1098. f_jsnup "error"
  1099. exit 1
  1100. fi
  1101. fi
  1102. }
  1103. # start ubus monitor service to trace dns backend events
  1104. #
  1105. f_bgserv()
  1106. {
  1107. local bg_pid status="${1}"
  1108. bg_pid="$(pgrep -f "^/bin/sh ${adb_ubusservice}.*|^/bin/ubus -S -M r -m invoke monitor|^grep -qF \"method\":\"set\",\"data\":\\{\"name\":\"${adb_dns}\"" | "${adb_awk}" '{ORS=" "; print $1}')"
  1109. if [ "${adb_dns}" != "raw" ] && [ -z "${bg_pid}" ] && [ "${status}" = "start" ] \
  1110. && [ -x "${adb_ubusservice}" ] && [ "${adb_dnsfilereset}" -eq 1 ]
  1111. then
  1112. ( "${adb_ubusservice}" "${adb_ver}" & )
  1113. elif [ -n "${bg_pid}" ] && [ "${status}" = "stop" ]
  1114. then
  1115. kill -HUP "${bg_pid}" 2>/dev/null
  1116. fi
  1117. f_log "debug" "f_bgserv ::: status: ${status:-"-"}, bg_pid: ${bg_pid:-"-"}, dns_filereset: ${adb_dnsfilereset:-"-"}, ubus_service: ${adb_ubusservice:-"-"}"
  1118. }
  1119. # main function for blocklist processing
  1120. #
  1121. f_main()
  1122. {
  1123. local src_tmpload src_tmpfile src_name src_rset src_url src_log src_arc src_cat src_item src_list src_entries src_suffix src_rc entry keylist memory cnt=1
  1124. memory="$("${adb_awk}" '/^MemTotal|^MemFree|^MemAvailable/{ORS="/"; print int($2/1000)}' "/proc/meminfo" 2>/dev/null | "${adb_awk}" '{print substr($0,1,length($0)-1)}')"
  1125. f_log "debug" "f_main ::: memory: ${memory:-0}, max_queue: ${adb_maxqueue}, safe_search: ${adb_safesearch}, force_dns: ${adb_forcedns}, awk: ${adb_awk}"
  1126. # white- and blacklist preparation
  1127. #
  1128. for entry in ${adb_locallist}
  1129. do
  1130. ( f_list "${entry}" "${entry}" )&
  1131. done
  1132. # safe search preparation
  1133. #
  1134. if [ "${adb_safesearch}" -eq 1 ] && [ "${adb_dnssafesearch}" != "0" ]
  1135. then
  1136. if [ -z "${adb_safesearchlist}" ]
  1137. then
  1138. adb_safesearchlist="google bing duckduckgo pixabay yandex youtube"
  1139. fi
  1140. for entry in ${adb_safesearchlist}
  1141. do
  1142. ( f_list safesearch "${entry}" )&
  1143. done
  1144. fi
  1145. wait
  1146. # main loop
  1147. #
  1148. for src_name in ${adb_sources}
  1149. do
  1150. json_select "${src_name}" >/dev/null 2>&1
  1151. if [ "${?}" -ne 0 ]
  1152. then
  1153. adb_sources="${adb_sources/${src_name}}"
  1154. continue
  1155. fi
  1156. json_get_var src_url "url" >/dev/null 2>&1
  1157. json_get_var src_rset "rule" >/dev/null 2>&1
  1158. json_get_values src_cat "categories" >/dev/null 2>&1
  1159. json_select ..
  1160. src_tmpload="${adb_tmpload}.${src_name}.load"
  1161. src_tmpsort="${adb_tmpload}.${src_name}.sort"
  1162. src_tmpfile="${adb_tmpfile}.${src_name}"
  1163. src_rc=4
  1164. # basic pre-checks
  1165. #
  1166. if [ -z "${src_url}" ] || [ -z "${src_rset}" ]
  1167. then
  1168. f_list remove
  1169. continue
  1170. fi
  1171. # backup mode
  1172. #
  1173. if [ "${adb_backup}" -eq 1 ] && { [ "${adb_action}" = "start" ] || [ "${adb_action}" = "resume" ]; }
  1174. then
  1175. f_list restore
  1176. if [ "${?}" -eq 0 ] && [ -s "${src_tmpfile}" ]
  1177. then
  1178. continue
  1179. fi
  1180. fi
  1181. # download queue processing
  1182. #
  1183. if [ -n "${src_cat}" ]
  1184. then
  1185. (
  1186. src_arc="${adb_tmpdir}/${src_url##*/}"
  1187. src_log="$("${adb_fetchutil}" ${adb_fetchparm} "${src_arc}" "${src_url}" 2>&1)"
  1188. src_rc="${?}"
  1189. if [ "${src_rc}" -eq 0 ] && [ -s "${src_arc}" ]
  1190. then
  1191. unset src_entries
  1192. src_suffix="$(eval printf "%s" \"\$\{adb_src_suffix_${src_name}:-\"domains\"\}\")"
  1193. src_list="$(tar -tzf "${src_arc}" 2>/dev/null)"
  1194. for src_item in ${src_cat}
  1195. do
  1196. src_entries="${src_entries} $(printf "%s" "${src_list}" | grep -E "${src_item}/${src_suffix}$")"
  1197. done
  1198. if [ -n "${src_entries}" ]
  1199. then
  1200. tar -xOzf "${src_arc}" ${src_entries} 2>/dev/null > "${src_tmpload}"
  1201. src_rc="${?}"
  1202. fi
  1203. rm -f "${src_arc}"
  1204. else
  1205. src_log="$(printf "%s" "${src_log}" | "${adb_awk}" '{ORS=" ";print $0}')"
  1206. f_log "info" "download of '${src_name}' failed, url: ${src_url}, rule: ${src_rset:-"-"}, categories: ${src_cat:-"-"}, rc: ${src_rc}, log: ${src_log:-"-"}"
  1207. fi
  1208. if [ "${src_rc}" -eq 0 ] && [ -s "${src_tmpload}" ]
  1209. then
  1210. if [ -s "${adb_tmpdir}/tmp.rem.whitelist" ]
  1211. then
  1212. "${adb_awk}" "${src_rset}" "${src_tmpload}" | sed "s/\r//g" | \
  1213. grep -Evf "${adb_tmpdir}/tmp.rem.whitelist" | "${adb_awk}" 'BEGIN{FS="."}{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' > "${src_tmpsort}"
  1214. else
  1215. "${adb_awk}" "${src_rset}" "${src_tmpload}" | sed "s/\r//g" | \
  1216. "${adb_awk}" 'BEGIN{FS="."}{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' > "${src_tmpsort}"
  1217. fi
  1218. rm -f "${src_tmpload}"
  1219. sort ${adb_srtopts} -u "${src_tmpsort}" 2>/dev/null > "${src_tmpfile}"
  1220. src_rc="${?}"
  1221. rm -f "${src_tmpsort}"
  1222. if [ "${src_rc}" -eq 0 ] && [ -s "${src_tmpfile}" ]
  1223. then
  1224. f_list download
  1225. if [ "${adb_backup}" -eq 1 ]
  1226. then
  1227. f_list backup
  1228. fi
  1229. elif [ "${adb_backup}" -eq 1 ] && [ "${adb_action}" != "start" ]
  1230. then
  1231. f_log "info" "archive preparation of '${src_name}' failed, categories: ${src_cat:-"-"}, entries: ${src_entries}, rc: ${src_rc}"
  1232. f_list restore
  1233. rm -f "${src_tmpfile}"
  1234. fi
  1235. elif [ "${adb_backup}" -eq 1 ] && [ "${adb_action}" != "start" ]
  1236. then
  1237. f_log "info" "archive extraction of '${src_name}' failed, categories: ${src_cat:-"-"}, entries: ${src_entries}, rc: ${src_rc}"
  1238. f_list restore
  1239. fi
  1240. )&
  1241. continue
  1242. else
  1243. (
  1244. src_log="$("${adb_fetchutil}" ${adb_fetchparm} "${src_tmpload}" "${src_url}" 2>&1)"
  1245. src_rc="${?}"
  1246. if [ "${src_rc}" -eq 0 ] && [ -s "${src_tmpload}" ]
  1247. then
  1248. if [ -s "${adb_tmpdir}/tmp.rem.whitelist" ]
  1249. then
  1250. "${adb_awk}" "${src_rset}" "${src_tmpload}" | sed "s/\r//g" | \
  1251. grep -Evf "${adb_tmpdir}/tmp.rem.whitelist" | "${adb_awk}" 'BEGIN{FS="."}{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' > "${src_tmpsort}"
  1252. else
  1253. "${adb_awk}" "${src_rset}" "${src_tmpload}" | sed "s/\r//g" | \
  1254. "${adb_awk}" 'BEGIN{FS="."}{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' > "${src_tmpsort}"
  1255. fi
  1256. rm -f "${src_tmpload}"
  1257. sort ${adb_srtopts} -u "${src_tmpsort}" 2>/dev/null > "${src_tmpfile}"
  1258. src_rc="${?}"
  1259. rm -f "${src_tmpsort}"
  1260. if [ "${src_rc}" -eq 0 ] && [ -s "${src_tmpfile}" ]
  1261. then
  1262. f_list download
  1263. if [ "${adb_backup}" -eq 1 ]
  1264. then
  1265. f_list backup
  1266. fi
  1267. elif [ "${adb_backup}" -eq 1 ] && [ "${adb_action}" != "start" ]
  1268. then
  1269. f_log "info" "preparation of '${src_name}' failed, rc: ${src_rc}"
  1270. f_list restore
  1271. rm -f "${src_tmpfile}"
  1272. fi
  1273. else
  1274. src_log="$(printf "%s" "${src_log}" | "${adb_awk}" '{ORS=" ";print $0}')"
  1275. f_log "info" "download of '${src_name}' failed, url: ${src_url}, rule: ${src_rset:-"-"}, categories: ${src_cat:-"-"}, rc: ${src_rc}, log: ${src_log:-"-"}"
  1276. if [ "${adb_backup}" -eq 1 ] && [ "${adb_action}" != "start" ]
  1277. then
  1278. f_list restore
  1279. fi
  1280. fi
  1281. )&
  1282. fi
  1283. hold=$((cnt%adb_maxqueue))
  1284. if [ "${hold}" -eq 0 ]
  1285. then
  1286. wait
  1287. fi
  1288. cnt=$((cnt+1))
  1289. done
  1290. wait
  1291. f_list merge
  1292. # tld compression and dns restart
  1293. #
  1294. if [ "${?}" -eq 0 ] && [ -s "${adb_tmpdir}/${adb_dnsfile}" ]
  1295. then
  1296. f_tld "${adb_tmpdir}/${adb_dnsfile}"
  1297. f_list final
  1298. else
  1299. printf "${adb_dnsheader}" > "${adb_dnsdir}/${adb_dnsfile}"
  1300. fi
  1301. chown "${adb_dnsuser}" "${adb_dnsdir}/${adb_dnsfile}" 2>/dev/null
  1302. f_dnsup
  1303. if [ "${?}" -eq 0 ]
  1304. then
  1305. if [ "${adb_action}" != "resume" ]
  1306. then
  1307. f_jsnup "enabled"
  1308. fi
  1309. if [ "${adb_dns}" != "raw" ] && [ "${adb_dnsfilereset}" -eq 1 ]
  1310. then
  1311. printf "${adb_dnsheader}" > "${adb_dnsdir}/${adb_dnsfile}"
  1312. f_log "info" "blocklist with overall ${adb_cnt} blocked domains loaded successfully and reset afterwards (${adb_sysver})"
  1313. f_bgserv "start"
  1314. else
  1315. f_log "info" "blocklist with overall ${adb_cnt} blocked domains loaded successfully (${adb_sysver})"
  1316. fi
  1317. else
  1318. f_log "err" "dns backend restart with adblock blocklist failed"
  1319. fi
  1320. f_rmtemp
  1321. }
  1322. # trace dns queries via tcpdump and prepare a report
  1323. #
  1324. f_report()
  1325. {
  1326. local iface bg_pid status total start end blocked percent top_list top array item index hold ports cnt=0 search="${1}" count="${2}" process="${3}" print="${4}"
  1327. if [ "${adb_report}" -eq 1 ] && [ ! -x "${adb_dumpcmd}" ]
  1328. then
  1329. f_log "info" "Please install the package 'tcpdump' or 'tcpdump-mini' to use the reporting feature"
  1330. elif [ "${adb_report}" -eq 0 ] && [ "${adb_action}" = "report" ]
  1331. then
  1332. f_log "info" "Please enable the 'DNS Report' option to use the reporting feature"
  1333. fi
  1334. if [ -x "${adb_dumpcmd}" ]
  1335. then
  1336. bg_pid="$(pgrep -f "^${adb_dumpcmd}.*adb_report\\.pcap$" | "${adb_awk}" '{ORS=" "; print $1}')"
  1337. if [ "${adb_report}" -eq 0 ] || { [ -n "${bg_pid}" ] && { [ "${adb_action}" = "stop" ] || [ "${adb_action}" = "restart" ]; } }
  1338. then
  1339. if [ -n "${bg_pid}" ]
  1340. then
  1341. kill -HUP "${bg_pid}" 2>/dev/null
  1342. while $(kill -0 "${bg_pid}" 2>/dev/null)
  1343. do
  1344. sleep 1
  1345. done
  1346. unset bg_pid
  1347. fi
  1348. fi
  1349. fi
  1350. if [ -x "${adb_dumpcmd}" ] && [ "${adb_report}" -eq 1 ]
  1351. then
  1352. if [ -z "${bg_pid}" ] && [ "${adb_action}" != "report" ] && [ "${adb_action}" != "stop" ]
  1353. then
  1354. for port in ${adb_replisten}
  1355. do
  1356. if [ -z "${ports}" ]
  1357. then
  1358. ports="port ${port}"
  1359. else
  1360. ports="${ports} or port ${port}"
  1361. fi
  1362. done
  1363. if [ -z "${adb_repiface}" ]
  1364. then
  1365. network_get_device iface "lan"
  1366. if [ -n "${iface}" ]
  1367. then
  1368. adb_repiface="${iface}"
  1369. else
  1370. network_get_physdev iface "lan"
  1371. if [ -n "${iface}" ]
  1372. then
  1373. adb_repiface="${iface}"
  1374. fi
  1375. fi
  1376. if [ -n "${adb_repiface}" ]
  1377. then
  1378. uci_set adblock global adb_repiface "${adb_repiface}"
  1379. f_uci "adblock"
  1380. fi
  1381. fi
  1382. if [ -n "${adb_reportdir}" ] && [ ! -d "${adb_reportdir}" ]
  1383. then
  1384. mkdir -p "${adb_reportdir}"
  1385. f_log "info" "report directory '${adb_reportdir}' created"
  1386. fi
  1387. if [ -n "${adb_repiface}" ] && [ -d "${adb_reportdir}" ]
  1388. then
  1389. ( "${adb_dumpcmd}" -nn -s0 -l -i ${adb_repiface} ${ports} -C${adb_repchunksize} -W${adb_repchunkcnt} -w "${adb_reportdir}/adb_report.pcap" >/dev/null 2>&1 & )
  1390. bg_pid="$(pgrep -f "^${adb_dumpcmd}.*adb_report\\.pcap$" | "${adb_awk}" '{ORS=" "; print $1}')"
  1391. else
  1392. f_log "info" "Please set the name of the reporting network device 'adb_repiface' manually"
  1393. fi
  1394. fi
  1395. if [ "${adb_action}" = "report" ] && [ "${process}" = "true" ]
  1396. then
  1397. > "${adb_reportdir}/adb_report.raw"
  1398. for file in "${adb_reportdir}/adb_report.pcap"*
  1399. do
  1400. (
  1401. "${adb_dumpcmd}" -tttt -r "${file}" 2>/dev/null | \
  1402. "${adb_awk}" -v cnt="${cnt}" '!/\.lan\. |PTR\? | SOA\? /&&/ A[\? ]+|NXDomain|0\.0\.0\.0/{a=$1;b=substr($2,0,8);c=$4;sub(/\.[0-9]+$/,"",c);d=cnt $7;sub(/\*$/,"",d);
  1403. e=$(NF-1);sub(/[0-9]\/[0-9]\/[0-9]|0\.0\.0\.0/,"NX",e);sub(/\.$/,"",e);sub(/([0-9]{1,3}\.){3}[0-9]{1,3}/,"OK",e);printf "%s\t%s\t%s\t%s\t%s\n",d,e,a,b,c}' >> "${adb_reportdir}/adb_report.raw"
  1404. )&
  1405. hold=$((cnt%adb_maxqueue))
  1406. if [ "${hold}" -eq 0 ]
  1407. then
  1408. wait
  1409. fi
  1410. cnt=$((cnt+1))
  1411. done
  1412. wait
  1413. if [ -s "${adb_reportdir}/adb_report.raw" ]
  1414. then
  1415. sort ${adb_srtopts} -k1 -k3 -k4 -k5 -k1 -ur "${adb_reportdir}/adb_report.raw" | \
  1416. "${adb_awk}" '{currA=($1+0);currB=$1;currC=substr($1,length($1),1);if(reqA==currB){reqA=0;printf "%s\t%s\n",d,$2}else if(currC=="+"){reqA=currA;d=$3"\t"$4"\t"$5"\t"$2}}' | \
  1417. sort ${adb_srtopts} -k1 -k2 -k3 -k4 -ur > "${adb_reportdir}/adb_report.srt"
  1418. rm -f "${adb_reportdir}/adb_report.raw"
  1419. fi
  1420. if [ -s "${adb_reportdir}/adb_report.srt" ]
  1421. then
  1422. start="$("${adb_awk}" 'END{printf "%s_%s",$1,$2}' "${adb_reportdir}/adb_report.srt")"
  1423. end="$("${adb_awk}" 'NR==1{printf "%s_%s",$1,$2}' "${adb_reportdir}/adb_report.srt")"
  1424. total="$(wc -l < "${adb_reportdir}/adb_report.srt")"
  1425. blocked="$("${adb_awk}" '{if($5=="NX")cnt++}END{printf "%s",cnt}' "${adb_reportdir}/adb_report.srt")"
  1426. percent="$("${adb_awk}" -v t="${total}" -v b="${blocked}" 'BEGIN{printf "%.2f%s",b/t*100,"%"}')"
  1427. > "${adb_reportdir}/adb_report.json"
  1428. printf "%s" "{ \"data\": { " >> "${adb_reportdir}/adb_report.json"
  1429. printf "%s" "\"start_date\": \"${start%_*}\", " >> "${adb_reportdir}/adb_report.json"
  1430. printf "%s" "\"start_time\": \"${start#*_}\", " >> "${adb_reportdir}/adb_report.json"
  1431. printf "%s" "\"end_date\": \"${end%_*}\", " >> "${adb_reportdir}/adb_report.json"
  1432. printf "%s" "\"end_time\": \"${end#*_}\", " >> "${adb_reportdir}/adb_report.json"
  1433. printf "%s" "\"total\": \"${total}\", " >> "${adb_reportdir}/adb_report.json"
  1434. printf "%s" "\"blocked\": \"${blocked}\", " >> "${adb_reportdir}/adb_report.json"
  1435. printf "%s" "\"percent\": \"${percent}\", " >> "${adb_reportdir}/adb_report.json"
  1436. top_list="top_clients top_domains top_blocked"
  1437. for top in ${top_list}
  1438. do
  1439. printf "%s" " \"${top}\": [ " >> "${adb_reportdir}/adb_report.json"
  1440. case "${top}" in
  1441. "top_clients")
  1442. "${adb_awk}" '{print $3}' "${adb_reportdir}/adb_report.srt" | sort ${adb_srtopts} | uniq -c | \
  1443. sort ${adb_srtopts} -nr | "${adb_awk}" '{ORS=" ";if(NR==1)printf "{ \"count\": \"%s\", \"address\": \"%s\" }",$1,$2; else if(NR<10)printf ", { \"count\": \"%s\", \"address\": \"%s\" }",$1,$2}' >> "${adb_reportdir}/adb_report.json"
  1444. ;;
  1445. "top_domains")
  1446. "${adb_awk}" '{if($5!="NX")print $4}' "${adb_reportdir}/adb_report.srt" | sort ${adb_srtopts} | uniq -c | \
  1447. sort ${adb_srtopts} -nr | "${adb_awk}" '{ORS=" ";if(NR==1)printf "{ \"count\": \"%s\", \"address\": \"%s\" }",$1,$2; else if(NR<10)printf ", { \"count\": \"%s\", \"address\": \"%s\" }",$1,$2}' >> "${adb_reportdir}/adb_report.json"
  1448. ;;
  1449. "top_blocked")
  1450. "${adb_awk}" '{if($5=="NX")print $4}' "${adb_reportdir}/adb_report.srt" | sort ${adb_srtopts} | uniq -c | \
  1451. sort ${adb_srtopts} -nr | "${adb_awk}" '{ORS=" ";if(NR==1)printf "{ \"count\": \"%s\", \"address\": \"%s\" }",$1,$2; else if(NR<10)printf ", { \"count\": \"%s\", \"address\": \"%s\" }",$1,$2}' >> "${adb_reportdir}/adb_report.json"
  1452. ;;
  1453. esac
  1454. printf "%s" " ], " >> "${adb_reportdir}/adb_report.json"
  1455. done
  1456. search="${search//./\\.}"
  1457. search="${search//[+*~%\$&\"\' ]/}"
  1458. "${adb_awk}" "BEGIN{i=0;printf \"\\\"requests\\\": [ \" }/(${search})/{i++;if(i==1)printf \"{ \\\"date\\\": \\\"%s\\\", \\\"time\\\": \\\"%s\\\", \\\"client\\\": \\\"%s\\\", \\\"domain\\\": \\\"%s\\\", \\\"rc\\\": \\\"%s\\\" }\",\$1,\$2,\$3,\$4,\$5;else if(i<=${count})printf \", { \\\"date\\\": \\\"%s\\\", \\\"time\\\": \\\"%s\\\", \\\"client\\\": \\\"%s\\\", \\\"domain\\\": \\\"%s\\\", \\\"rc\\\": \\\"%s\\\" }\",\$1,\$2,\$3,\$4,\$5}END{printf \" ] } }\n\"}" "${adb_reportdir}/adb_report.srt" >> "${adb_reportdir}/adb_report.json"
  1459. rm -f "${adb_reportdir}/adb_report.srt"
  1460. fi
  1461. fi
  1462. if [ -s "${adb_reportdir}/adb_report.json" ]
  1463. then
  1464. if [ "${print}" = "cli" ]
  1465. then
  1466. printf "%s\\n%s\\n%s\\n" ":::" "::: Adblock DNS-Query Report" ":::"
  1467. json_load_file "${adb_reportdir}/adb_report.json"
  1468. json_select "data"
  1469. json_get_keys keylist
  1470. for key in ${keylist}
  1471. do
  1472. json_get_var value "${key}"
  1473. eval "${key}=\"${value}\""
  1474. done
  1475. printf " + %s\\n + %s\\n" "Start ::: ${start_date}, ${start_time}" "End ::: ${end_date}, ${end_time}"
  1476. printf " + %s\\n + %s %s\\n" "Total ::: ${total}" "Blocked ::: ${blocked}" "(${percent})"
  1477. top_list="top_clients top_domains top_blocked requests"
  1478. for top in ${top_list}
  1479. do
  1480. case "${top}" in
  1481. "top_clients")
  1482. item="::: Top 10 Clients"
  1483. ;;
  1484. "top_domains")
  1485. item="::: Top 10 Domains"
  1486. ;;
  1487. "top_blocked")
  1488. item="::: Top 10 Blocked Domains"
  1489. ;;
  1490. esac
  1491. if json_get_type status "${top}" && [ "${top}" != "requests" ] && [ "${status}" = "array" ]
  1492. then
  1493. printf "%s\\n%s\\n%s\\n" ":::" "${item}" ":::"
  1494. json_select "${top}"
  1495. index=1
  1496. while json_get_type status "${index}" && [ "${status}" = "object" ]
  1497. do
  1498. json_get_values item "${index}"
  1499. printf " + %-9s::: %s\\n" ${item}
  1500. index=$((index+1))
  1501. done
  1502. elif json_get_type status "${top}" && [ "${top}" = "requests" ] && [ "${status}" = "array" ]
  1503. then
  1504. printf "%s\\n%s\\n%s\\n" ":::" "::: Latest DNS Queries" ":::"
  1505. printf "%-15s%-15s%-45s%-50s%s\\n" "Date" "Time" "Client" "Domain" "Answer"
  1506. json_select "${top}"
  1507. index=1
  1508. while json_get_type status "${index}" && [ "${status}" = "object" ]
  1509. do
  1510. json_get_values item "${index}"
  1511. printf "%-15s%-15s%-45s%-50s%s\\n" ${item}
  1512. index=$((index+1))
  1513. done
  1514. fi
  1515. json_select ".."
  1516. done
  1517. elif [ "${print}" = "json" ]
  1518. then
  1519. cat "${adb_reportdir}/adb_report.json"
  1520. fi
  1521. fi
  1522. fi
  1523. f_log "debug" "f_report ::: action: ${adb_action}, report: ${adb_report}, search: ${1}, count: ${2}, process: ${3}, print: ${4}, dump_util: ${adb_dumpcmd}, repdir: ${adb_reportdir}, repiface: ${adb_repiface:-"-"}, replisten: ${adb_replisten}, repchunksize: ${adb_repchunksize}, repchunkcnt: ${adb_repchunkcnt}, bg_pid: ${bg_pid}"
  1524. }
  1525. # awk selection
  1526. #
  1527. adb_awk="$(command -v gawk)"
  1528. if [ -z "${adb_awk}" ]
  1529. then
  1530. adb_awk="$(command -v awk)"
  1531. fi
  1532. # source required system libraries
  1533. #
  1534. if [ -r "/lib/functions.sh" ] && [ -r "/lib/functions/network.sh" ] && [ -r "/usr/share/libubox/jshn.sh" ]
  1535. then
  1536. . "/lib/functions.sh"
  1537. . "/lib/functions/network.sh"
  1538. . "/usr/share/libubox/jshn.sh"
  1539. else
  1540. f_log "err" "system libraries not found"
  1541. fi
  1542. # handle different adblock actions
  1543. #
  1544. f_load
  1545. case "${adb_action}" in
  1546. "stop")
  1547. f_bgserv "stop"
  1548. f_report "+" "50" "false" "false"
  1549. f_rmdns
  1550. ;;
  1551. "restart")
  1552. f_bgserv "stop"
  1553. f_report "+" "50" "false" "false"
  1554. f_rmdns
  1555. f_env
  1556. f_main
  1557. ;;
  1558. "suspend")
  1559. if [ "${adb_dns}" != "raw" ]
  1560. then
  1561. f_switch suspend
  1562. fi
  1563. ;;
  1564. "resume")
  1565. if [ "${adb_dns}" != "raw" ]
  1566. then
  1567. f_switch resume
  1568. fi
  1569. ;;
  1570. "report")
  1571. f_report "${2}" "${3}" "${4}" "${5}"
  1572. ;;
  1573. "query")
  1574. f_query "${2}"
  1575. ;;
  1576. "start"|"reload")
  1577. f_bgserv "stop"
  1578. f_report "+" "50" "false" "false"
  1579. f_env
  1580. f_main
  1581. ;;
  1582. esac