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.

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