adblock.sh 29 KB

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