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.

1304 lines
36 KiB

  1. #!/bin/sh
  2. # dns based ad/abuse domain blocking
  3. # written by Dirk Brenken (dev@brenken.org)
  4. # This is free software, licensed under the GNU General Public License v3.
  5. # You should have received a copy of the GNU General Public License
  6. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  7. # set initial defaults
  8. #
  9. LC_ALL=C
  10. PATH="/usr/sbin:/usr/bin:/sbin:/bin"
  11. adb_ver="3.6.5-2"
  12. adb_sysver="unknown"
  13. adb_enabled=0
  14. adb_debug=0
  15. adb_forcedns=0
  16. adb_jail=0
  17. adb_maxqueue=8
  18. adb_notify=0
  19. adb_notifycnt=0
  20. adb_triggerdelay=0
  21. adb_backup=0
  22. adb_backup_mode=0
  23. adb_backupdir="/mnt"
  24. adb_fetchutil="uclient-fetch"
  25. adb_dns="dnsmasq"
  26. adb_dnsprefix="adb_list"
  27. adb_dnsfile="${adb_dnsprefix}.overall"
  28. adb_dnsjail="${adb_dnsprefix}.jail"
  29. adb_dnsflush=0
  30. adb_whitelist="/etc/adblock/adblock.whitelist"
  31. adb_rtfile="/tmp/adb_runtime.json"
  32. adb_hashutil="$(command -v sha256sum)"
  33. adb_hashold=""
  34. adb_hashnew=""
  35. adb_report=0
  36. adb_repiface="br-lan"
  37. adb_replisten="53"
  38. adb_repdir="/tmp"
  39. adb_reputil="$(command -v tcpdump)"
  40. adb_repchunkcnt="5"
  41. adb_repchunksize="1"
  42. adb_cnt=""
  43. adb_rc=0
  44. adb_action="${1:-"start"}"
  45. adb_pidfile="/var/run/adblock.pid"
  46. # load adblock environment
  47. #
  48. f_envload()
  49. {
  50. local dns_up sys_call sys_desc sys_model cnt=0
  51. # get system information
  52. #
  53. sys_call="$(ubus -S call system board 2>/dev/null)"
  54. if [ -n "${sys_call}" ]
  55. then
  56. sys_desc="$(printf '%s' "${sys_call}" | jsonfilter -e '@.release.description')"
  57. sys_model="$(printf '%s' "${sys_call}" | jsonfilter -e '@.model')"
  58. adb_sysver="${sys_model}, ${sys_desc}"
  59. fi
  60. # check hash utility
  61. #
  62. if [ ! -x "${adb_hashutil}" ]
  63. then
  64. adb_hashutil="$(command -v md5sum)"
  65. fi
  66. # parse 'global' and 'extra' section by callback
  67. #
  68. config_cb()
  69. {
  70. local type="${1}"
  71. if [ "${type}" = "adblock" ]
  72. then
  73. option_cb()
  74. {
  75. local option="${1}"
  76. local value="${2}"
  77. eval "${option}=\"${value}\""
  78. }
  79. else
  80. reset_cb
  81. fi
  82. }
  83. # parse 'source' typed sections
  84. #
  85. parse_config()
  86. {
  87. local value opt section="${1}" options="enabled adb_src adb_src_rset adb_src_cat"
  88. eval "adb_sources=\"${adb_sources} ${section}\""
  89. for opt in ${options}
  90. do
  91. config_get value "${section}" "${opt}"
  92. if [ -n "${value}" ]
  93. then
  94. eval "${opt}_${section}=\"${value}\""
  95. fi
  96. done
  97. }
  98. # load adblock config
  99. #
  100. config_load adblock
  101. config_foreach parse_config source
  102. # check dns backend
  103. #
  104. case "${adb_dns}" in
  105. dnsmasq)
  106. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  107. adb_dnsuser="${adb_dnsuser:-"dnsmasq"}"
  108. adb_dnsdir="${adb_dnsdir:-"/tmp"}"
  109. adb_dnsheader=""
  110. adb_dnsdeny="awk '{print \"server=/\"\$0\"/\"}'"
  111. adb_dnsallow="awk '{print \"server=/\"\$0\"/#\"}'"
  112. adb_dnshalt="server=/#/"
  113. ;;
  114. unbound)
  115. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  116. adb_dnsuser="${adb_dnsuser:-"unbound"}"
  117. adb_dnsdir="${adb_dnsdir:-"/var/lib/unbound"}"
  118. adb_dnsheader=""
  119. adb_dnsdeny="awk '{print \"local-zone: \042\"\$0\"\042 static\"}'"
  120. adb_dnsallow="awk '{print \"local-zone: \042\"\$0\"\042 transparent\"}'"
  121. adb_dnshalt="local-zone: \".\" static"
  122. ;;
  123. named)
  124. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  125. adb_dnsuser="${adb_dnsuser:-"bind"}"
  126. adb_dnsdir="${adb_dnsdir:-"/var/lib/bind"}"
  127. adb_dnsheader="\$TTL 2h"$'\n'"@ IN SOA localhost. root.localhost. (1 6h 1h 1w 2h)"$'\n'" IN NS localhost."
  128. adb_dnsdeny="awk '{print \"\"\$0\" CNAME .\n*.\"\$0\" CNAME .\"}'"
  129. adb_dnsallow="awk '{print \"\"\$0\" CNAME rpz-passthru.\n*.\"\$0\" CNAME rpz-passthru.\"}'"
  130. adb_dnshalt="* CNAME ."
  131. ;;
  132. kresd)
  133. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  134. adb_dnsuser="${adb_dnsuser:-"root"}"
  135. adb_dnsdir="${adb_dnsdir:-"/etc/kresd"}"
  136. adb_dnsheader="\$TTL 2h"$'\n'"@ IN SOA localhost. root.localhost. (1 6h 1h 1w 2h)"$'\n'" IN NS localhost."
  137. adb_dnsdeny="awk '{print \"\"\$0\" CNAME .\n*.\"\$0\" CNAME .\"}'"
  138. adb_dnsallow="awk '{print \"\"\$0\" CNAME rpz-passthru.\n*.\"\$0\" CNAME rpz-passthru.\"}'"
  139. adb_dnshalt="* CNAME ."
  140. ;;
  141. dnscrypt-proxy)
  142. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  143. adb_dnsuser="${adb_dnsuser:-"nobody"}"
  144. adb_dnsdir="${adb_dnsdir:-"/tmp"}"
  145. adb_dnsheader=""
  146. adb_dnsdeny="awk '{print \$0}'"
  147. adb_dnsallow=""
  148. adb_dnshalt=""
  149. ;;
  150. esac
  151. # check adblock status
  152. #
  153. if [ ${adb_enabled} -eq 0 ]
  154. then
  155. f_extconf
  156. f_temp
  157. f_rmdns
  158. f_jsnup "disabled"
  159. f_log "info" "adblock is currently disabled, please set adb_enabled to '1' to use this service"
  160. exit 0
  161. fi
  162. if [ -d "${adb_dnsdir}" ] && [ ! -f "${adb_dnsdir}/${adb_dnsfile}" ]
  163. then
  164. printf '%s\n' "${adb_dnsheader}" > "${adb_dnsdir}/${adb_dnsfile}"
  165. fi
  166. if [ "${adb_action}" = "start" ] && [ "${adb_trigger}" = "timed" ]
  167. then
  168. sleep ${adb_triggerdelay}
  169. fi
  170. while [ ${cnt} -le 30 ]
  171. do
  172. dns_up="$(ubus -S call service list "{\"name\":\"${adb_dns}\"}" 2>/dev/null | jsonfilter -l1 -e "@[\"${adb_dns}\"].instances.*.running" 2>/dev/null)"
  173. if [ "${dns_up}" = "true" ]
  174. then
  175. break
  176. fi
  177. sleep 1
  178. cnt=$((cnt+1))
  179. done
  180. if [ "${dns_up}" != "true" ] || [ -z "${adb_dns}" ] || [ ! -x "$(command -v ${adb_dns})" ]
  181. then
  182. f_log "err" "'${adb_dns}' not running or not executable"
  183. elif [ ! -d "${adb_dnsdir}" ]
  184. then
  185. f_log "err" "'${adb_dnsdir}' backend directory not found"
  186. fi
  187. }
  188. # check environment
  189. #
  190. f_envcheck()
  191. {
  192. local ssl_lib
  193. # startup message
  194. #
  195. f_log "info" "adblock instance started ::: action: ${adb_action}, priority: ${adb_nice:-"0"}, pid: ${$}"
  196. f_jsnup "running"
  197. # check external uci config files
  198. #
  199. f_extconf
  200. # check fetch utility
  201. #
  202. case "${adb_fetchutil}" in
  203. uclient-fetch)
  204. if [ -f "/lib/libustream-ssl.so" ]
  205. then
  206. adb_fetchparm="${adb_fetchparm:-"--timeout=10 --no-check-certificate -O"}"
  207. ssl_lib="libustream-ssl"
  208. else
  209. adb_fetchparm="${adb_fetchparm:-"--timeout=10 -O"}"
  210. fi
  211. ;;
  212. wget)
  213. adb_fetchparm="${adb_fetchparm:-"--no-cache --no-cookies --max-redirect=0 --timeout=10 --no-check-certificate -O"}"
  214. ssl_lib="built-in"
  215. ;;
  216. wget-nossl)
  217. adb_fetchparm="${adb_fetchparm:-"--no-cache --no-cookies --max-redirect=0 --timeout=10 -O"}"
  218. ;;
  219. busybox)
  220. adb_fetchparm="${adb_fetchparm:-"-O"}"
  221. ;;
  222. curl)
  223. adb_fetchparm="${adb_fetchparm:-"--connect-timeout 10 --insecure -o"}"
  224. ssl_lib="built-in"
  225. ;;
  226. aria2c)
  227. adb_fetchparm="${adb_fetchparm:-"--timeout=10 --allow-overwrite=true --auto-file-renaming=false --check-certificate=false -o"}"
  228. ssl_lib="built-in"
  229. ;;
  230. esac
  231. adb_fetchutil="$(command -v "${adb_fetchutil}")"
  232. if [ ! -x "${adb_fetchutil}" ] || [ -z "${adb_fetchutil}" ] || [ -z "${adb_fetchparm}" ]
  233. then
  234. f_log "err" "download utility not found, please install 'uclient-fetch' with 'libustream-mbedtls' or the full 'wget' package"
  235. fi
  236. adb_fetchinfo="${adb_fetchutil} (${ssl_lib:-"-"})"
  237. f_temp
  238. }
  239. # create temporary files and directories
  240. #
  241. f_temp()
  242. {
  243. if [ -z "${adb_tmpdir}" ]
  244. then
  245. adb_tmpdir="$(mktemp -p /tmp -d)"
  246. adb_tmpload="$(mktemp -p ${adb_tmpdir} -tu)"
  247. adb_tmpfile="$(mktemp -p ${adb_tmpdir} -tu)"
  248. fi
  249. if [ ! -s "${adb_pidfile}" ]
  250. then
  251. printf '%s' "${$}" > "${adb_pidfile}"
  252. fi
  253. }
  254. # remove temporary files and directories
  255. #
  256. f_rmtemp()
  257. {
  258. if [ -d "${adb_tmpdir}" ]
  259. then
  260. rm -rf "${adb_tmpdir}"
  261. fi
  262. > "${adb_pidfile}"
  263. }
  264. # remove dns related files and directories
  265. #
  266. f_rmdns()
  267. {
  268. if [ -n "${adb_dns}" ]
  269. then
  270. f_hash
  271. printf '%s\n' "${adb_dnsheader}" > "${adb_dnsdir}/${adb_dnsfile}"
  272. > "${adb_dnsdir}/.${adb_dnsfile}"
  273. > "${adb_rtfile}"
  274. rm -f "${adb_backupdir}/${adb_dnsprefix}"*.gz
  275. f_hash
  276. if [ ${?} -eq 1 ]
  277. then
  278. f_dnsup
  279. fi
  280. f_rmtemp
  281. fi
  282. f_log "debug" "f_rmdns ::: dns: ${adb_dns}, dns_dir: ${adb_dnsdir}, dns_prefix: ${adb_dnsprefix}, dns_file: ${adb_dnsfile}, rt_file: ${adb_rtfile}, backup_dir: ${adb_backupdir}"
  283. }
  284. # commit uci changes
  285. #
  286. f_uci()
  287. {
  288. local change config="${1}"
  289. if [ -n "${config}" ]
  290. then
  291. change="$(uci -q changes "${config}" | awk '{ORS=" "; print $0}')"
  292. if [ -n "${change}" ]
  293. then
  294. uci_commit "${config}"
  295. case "${config}" in
  296. firewall)
  297. /etc/init.d/firewall reload >/dev/null 2>&1
  298. ;;
  299. *)
  300. /etc/init.d/"${adb_dns}" reload >/dev/null 2>&1
  301. ;;
  302. esac
  303. fi
  304. f_log "debug" "f_uci ::: config: ${config}, change: ${change}"
  305. fi
  306. }
  307. # list/overall count
  308. #
  309. f_count()
  310. {
  311. local mode="${1}"
  312. adb_cnt=0
  313. if [ -s "${adb_dnsdir}/${adb_dnsfile}" ] && ([ -z "${mode}" ] || [ "${mode}" = "final" ])
  314. then
  315. adb_cnt="$(wc -l 2>/dev/null < "${adb_dnsdir}/${adb_dnsfile}")"
  316. if [ -s "${adb_tmpdir}/tmp.add_whitelist" ]
  317. then
  318. adb_cnt="$(( ${adb_cnt} - $(wc -l 2>/dev/null < "${adb_tmpdir}/tmp.add_whitelist") ))"
  319. fi
  320. if [ "${adb_dns}" = "named" ] || [ "${adb_dns}" = "kresd" ]
  321. then
  322. adb_cnt="$(( (${adb_cnt} - $(printf '%s' "${adb_dnsheader}" | grep -c "^")) / 2 ))"
  323. fi
  324. elif [ -s "${adb_tmpfile}" ]
  325. then
  326. adb_cnt="$(wc -l 2>/dev/null < "${adb_tmpfile}")"
  327. fi
  328. }
  329. # set external config options
  330. #
  331. f_extconf()
  332. {
  333. local uci_config port port_list="53 853 5353"
  334. case "${adb_dns}" in
  335. dnsmasq)
  336. uci_config="dhcp"
  337. if [ ${adb_enabled} -eq 1 ] && [ -n "$(uci_get dhcp "@dnsmasq[${adb_dnsinstance}]")" ] && \
  338. [ -z "$(uci_get dhcp "@dnsmasq[${adb_dnsinstance}]" serversfile | grep -Fo "${adb_dnsdir}/${adb_dnsfile}")" ] && \
  339. [ -z "$(uci_get dhcp "@dnsmasq[${adb_dnsinstance}]" serversfile | grep -Fo "${adb_dnsdir}/${adb_dnsjail}")" ]
  340. then
  341. uci_set dhcp "@dnsmasq[${adb_dnsinstance}]" serversfile "${adb_dnsdir}/${adb_dnsfile}"
  342. elif [ ${adb_enabled} -eq 0 ] && [ -n "$(uci_get dhcp "@dnsmasq[${adb_dnsinstance}]" serversfile | grep -Fo "${adb_dnsdir}/${adb_dnsfile}")" ]
  343. then
  344. uci_remove dhcp "@dnsmasq[${adb_dnsinstance}]" serversfile
  345. fi
  346. ;;
  347. kresd)
  348. uci_config="resolver"
  349. if [ ${adb_enabled} -eq 1 ] && [ -z "$(uci_get resolver kresd rpz_file | grep -Fo "${adb_dnsdir}/${adb_dnsfile}")" ]
  350. then
  351. uci -q add_list resolver.kresd.rpz_file="${adb_dnsdir}/${adb_dnsfile}"
  352. elif [ ${adb_enabled} -eq 0 ] && [ -n "$(uci_get resolver kresd rpz_file | grep -Fo "${adb_dnsdir}/${adb_dnsfile}")" ]
  353. then
  354. uci -q del_list resolver.kresd.rpz_file="${adb_dnsdir}/${adb_dnsfile}"
  355. fi
  356. if [ ${adb_enabled} -eq 1 ] && [ ${adb_dnsflush} -eq 0 ] && [ "$(uci_get resolver kresd keep_cache)" != "1" ]
  357. then
  358. uci_set resolver kresd keep_cache "1"
  359. elif [ ${adb_enabled} -eq 0 ] || ([ ${adb_dnsflush} -eq 1 ] && [ "$(uci_get resolver kresd keep_cache)" = "1" ])
  360. then
  361. uci_set resolver kresd keep_cache "0"
  362. fi
  363. ;;
  364. esac
  365. f_uci "${uci_config}"
  366. uci_config="firewall"
  367. if [ ${adb_enabled} -eq 1 ] && [ ${adb_forcedns} -eq 1 ] && \
  368. [ -z "$(uci_get firewall adblock_dns_53)" ] && [ $(/etc/init.d/firewall enabled; printf '%u' ${?}) -eq 0 ]
  369. then
  370. for port in ${port_list}
  371. do
  372. uci_add firewall "redirect" "adblock_dns_${port}"
  373. uci_set firewall "adblock_dns_${port}" "name" "Adblock DNS, port ${port}"
  374. uci_set firewall "adblock_dns_${port}" "src" "lan"
  375. uci_set firewall "adblock_dns_${port}" "proto" "tcp udp"
  376. uci_set firewall "adblock_dns_${port}" "src_dport" "${port}"
  377. uci_set firewall "adblock_dns_${port}" "dest_port" "${port}"
  378. uci_set firewall "adblock_dns_${port}" "target" "DNAT"
  379. done
  380. elif [ -n "$(uci_get firewall adblock_dns_53)" ] && ([ ${adb_enabled} -eq 0 ] || [ ${adb_forcedns} -eq 0 ])
  381. then
  382. for port in ${port_list}
  383. do
  384. uci_remove firewall "adblock_dns_${port}"
  385. done
  386. fi
  387. f_uci "${uci_config}"
  388. }
  389. # restart of the dns backend
  390. #
  391. f_dnsup()
  392. {
  393. local dns_up cache_util cache_rc cnt=0
  394. if [ ${adb_dnsflush} -eq 0 ] && [ ${adb_enabled} -eq 1 ] && [ "${adb_rc}" -eq 0 ]
  395. then
  396. case "${adb_dns}" in
  397. dnsmasq)
  398. killall -q -HUP "${adb_dns}"
  399. cache_rc=${?}
  400. ;;
  401. unbound)
  402. cache_util="$(command -v unbound-control)"
  403. if [ -x "${cache_util}" ] && [ -d "${adb_tmpdir}" ] && [ -f "${adb_dnsdir}"/unbound.conf ]
  404. then
  405. "${cache_util}" -c "${adb_dnsdir}"/unbound.conf dump_cache > "${adb_tmpdir}"/adb_cache.dump 2>/dev/null
  406. fi
  407. "/etc/init.d/${adb_dns}" restart >/dev/null 2>&1
  408. ;;
  409. kresd)
  410. cache_util="keep_cache"
  411. "/etc/init.d/${adb_dns}" restart >/dev/null 2>&1
  412. cache_rc=${?}
  413. ;;
  414. named)
  415. cache_util="$(command -v rndc)"
  416. if [ -x "${cache_util}" ] && [ -f /etc/bind/rndc.conf ]
  417. then
  418. "${cache_util}" -c /etc/bind/rndc.conf reload >/dev/null 2>&1
  419. cache_rc=${?}
  420. else
  421. "/etc/init.d/${adb_dns}" restart >/dev/null 2>&1
  422. fi
  423. ;;
  424. *)
  425. "/etc/init.d/${adb_dns}" restart >/dev/null 2>&1
  426. ;;
  427. esac
  428. else
  429. "/etc/init.d/${adb_dns}" restart >/dev/null 2>&1
  430. fi
  431. adb_rc=1
  432. while [ ${cnt} -le 10 ]
  433. do
  434. dns_up="$(ubus -S call service list "{\"name\":\"${adb_dns}\"}" | jsonfilter -l1 -e "@[\"${adb_dns}\"].instances.*.running")"
  435. if [ "${dns_up}" = "true" ]
  436. then
  437. case "${adb_dns}" in
  438. unbound)
  439. cache_util="$(command -v unbound-control)"
  440. if [ -x "${cache_util}" ] && [ -d "${adb_tmpdir}" ] && [ -s "${adb_tmpdir}"/adb_cache.dump ]
  441. then
  442. while [ ${cnt} -le 10 ]
  443. do
  444. "${cache_util}" -c "${adb_dnsdir}"/unbound.conf load_cache < "${adb_tmpdir}"/adb_cache.dump >/dev/null 2>&1
  445. cache_rc=${?}
  446. if [ ${cache_rc} -eq 0 ]
  447. then
  448. break
  449. fi
  450. cnt=$((cnt+1))
  451. sleep 1
  452. done
  453. fi
  454. ;;
  455. esac
  456. adb_rc=0
  457. break
  458. fi
  459. cnt=$((cnt+1))
  460. sleep 1
  461. done
  462. f_log "debug" "f_dnsup ::: cache_util: ${cache_util:-"-"}, cache_rc: ${cache_rc:-"-"}, cache_flush: ${adb_dnsflush}, cache_cnt: ${cnt}, rc: ${adb_rc}"
  463. return ${adb_rc}
  464. }
  465. # backup/restore/remove blocklists
  466. #
  467. f_list()
  468. {
  469. local file mode="${1}" in_rc="${adb_rc}"
  470. case "${mode}" in
  471. backup)
  472. if [ -d "${adb_backupdir}" ]
  473. then
  474. gzip -cf "${adb_tmpfile}" 2>/dev/null > "${adb_backupdir}/${adb_dnsprefix}.${src_name}.gz"
  475. adb_rc=${?}
  476. fi
  477. ;;
  478. restore)
  479. if [ -d "${adb_backupdir}" ] && [ -f "${adb_backupdir}/${adb_dnsprefix}.${src_name}.gz" ]
  480. then
  481. gunzip -cf "${adb_backupdir}/${adb_dnsprefix}.${src_name}.gz" 2>/dev/null > "${adb_tmpfile}"
  482. adb_rc=${?}
  483. fi
  484. ;;
  485. remove)
  486. if [ -d "${adb_backupdir}" ]
  487. then
  488. rm -f "${adb_backupdir}/${adb_dnsprefix}.${src_name}.gz"
  489. fi
  490. adb_rc=${?}
  491. ;;
  492. merge)
  493. for file in "${adb_tmpfile}".*
  494. do
  495. cat "${file}" 2>/dev/null >> "${adb_tmpdir}/${adb_dnsfile}"
  496. if [ ${?} -ne 0 ]
  497. then
  498. adb_rc=${?}
  499. break
  500. fi
  501. rm -f "${file}"
  502. done
  503. adb_tmpfile="${adb_tmpdir}/${adb_dnsfile}"
  504. ;;
  505. final)
  506. > "${adb_dnsdir}/${adb_dnsfile}"
  507. if [ -s "${adb_tmpdir}/tmp.add_whitelist" ]
  508. then
  509. cat "${adb_tmpdir}/tmp.add_whitelist" >> "${adb_dnsdir}/${adb_dnsfile}"
  510. fi
  511. if [ -s "${adb_tmpdir}/tmp.rem_whitelist" ]
  512. then
  513. grep -vf "${adb_tmpdir}/tmp.rem_whitelist" "${adb_tmpdir}/${adb_dnsfile}" | eval "${adb_dnsdeny}" >> "${adb_dnsdir}/${adb_dnsfile}"
  514. else
  515. eval "${adb_dnsdeny}" "${adb_tmpdir}/${adb_dnsfile}" >> "${adb_dnsdir}/${adb_dnsfile}"
  516. fi
  517. if [ ${?} -eq 0 ] && [ -n "${adb_dnsheader}" ]
  518. then
  519. printf '%s\n' "${adb_dnsheader}" | cat - "${adb_dnsdir}/${adb_dnsfile}" > "${adb_tmpdir}/${adb_dnsfile}"
  520. mv -f "${adb_tmpdir}/${adb_dnsfile}" "${adb_dnsdir}/${adb_dnsfile}"
  521. fi
  522. adb_rc=${?}
  523. ;;
  524. esac
  525. f_count "${mode}"
  526. f_log "debug" "f_list ::: name: ${src_name:-"-"}, mode: ${mode}, cnt: ${adb_cnt}, in_rc: ${in_rc}, out_rc: ${adb_rc}"
  527. }
  528. # top level domain compression
  529. #
  530. f_tld()
  531. {
  532. local cnt cnt_srt cnt_tld source="${1}" temp_src="${1}.src.gz" temp_tld="${1}.tld" tld_ok="false"
  533. gzip -cf "${source}" 2>/dev/null > "${temp_src}"
  534. if [ ${?} -eq 0 ]
  535. then
  536. cnt="$(wc -l 2>/dev/null < "${source}")"
  537. awk 'BEGIN{FS="."}{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' "${source}" > "${temp_tld}"
  538. if [ ${?} -eq 0 ]
  539. then
  540. sort -u "${temp_tld}" > "${source}"
  541. if [ ${?} -eq 0 ]
  542. then
  543. cnt_srt="$(wc -l 2>/dev/null < "${source}")"
  544. awk '{if(NR==1){tld=$NF};while(getline){if($NF!~tld"\\."){print tld;tld=$NF}}print tld}' "${source}" > "${temp_tld}"
  545. if [ ${?} -eq 0 ]
  546. then
  547. awk 'BEGIN{FS="."}{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' "${temp_tld}" > "${source}"
  548. if [ ${?} -eq 0 ]
  549. then
  550. rm -f "${temp_src}" "${temp_tld}"
  551. cnt_tld="$(wc -l 2>/dev/null < "${source}")"
  552. tld_ok="true"
  553. fi
  554. fi
  555. fi
  556. fi
  557. fi
  558. if [ "${tld_ok}" = "false" ]
  559. then
  560. rm -f "${temp_tld}"
  561. gunzip -cf "${temp_src}" 2>/dev/null > "${source}"
  562. if [ ${?} -ne 0 ]
  563. then
  564. rm -f "${temp_src}"
  565. > "${source}"
  566. fi
  567. fi
  568. f_log "debug" "f_tld ::: source: ${source}, cnt: ${cnt:-"-"}, cnt_srt: ${cnt_srt:-"-"}, cnt_tld: ${cnt_tld:-"-"}, tld_ok: ${tld_ok}"
  569. }
  570. # blocklist hash compare
  571. #
  572. f_hash()
  573. {
  574. local hash hash_rc=1
  575. if [ -x "${adb_hashutil}" ] && [ -f "${adb_dnsdir}/${adb_dnsfile}" ]
  576. then
  577. hash="$(${adb_hashutil} "${adb_dnsdir}/${adb_dnsfile}" 2>/dev/null | awk '{print $1}')"
  578. if [ -z "${adb_hashold}" ] && [ -n "${hash}" ]
  579. then
  580. adb_hashold="${hash}"
  581. elif [ -z "${adb_hashnew}" ] && [ -n "${hash}" ]
  582. then
  583. adb_hashnew="${hash}"
  584. fi
  585. if [ -n "${adb_hashold}" ] && [ -n "${adb_hashnew}" ]
  586. then
  587. if [ "${adb_hashold}" = "${adb_hashnew}" ]
  588. then
  589. hash_rc=0
  590. fi
  591. adb_hashold=""
  592. adb_hashnew=""
  593. fi
  594. fi
  595. f_log "debug" "f_hash ::: hash_util: ${adb_hashutil}, hash: ${hash}, out_rc: ${hash_rc}"
  596. return ${hash_rc}
  597. }
  598. # suspend/resume adblock processing
  599. #
  600. f_switch()
  601. {
  602. local status cnt mode="${1}"
  603. json_load_file "${adb_rtfile}" >/dev/null 2>&1
  604. json_select "data"
  605. json_get_var status "adblock_status"
  606. json_get_var cnt "overall_domains"
  607. if [ "${mode}" = "suspend" ] && [ "${status}" = "enabled" ]
  608. then
  609. if [ ${cnt%% *} -gt 0 ] && [ -s "${adb_dnsdir}/${adb_dnsfile}" ]
  610. then
  611. f_hash
  612. cat "${adb_dnsdir}/${adb_dnsfile}" > "${adb_dnsdir}/.${adb_dnsfile}"
  613. printf '%s\n' "${adb_dnsheader}" > "${adb_dnsdir}/${adb_dnsfile}"
  614. f_hash
  615. fi
  616. elif [ "${mode}" = "resume" ] && [ "${status}" = "paused" ]
  617. then
  618. if [ ${cnt%% *} -gt 0 ] && [ -s "${adb_dnsdir}/.${adb_dnsfile}" ]
  619. then
  620. f_hash
  621. cat "${adb_dnsdir}/.${adb_dnsfile}" > "${adb_dnsdir}/${adb_dnsfile}"
  622. > "${adb_dnsdir}/.${adb_dnsfile}"
  623. f_hash
  624. fi
  625. fi
  626. if [ ${?} -eq 1 ]
  627. then
  628. f_temp
  629. f_dnsup
  630. f_jsnup "${mode}"
  631. f_log "info" "${mode} adblock processing"
  632. f_rmtemp
  633. exit 0
  634. fi
  635. }
  636. # query blocklist for certain (sub-)domains
  637. #
  638. f_query()
  639. {
  640. local search result prefix suffix field domain="${1}" tld="${1#*.}"
  641. if [ -z "${domain}" ] || [ "${domain}" = "${tld}" ]
  642. then
  643. printf '%s\n' "::: invalid domain input, please submit a single domain, e.g. 'doubleclick.net'"
  644. else
  645. case "${adb_dns}" in
  646. dnsmasq)
  647. prefix=".*[\/\.]"
  648. suffix="(\/)"
  649. field=2
  650. ;;
  651. unbound)
  652. prefix=".*[\"\.]"
  653. suffix="(static)"
  654. field=3
  655. ;;
  656. named)
  657. prefix="[^\*].*[\.]"
  658. suffix="( \.)"
  659. field=1
  660. ;;
  661. kresd)
  662. prefix="[^\*].*[\.]"
  663. suffix="( \.)"
  664. field=1
  665. ;;
  666. dnscrypt-proxy)
  667. prefix=".*[\.]"
  668. suffix=""
  669. field=1
  670. ;;
  671. esac
  672. while [ "${domain}" != "${tld}" ]
  673. do
  674. search="${domain//./\\.}"
  675. search="${search//[+*~%\$&\"\']/}"
  676. result="$(awk -F '/|\"| ' "/^(${search}|${prefix}+${search}.*${suffix}$)/{i++;{printf(\" + %s\n\",\$${field})};if(i>9){printf(\" + %s\n\",\"[...]\");exit}}" "${adb_dnsdir}/${adb_dnsfile}")"
  677. printf '%s\n%s\n%s\n' ":::" "::: results for domain '${domain}'" ":::"
  678. printf '%s\n' "${result:-" - no match"}"
  679. domain="${tld}"
  680. tld="${domain#*.}"
  681. done
  682. if [ ${adb_backup} -eq 1 ] && [ -d "${adb_backupdir}" ]
  683. then
  684. search="${1//./\\.}"
  685. search="${search//[+*~%\$&\"\']/}"
  686. printf '%s\n%s\n%s\n' ":::" "::: results for domain '${1}' in backups" ":::"
  687. for file in ${adb_backupdir}/${adb_dnsprefix}.*.gz
  688. do
  689. zcat "${file}" 2>/dev/null | awk -v f="${file##*/}" "/^($search|.*\.${search})/{i++;{printf(\" + %-30s%s\n\",f,\$1)};if(i>=3){printf(\" + %-30s%s\n\",f,\"[...]\");exit}}"
  690. done
  691. fi
  692. fi
  693. }
  694. # update runtime information
  695. #
  696. f_jsnup()
  697. {
  698. local run_time bg_pid status="${1:-"enabled"}" mode="normal mode"
  699. if [ ${adb_rc} -gt 0 ]
  700. then
  701. status="error"
  702. run_time="$(/bin/date "+%d.%m.%Y %H:%M:%S")"
  703. fi
  704. if [ "${status}" = "enabled" ]
  705. then
  706. run_time="$(/bin/date "+%d.%m.%Y %H:%M:%S")"
  707. fi
  708. if [ "${status}" = "suspend" ]
  709. then
  710. status="paused"
  711. fi
  712. if [ "${status}" = "resume" ]
  713. then
  714. status=""
  715. fi
  716. if [ ${adb_backup_mode} -eq 1 ]
  717. then
  718. mode="backup mode"
  719. fi
  720. json_load_file "${adb_rtfile}" >/dev/null 2>&1
  721. json_select "data" >/dev/null 2>&1
  722. if [ ${?} -eq 0 ]
  723. then
  724. if [ -z "${adb_fetchinfo}" ]
  725. then
  726. json_get_var adb_fetchinfo "fetch_utility"
  727. fi
  728. if [ -z "${adb_cnt}" ]
  729. then
  730. json_get_var adb_cnt "overall_domains"
  731. adb_cnt="${adb_cnt%% *}"
  732. fi
  733. if [ -z "${run_time}" ]
  734. then
  735. json_get_var run_time "last_rundate"
  736. fi
  737. fi
  738. > "${adb_rtfile}"
  739. json_load_file "${adb_rtfile}" >/dev/null 2>&1
  740. json_init
  741. json_add_object "data"
  742. json_add_string "adblock_status" "${status:-"enabled"}"
  743. json_add_string "adblock_version" "${adb_ver}"
  744. json_add_string "overall_domains" "${adb_cnt:-0} (${mode})"
  745. json_add_string "fetch_utility" "${adb_fetchinfo:-"-"}"
  746. json_add_string "dns_backend" "${adb_dns} (${adb_dnsdir})"
  747. json_add_string "last_rundate" "${run_time:-"-"}"
  748. json_add_string "system_release" "${adb_sysver}"
  749. json_close_object
  750. json_dump > "${adb_rtfile}"
  751. if [ ${adb_notify} -eq 1 ] && [ -x /etc/adblock/adblock.notify ] && \
  752. ([ "${status}" = "error" ] || ([ "${status}" = "enabled" ] && [ ${adb_cnt} -le ${adb_notifycnt} ]))
  753. then
  754. (/etc/adblock/adblock.notify >/dev/null 2>&1)&
  755. bg_pid=${!}
  756. fi
  757. f_log "debug" "f_jsnup ::: status: ${status:-"-"}, mode: ${mode}, cnt: ${adb_cnt}, notify: ${adb_notify}, notify_cnt: ${adb_notifycnt}, notify_pid: ${bg_pid:-"-"}"
  758. }
  759. # write to syslog
  760. #
  761. f_log()
  762. {
  763. local class="${1}" log_msg="${2}"
  764. if [ -n "${log_msg}" ] && ([ "${class}" != "debug" ] || [ ${adb_debug} -eq 1 ])
  765. then
  766. logger -p "${class}" -t "adblock-${adb_ver}[${$}]" "${log_msg}"
  767. if [ "${class}" = "err" ]
  768. then
  769. f_rmdns
  770. f_jsnup
  771. logger -p "${class}" -t "adblock-${adb_ver}[${$}]" "Please also check 'https://github.com/openwrt/packages/blob/master/net/adblock/files/README.md'"
  772. exit 1
  773. fi
  774. fi
  775. }
  776. # main function for blocklist processing
  777. #
  778. f_main()
  779. {
  780. local tmp_load tmp_file src_name src_rset src_url src_log src_arc src_cat cat list entry suffix mem_total mem_free enabled cnt=1
  781. mem_total="$(awk '/^MemTotal/ {print int($2/1000)}' "/proc/meminfo" 2>/dev/null)"
  782. mem_free="$(awk '/^MemFree/ {print int($2/1000)}' "/proc/meminfo" 2>/dev/null)"
  783. tmp_load="${adb_tmpload}"
  784. tmp_file="${adb_tmpfile}"
  785. > "${adb_dnsdir}/.${adb_dnsfile}"
  786. > "${adb_tmpdir}/tmp.raw_whitelist"
  787. > "${adb_tmpdir}/tmp.add_whitelist"
  788. > "${adb_tmpdir}/tmp.rem_whitelist"
  789. f_log "debug" "f_main ::: dns: ${adb_dns}, fetch_util: ${adb_fetchinfo}, backup: ${adb_backup}, backup_mode: ${adb_backup_mode}, dns_jail: ${adb_jail}, force_dns: ${adb_forcedns}, mem_total: ${mem_total:-0}, mem_free: ${mem_free:-0}, max_queue: ${adb_maxqueue}"
  790. # prepare whitelist entries
  791. #
  792. if [ -s "${adb_whitelist}" ]
  793. then
  794. adb_whitelist_rset="/^([[:alnum:]_-]+\.)+[[:alpha:]]+([[:space:]]|$)/{print tolower(\$1)}"
  795. awk "${adb_whitelist_rset}" "${adb_whitelist}" > "${adb_tmpdir}/tmp.raw_whitelist"
  796. f_tld "${adb_tmpdir}/tmp.raw_whitelist"
  797. adb_whitelist_rset="/^([[:alnum:]_-]+\.)+[[:alpha:]]+([[:space:]]|$)/{gsub(\"\\\.\",\"\\\.\",\$1);print tolower(\"^\"\$1\"\\\|\\\.\"\$1)}"
  798. awk "${adb_whitelist_rset}" "${adb_tmpdir}/tmp.raw_whitelist" > "${adb_tmpdir}/tmp.rem_whitelist"
  799. if [ -n "${adb_dnsallow}" ]
  800. then
  801. eval "${adb_dnsallow}" "${adb_tmpdir}/tmp.raw_whitelist" > "${adb_tmpdir}/tmp.add_whitelist"
  802. fi
  803. fi
  804. # build 'dnsjail' list
  805. #
  806. if [ ${adb_jail} -eq 1 ]
  807. then
  808. cat "${adb_tmpdir}/tmp.add_whitelist" > "/tmp/${adb_dnsjail}"
  809. printf '%s\n' "${adb_dnshalt}" >> "/tmp/${adb_dnsjail}"
  810. if [ -n "${adb_dnsheader}" ]
  811. then
  812. printf '%s\n' "${adb_dnsheader}" | cat - "/tmp/${adb_dnsjail}" > "${adb_tmpdir}/tmp.dnsjail"
  813. cat "${adb_tmpdir}/tmp.dnsjail" > "/tmp/${adb_dnsjail}"
  814. fi
  815. fi
  816. # main loop
  817. #
  818. for src_name in ${adb_sources}
  819. do
  820. enabled="$(eval printf '%s' \"\${enabled_${src_name}\}\")"
  821. src_url="$(eval printf '%s' \"\${adb_src_${src_name}\}\")"
  822. src_rset="$(eval printf '%s' \"\${adb_src_rset_${src_name}\}\")"
  823. src_cat="$(eval printf '%s' \"\${adb_src_cat_${src_name}\}\")"
  824. adb_tmpload="${tmp_load}.${src_name}"
  825. adb_tmpfile="${tmp_file}.${src_name}"
  826. # basic pre-checks
  827. #
  828. f_log "debug" "f_main ::: name: ${src_name}, enabled: ${enabled}"
  829. if [ "${enabled}" != "1" ] || [ -z "${src_url}" ] || [ -z "${src_rset}" ]
  830. then
  831. f_list remove
  832. continue
  833. fi
  834. # backup mode
  835. #
  836. if [ ${adb_backup_mode} -eq 1 ] && [ "${adb_action}" = "start" ] && [ "${src_name}" != "blacklist" ]
  837. then
  838. f_list restore
  839. if [ ${adb_rc} -eq 0 ] && [ -s "${adb_tmpfile}" ]
  840. then
  841. continue
  842. fi
  843. fi
  844. # download queue processing
  845. #
  846. if [ "${src_name}" = "blacklist" ]
  847. then
  848. if [ -s "${src_url}" ]
  849. then
  850. (
  851. src_log="$(cat "${src_url}" > "${adb_tmpload}" 2>&1)"
  852. adb_rc=${?}
  853. if [ ${adb_rc} -eq 0 ] && [ -s "${adb_tmpload}" ]
  854. then
  855. awk "${src_rset}" "${adb_tmpload}" 2>/dev/null > "${adb_tmpfile}"
  856. adb_rc=${?}
  857. if [ ${adb_rc} -eq 0 ] && [ -s "${adb_tmpfile}" ]
  858. then
  859. rm -f "${adb_tmpload}"
  860. f_list download
  861. fi
  862. else
  863. src_log="$(printf '%s' "${src_log}" | awk '{ORS=" ";print $0}')"
  864. f_log "debug" "f_main ::: name: ${src_name}, url: ${src_url}, rc: ${adb_rc}, log: ${src_log:-"-"}"
  865. fi
  866. ) &
  867. else
  868. continue
  869. fi
  870. elif [ -n "${src_cat}" ]
  871. then
  872. (
  873. src_arc="${adb_tmpdir}/${src_url##*/}"
  874. src_log="$("${adb_fetchutil}" ${adb_fetchparm} "${src_arc}" "${src_url}" 2>&1)"
  875. adb_rc=${?}
  876. if [ ${adb_rc} -eq 0 ] && [ -s "${src_arc}" ]
  877. then
  878. list="$(tar -tzf "${src_arc}")"
  879. suffix="$(eval printf '%s' \"\${adb_src_suffix_${src_name}:-\"domains\"\}\")"
  880. for cat in ${src_cat}
  881. do
  882. entry="$(printf '%s' "${list}" | grep -E "[\^/]+${cat}/${suffix}")"
  883. if [ -n "${entry}" ]
  884. then
  885. tar -xOzf "${src_arc}" "${entry}" >> "${adb_tmpload}"
  886. adb_rc=${?}
  887. if [ ${adb_rc} -ne 0 ]
  888. then
  889. break
  890. fi
  891. fi
  892. done
  893. else
  894. src_log="$(printf '%s' "${src_log}" | awk '{ORS=" ";print $0}')"
  895. f_log "debug" "f_main ::: name: ${src_name}, url: ${src_url}, rc: ${adb_rc}, log: ${src_log:-"-"}"
  896. fi
  897. if [ ${adb_rc} -eq 0 ] && [ -s "${adb_tmpload}" ]
  898. then
  899. rm -f "${src_arc}"
  900. awk "${src_rset}" "${adb_tmpload}" 2>/dev/null > "${adb_tmpfile}"
  901. adb_rc=${?}
  902. if [ ${adb_rc} -eq 0 ] && [ -s "${adb_tmpfile}" ]
  903. then
  904. rm -f "${adb_tmpload}"
  905. f_list download
  906. if [ ${adb_backup} -eq 1 ]
  907. then
  908. f_list backup
  909. fi
  910. elif [ ${adb_backup} -eq 1 ]
  911. then
  912. f_list restore
  913. fi
  914. elif [ ${adb_backup} -eq 1 ]
  915. then
  916. f_list restore
  917. fi
  918. ) &
  919. else
  920. (
  921. src_log="$("${adb_fetchutil}" ${adb_fetchparm} "${adb_tmpload}" "${src_url}" 2>&1)"
  922. adb_rc=${?}
  923. if [ ${adb_rc} -eq 0 ] && [ -s "${adb_tmpload}" ]
  924. then
  925. awk "${src_rset}" "${adb_tmpload}" 2>/dev/null > "${adb_tmpfile}"
  926. adb_rc=${?}
  927. if [ ${adb_rc} -eq 0 ] && [ -s "${adb_tmpfile}" ]
  928. then
  929. rm -f "${adb_tmpload}"
  930. f_list download
  931. if [ ${adb_backup} -eq 1 ]
  932. then
  933. f_list backup
  934. fi
  935. elif [ ${adb_backup} -eq 1 ]
  936. then
  937. f_list restore
  938. fi
  939. else
  940. src_log="$(printf '%s' "${src_log}" | awk '{ORS=" ";print $0}')"
  941. f_log "debug" "f_main ::: name: ${src_name}, url: ${src_url}, rc: ${adb_rc}, log: ${src_log:-"-"}"
  942. if [ ${adb_backup} -eq 1 ]
  943. then
  944. f_list restore
  945. fi
  946. fi
  947. ) &
  948. fi
  949. hold=$(( cnt % adb_maxqueue ))
  950. if [ ${hold} -eq 0 ]
  951. then
  952. wait
  953. fi
  954. cnt=$(( cnt + 1 ))
  955. done
  956. # list merge
  957. #
  958. wait
  959. src_name="overall"
  960. adb_tmpfile="${tmp_file}"
  961. f_list merge
  962. # overall sort and conditional dns restart
  963. #
  964. f_hash
  965. if [ -s "${adb_tmpdir}/${adb_dnsfile}" ]
  966. then
  967. f_tld "${adb_tmpdir}/${adb_dnsfile}"
  968. f_list final
  969. else
  970. > "${adb_dnsdir}/${adb_dnsfile}"
  971. fi
  972. chown "${adb_dnsuser}" "${adb_dnsdir}/${adb_dnsfile}" 2>/dev/null
  973. f_hash
  974. if [ ${?} -eq 1 ]
  975. then
  976. f_dnsup
  977. fi
  978. f_jsnup
  979. if [ ${?} -eq 0 ]
  980. then
  981. f_log "info" "blocklist with overall ${adb_cnt} domains loaded successfully (${adb_sysver})"
  982. else
  983. f_log "err" "dns backend restart with active blocklist failed"
  984. fi
  985. f_rmtemp
  986. exit ${adb_rc}
  987. }
  988. # trace dns queries via tcpdump and prepare a report
  989. #
  990. f_report()
  991. {
  992. local bg_pid total blocked percent rep_clients rep_domains rep_blocked index hold ports cnt=0 search="${1}" count="${2}" filter="${3}" print="${4}"
  993. if [ ${adb_report} -eq 1 ] && [ ! -x "${adb_reputil}" ]
  994. then
  995. f_log "info" "Please install the package 'tcpdump' or 'tcpdump-mini' to use the adblock reporting feature!"
  996. elif [ ${adb_report} -eq 0 ] && [ "${adb_action}" = "report" ]
  997. then
  998. f_log "info" "Please enable the extra option 'adb_report' to use the adblock reporting feature!"
  999. fi
  1000. if [ -x "${adb_reputil}" ]
  1001. then
  1002. bg_pid="$(pgrep -f "^${adb_reputil}.*adb_report\.pcap$" | awk '{ORS=" "; print $1}')"
  1003. if [ ${adb_report} -eq 0 ] || ([ -n "${bg_pid}" ] && ([ "${adb_action}" = "stop" ] || [ "${adb_action}" = "restart" ]))
  1004. then
  1005. if [ -n "${bg_pid}" ]
  1006. then
  1007. kill -HUP ${bg_pid}
  1008. while $(kill -0 ${bg_pid} 2>/dev/null)
  1009. do
  1010. sleep 1
  1011. done
  1012. unset bg_pid
  1013. fi
  1014. fi
  1015. fi
  1016. if [ -x "${adb_reputil}" ] && [ ${adb_report} -eq 1 ]
  1017. then
  1018. if [ -z "${bg_pid}" ] && [ "${adb_action}" != "report" ] && [ "${adb_action}" != "stop" ]
  1019. then
  1020. for port in ${adb_replisten}
  1021. do
  1022. if [ -z "${ports}" ]
  1023. then
  1024. ports="port ${port}"
  1025. else
  1026. ports="${ports} or port ${port}"
  1027. fi
  1028. done
  1029. ("${adb_reputil}" -nn -s0 -l -i ${adb_repiface} ${ports} -C${adb_repchunksize} -W${adb_repchunkcnt} -w "${adb_repdir}/adb_report.pcap" >/dev/null 2>&1 &)
  1030. bg_pid="$(pgrep -f "^${adb_reputil}.*adb_report\.pcap$" | awk '{ORS=" "; print $1}')"
  1031. fi
  1032. if [ "${adb_action}" = "report" ] && [ "${filter}" = "false" ]
  1033. then
  1034. > "${adb_repdir}/adb_report.raw"
  1035. for file in "${adb_repdir}"/adb_report.pcap*
  1036. do
  1037. (
  1038. "${adb_reputil}" -tttt -r $file 2>/dev/null | \
  1039. awk -v cnt=${cnt} '!/\.lan\. /&&/ A[\? ]+|NXDomain/{a=$1;b=substr($2,0,8);c=$4;sub(/\.[0-9]+$/,"",c); \
  1040. d=cnt $7;e=$(NF-1);sub(/[0-9]\/[0-9]\/[0-9]/,"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", a,b,c,d,e)}' >> "${adb_repdir}/adb_report.raw"
  1041. )&
  1042. hold=$(( cnt % adb_maxqueue ))
  1043. if [ ${hold} -eq 0 ]
  1044. then
  1045. wait
  1046. fi
  1047. cnt=$(( cnt + 1 ))
  1048. done
  1049. wait
  1050. if [ -s "${adb_repdir}/adb_report.raw" ]
  1051. then
  1052. awk '{printf("%s\t%s\t%s\t%s\t%s\t%s\n", $4,$5,$1,$2,$3,$4)}' "${adb_repdir}/adb_report.raw" | \
  1053. sort -ur | uniq -uf2 | awk '{currA=($6+0);currB=$6;currC=substr($6,length($6),1); \
  1054. 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}}' | sort -ur > "${adb_repdir}/adb_report"
  1055. fi
  1056. if [ -s "${adb_repdir}/adb_report" ]
  1057. then
  1058. total="$(wc -l < ${adb_repdir}/adb_report)"
  1059. blocked="$(awk '{if($5=="NX")print $4}' ${adb_repdir}/adb_report | wc -l)"
  1060. percent="$(awk -v t=${total} -v b=${blocked} 'BEGIN{printf("%.2f %s\n",b/t*100, "%")}')"
  1061. rep_clients="$(awk '{print $3}' ${adb_repdir}/adb_report | sort | uniq -c | sort -r | awk '{ORS=" ";if(NR<=10) printf("%s_%s ",$1,$2)}')"
  1062. rep_domains="$(awk '{if($5!="NX")print $4}' ${adb_repdir}/adb_report | sort | uniq -c | sort -r | awk '{ORS=" ";if(NR<=10)printf("%s_%s ",$1,$2)}')"
  1063. rep_blocked="$(awk '{if($5=="NX")print $4}' ${adb_repdir}/adb_report | sort | uniq -c | sort -r | awk '{ORS=" ";if(NR<=10)printf("%s_%s ",$1,$2)}')"
  1064. > "${adb_repdir}/adb_report.json"
  1065. json_load_file "${adb_repdir}/adb_report.json" >/dev/null 2>&1
  1066. json_init
  1067. json_add_object "data"
  1068. json_add_string "start_date" "$(awk 'END{printf("%s",$1)}' ${adb_repdir}/adb_report)"
  1069. json_add_string "start_time" "$(awk 'END{printf("%s",$2)}' ${adb_repdir}/adb_report)"
  1070. json_add_string "end_date" "$(awk 'NR==1{printf("%s",$1)}' ${adb_repdir}/adb_report)"
  1071. json_add_string "end_time" "$(awk 'NR==1{printf("%s",$2)}' ${adb_repdir}/adb_report)"
  1072. json_add_string "total" "${total}"
  1073. json_add_string "blocked" "${blocked}"
  1074. json_add_string "percent" "${percent}"
  1075. json_close_array
  1076. json_add_array "top_clients"
  1077. for client in ${rep_clients}
  1078. do
  1079. json_add_object
  1080. json_add_string "count" "${client%%_*}"
  1081. json_add_string "address" "${client#*_}"
  1082. json_close_object
  1083. done
  1084. json_close_array
  1085. json_add_array "top_domains"
  1086. for domain in ${rep_domains}
  1087. do
  1088. json_add_object
  1089. json_add_string "count" "${domain%%_*}"
  1090. json_add_string "address" "${domain#*_}"
  1091. json_close_object
  1092. done
  1093. json_close_array
  1094. json_add_array "top_blocked"
  1095. for block in ${rep_blocked}
  1096. do
  1097. json_add_object
  1098. json_add_string "count" "${block%%_*}"
  1099. json_add_string "address" "${block#*_}"
  1100. json_close_object
  1101. done
  1102. json_close_object
  1103. json_dump > "${adb_repdir}/adb_report.json"
  1104. fi
  1105. rm -f "${adb_repdir}/adb_report.raw"
  1106. fi
  1107. if [ -s "${adb_repdir}/adb_report" ]
  1108. then
  1109. search="${search//./\\.}"
  1110. search="${search//[+*~%\$&\"\' ]/}"
  1111. > "${adb_repdir}/adb_report.final"
  1112. awk "BEGIN{i=0}/(${search})/{i++;if(i<=${count}){printf \"%s\t%s\t%s\t%s\t%s\n\",\$1,\$2,\$3,\$4,\$5}}" "${adb_repdir}/adb_report" > "${adb_repdir}/adb_report.final"
  1113. if [ ! -s "${adb_repdir}/adb_report.final" ]
  1114. then
  1115. printf "%s\t%s\t%s\t%s\t%s\n" "-" "-" "-" "-" "-" > "${adb_repdir}/adb_report.final"
  1116. fi
  1117. fi
  1118. if [ "${print}" = "true" ]
  1119. then
  1120. if [ -s "${adb_repdir}/adb_report.json" ]
  1121. then
  1122. printf "%s\n%s\n%s\n" ":::" "::: Adblock DNS-Query Report" ":::"
  1123. json_load_file "${adb_repdir}/adb_report.json"
  1124. json_select "data"
  1125. json_get_keys keylist
  1126. for key in ${keylist}
  1127. do
  1128. json_get_var value "${key}"
  1129. eval "${key}=\"${value}\""
  1130. done
  1131. printf " + %s\n + %s\n" "Start ::: ${start_date}, ${start_time}" "End ::: ${end_date}, ${end_time}"
  1132. printf " + %s\n + %s %s\n" "Total ::: ${total}" "Blocked ::: ${blocked}" "(${percent})"
  1133. json_select ".."
  1134. if json_get_type Status "top_clients" && [ "${Status}" = "array" ]
  1135. then
  1136. printf "%s\n%s\n%s\n" ":::" "::: Top 10 Clients" ":::"
  1137. json_select "top_clients"
  1138. index=1
  1139. while json_get_type Status ${index} && [ "${Status}" = "object" ]
  1140. do
  1141. json_get_values client ${index}
  1142. printf " + %-9s::: %s\n" ${client}
  1143. index=$((index + 1))
  1144. done
  1145. fi
  1146. json_select ".."
  1147. if json_get_type Status "top_domains" && [ "${Status}" = "array" ]
  1148. then
  1149. printf "%s\n%s\n%s\n" ":::" "::: Top 10 Domains" ":::"
  1150. json_select "top_domains"
  1151. index=1
  1152. while json_get_type Status ${index} && [ "${Status}" = "object" ]
  1153. do
  1154. json_get_values domain ${index}
  1155. printf " + %-9s::: %s\n" ${domain}
  1156. index=$((index + 1))
  1157. done
  1158. fi
  1159. json_select ".."
  1160. if json_get_type Status "top_blocked" && [ "${Status}" = "array" ]
  1161. then
  1162. printf "%s\n%s\n%s\n" ":::" "::: Top 10 Blocked Domains" ":::"
  1163. json_select "top_blocked"
  1164. index=1
  1165. while json_get_type Status ${index} && [ "${Status}" = "object" ]
  1166. do
  1167. json_get_values blocked ${index}
  1168. printf " + %-9s::: %s\n" ${blocked}
  1169. index=$((index + 1))
  1170. done
  1171. fi
  1172. if [ -s "${adb_repdir}/adb_report.final" ]
  1173. then
  1174. printf "%s\n%s\n%s\n" ":::" "::: Latest DNS Queries" ":::"
  1175. printf "%-15s%-15s%-45s%-50s%s\n" "Date" "Time" "Client" "Domain" "Answer"
  1176. awk '{printf "%-15s%-15s%-45s%-50s%s\n",$1,$2,$3,$4,$5}' "${adb_repdir}/adb_report.final"
  1177. fi
  1178. else
  1179. printf "%s\n%s\n%s\n" ":::" "::: no reporting data available yet" ":::"
  1180. fi
  1181. fi
  1182. fi
  1183. f_log "debug" "f_report ::: action: ${adb_action}, report: ${adb_report}, search: ${1}, count: ${2}, filter: ${3}, print: ${4}, reputil: ${adb_reputil}, repdir: ${adb_repdir}, repiface: ${adb_repiface}, replisten: ${adb_replisten}, repchunksize: ${adb_repchunksize}, repchunkcnt: ${adb_repchunkcnt}, bg_pid: ${bg_pid}"
  1184. }
  1185. # source required system libraries
  1186. #
  1187. if [ -r "/lib/functions.sh" ] && [ -r "/usr/share/libubox/jshn.sh" ]
  1188. then
  1189. . "/lib/functions.sh"
  1190. . "/usr/share/libubox/jshn.sh"
  1191. else
  1192. f_log "err" "system libraries not found"
  1193. fi
  1194. # handle different adblock actions
  1195. #
  1196. f_envload
  1197. case "${adb_action}" in
  1198. stop)
  1199. f_report "+" "50" "false" "false"
  1200. f_rmdns
  1201. ;;
  1202. restart)
  1203. f_report "+" "50" "false" "false"
  1204. f_rmdns
  1205. f_envcheck
  1206. f_main
  1207. ;;
  1208. suspend)
  1209. f_switch suspend
  1210. ;;
  1211. resume)
  1212. f_switch resume
  1213. ;;
  1214. report)
  1215. f_report "${2}" "${3}" "${4}" "${5}"
  1216. ;;
  1217. query)
  1218. f_query "${2}"
  1219. ;;
  1220. start|reload)
  1221. f_report "+" "50" "false" "false"
  1222. f_envcheck
  1223. f_main
  1224. ;;
  1225. esac