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.

275 lines
9.8 KiB

  1. #!/bin/sh
  2. # dns based ad/abuse domain blocking script
  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. # prepare environment
  8. #
  9. adb_pid="${$}"
  10. adb_pidfile="/var/run/adblock.pid"
  11. adb_scriptdir="${0%/*}"
  12. if [ -r "${adb_pidfile}" ]
  13. then
  14. rc=255
  15. logger -s -t "adblock[${adb_pid}] error" "adblock service already running ($(cat ${adb_pidfile}))"
  16. exit ${rc}
  17. else
  18. printf "${adb_pid}" > "${adb_pidfile}"
  19. if [ -r "${adb_scriptdir}/adblock-helper.sh" ]
  20. then
  21. . "${adb_scriptdir}/adblock-helper.sh"
  22. f_envload
  23. else
  24. rc=254
  25. logger -s -t "adblock[${adb_pid}] error" "adblock function library not found"
  26. rm -f "${adb_pidfile}"
  27. exit ${rc}
  28. fi
  29. fi
  30. # call trap function on error signals (HUP, INT, QUIT, BUS, SEGV, TERM)
  31. #
  32. trap "rc=250; f_log 'error signal received/trapped'; f_exit" 1 2 3 10 11 15
  33. # check environment
  34. #
  35. f_envcheck
  36. # main loop for all block list sources
  37. #
  38. for src_name in ${adb_sources}
  39. do
  40. # check disabled sources
  41. #
  42. eval "enabled=\"\${enabled_${src_name}}\""
  43. if [ "${enabled}" = "0" ]
  44. then
  45. if [ -r "${adb_dnsdir}/${adb_dnsprefix}.${src_name}" ]
  46. then
  47. rm -f "${adb_dnsdir}/${adb_dnsprefix}.${src_name}"
  48. if [ "${backup_ok}" = "true" ] && [ -r "${adb_dir_backup}/${adb_dnsprefix}.${src_name}.gz" ]
  49. then
  50. rm -f "${adb_dir_backup}/${adb_dnsprefix}.${src_name}.gz"
  51. fi
  52. rm_done="true"
  53. f_log "=> disabled source '${src_name}' removed"
  54. fi
  55. "${adb_uci}" -q delete "adblock.${src_name}.adb_src_count"
  56. "${adb_uci}" -q delete "adblock.${src_name}.adb_src_timestamp"
  57. continue
  58. fi
  59. f_log "=> processing source '${src_name}'"
  60. eval "url=\"\${adb_src_${src_name}}\""
  61. eval "src_rset=\"\${adb_src_rset_${src_name}}\""
  62. eval "list_time=\"\${CONFIG_${src_name}_adb_src_timestamp}\""
  63. adb_dnsfile="${adb_dnsdir}/${adb_dnsprefix}.${src_name}"
  64. # check 'url' and 'src_rset' values
  65. #
  66. if [ -z "${url}" ] || [ -z "${src_rset}" ]
  67. then
  68. "${adb_uci}" -q set "adblock.${src_name}.adb_src_timestamp=broken config"
  69. f_log " broken source configuration, skipped"
  70. continue
  71. fi
  72. # download only block list with newer/updated timestamp
  73. #
  74. if [ "${src_name}" = "blacklist" ]
  75. then
  76. url_time="$(date -r "${url}")"
  77. else
  78. url_time="$(${adb_fetch} ${fetch_parm} ${response_parm} "${url}" 2>&1 | awk '$0 ~ /Last-Modified/ {printf substr($0,18)}')"
  79. fi
  80. if [ -z "${url_time}" ]
  81. then
  82. url_time="$(date)"
  83. f_log " no online timestamp"
  84. fi
  85. if [ -z "${list_time}" ] || [ "${list_time}" != "${url_time}" ] || [ ! -r "${adb_dnsfile}" ] ||\
  86. ([ "${backup_ok}" = "true" ] && [ ! -r "${adb_dir_backup}/${adb_dnsprefix}.${src_name}.gz" ])
  87. then
  88. if [ "${src_name}" = "blacklist" ]
  89. then
  90. tmp_domains="$(strings -n 1 "${url}")"
  91. elif [ "${src_name}" = "shalla" ]
  92. then
  93. shalla_archive="${adb_tmpdir}/shallalist.tar.gz"
  94. shalla_file="${adb_tmpdir}/shallalist.txt"
  95. "${adb_fetch}" ${fetch_parm} -O "${shalla_archive}" "${url}"
  96. rc=${?}
  97. if [ $((rc)) -eq 0 ]
  98. then
  99. > "${shalla_file}"
  100. for category in ${adb_src_cat_shalla}
  101. do
  102. tar -xOzf "${shalla_archive}" BL/${category}/domains >> "${shalla_file}"
  103. rc=${?}
  104. if [ $((rc)) -ne 0 ]
  105. then
  106. f_log " archive extraction failed (${category})"
  107. break
  108. fi
  109. done
  110. tmp_domains="$(strings -n 1 "${shalla_file}")"
  111. rm -rf "${adb_tmpdir}/BL"
  112. rm -f "${shalla_archive}"
  113. rm -f "${shalla_file}"
  114. fi
  115. else
  116. tmp_domains="$(${adb_fetch} ${fetch_parm} -O- "${url}" | strings -n 1)"
  117. fi
  118. rc=${?}
  119. else
  120. f_log " source doesn't change, skipped"
  121. continue
  122. fi
  123. # check download result and prepare domain output, backup/restore if needed
  124. #
  125. if [ $((rc)) -eq 0 ] && [ -n "${tmp_domains}" ]
  126. then
  127. count="$(printf "%s\n" "${tmp_domains}" | awk "${src_rset}" | tee "${adb_tmpfile}" | wc -l)"
  128. "${adb_uci}" -q set "adblock.${src_name}.adb_src_timestamp=${url_time}"
  129. if [ "${backup_ok}" = "true" ]
  130. then
  131. gzip -cf "${adb_tmpfile}" > "${adb_dir_backup}/${adb_dnsprefix}.${src_name}.gz"
  132. fi
  133. f_log " source download finished (${count} entries)"
  134. unset tmp_domains
  135. elif [ $((rc)) -eq 0 ] && [ -z "${tmp_domains}" ]
  136. then
  137. if [ "${backup_ok}" = "true" ] && [ -r "${adb_dir_backup}/${adb_dnsprefix}.${src_name}.gz" ]
  138. then
  139. gunzip -cf "${adb_dir_backup}/${adb_dnsprefix}.${src_name}.gz" > "${adb_tmpfile}"
  140. count="$(wc -l < "${adb_tmpfile}")"
  141. "${adb_uci}" -q set "adblock.${src_name}.adb_src_timestamp=list restored"
  142. f_log " empty source download, restored (${count} entries)"
  143. else
  144. if [ -r "${adb_dnsdir}/${adb_dnsprefix}.${src_name}" ]
  145. then
  146. rm -f "${adb_dnsdir}/${adb_dnsprefix}.${src_name}"
  147. rm_done="true"
  148. fi
  149. "${adb_uci}" -q delete "adblock.${src_name}.adb_src_count"
  150. "${adb_uci}" -q set "adblock.${src_name}.adb_src_timestamp=empty download"
  151. f_log " empty source download, skipped"
  152. continue
  153. fi
  154. else
  155. rc=0
  156. if [ "${backup_ok}" = "true" ] && [ -r "${adb_dir_backup}/${adb_dnsprefix}.${src_name}.gz" ]
  157. then
  158. gunzip -cf "${adb_dir_backup}/${adb_dnsprefix}.${src_name}.gz" > "${adb_tmpfile}"
  159. count="$(wc -l < "${adb_tmpfile}")"
  160. "${adb_uci}" -q set "adblock.${src_name}.adb_src_timestamp=list restored"
  161. f_log " source download failed, restored (${count} entries)"
  162. else
  163. if [ -r "${adb_dnsdir}/${adb_dnsprefix}.${src_name}" ]
  164. then
  165. rm -f "${adb_dnsdir}/${adb_dnsprefix}.${src_name}"
  166. rm_done="true"
  167. fi
  168. "${adb_uci}" -q delete "adblock.${src_name}.adb_src_count"
  169. "${adb_uci}" -q set "adblock.${src_name}.adb_src_timestamp=download failed"
  170. f_log " source download failed, skipped"
  171. continue
  172. fi
  173. fi
  174. # remove whitelist domains, sort domains and make them unique,
  175. # rewrite ad/abuse domain information to separate dnsmasq files
  176. #
  177. if [ $((count)) -gt 0 ] && [ -n "${adb_tmpfile}" ]
  178. then
  179. if [ -s "${adb_tmpdir}/tmp.whitelist" ]
  180. then
  181. grep -vf "${adb_tmpdir}/tmp.whitelist" "${adb_tmpfile}" | sort -u | eval "${adb_dnsformat}" > "${adb_dnsfile}"
  182. else
  183. sort -u "${adb_tmpfile}" | eval "${adb_dnsformat}" > "${adb_dnsfile}"
  184. fi
  185. rc=${?}
  186. if [ $((rc)) -eq 0 ]
  187. then
  188. rev_done="true"
  189. f_log " domain merging finished"
  190. else
  191. rc=0
  192. rm -f "${adb_dnsfile}"
  193. if [ "${backup_ok}" = "true" ] && [ -r "${adb_dir_backup}/${adb_dnsprefix}.${src_name}.gz" ]
  194. then
  195. rm -f "${adb_dir_backup}/${adb_dnsprefix}.${src_name}.gz"
  196. fi
  197. "${adb_uci}" -q delete "adblock.${src_name}.adb_src_count"
  198. "${adb_uci}" -q set "adblock.${src_name}.adb_src_timestamp=domain merging failed"
  199. f_log " domain merging failed, skipped"
  200. continue
  201. fi
  202. else
  203. rm -f "${adb_dnsfile}"
  204. if [ "${backup_ok}" = "true" ] && [ -r "${adb_dir_backup}/${adb_dnsprefix}.${src_name}.gz" ]
  205. then
  206. rm -f "${adb_dir_backup}/${adb_dnsprefix}.${src_name}.gz"
  207. fi
  208. "${adb_uci}" -q delete "adblock.${src_name}.adb_src_count"
  209. "${adb_uci}" -q set "adblock.${src_name}.adb_src_timestamp=empty domain input"
  210. f_log " empty domain input, skipped"
  211. continue
  212. fi
  213. done
  214. # overall sort, make block list entries unique
  215. #
  216. if [ "${rev_done}" = "true" ] && [ "${mem_ok}" = "true" ]
  217. then
  218. f_log "remove duplicates in separate block lists"
  219. for list in $(ls -ASr "${adb_dnsdir}/${adb_dnsprefix}"*)
  220. do
  221. list="${list/*./}"
  222. if [ -s "${adb_tmpdir}/blocklist.overall" ]
  223. then
  224. sort "${adb_tmpdir}/blocklist.overall" "${adb_tmpdir}/blocklist.overall" "${adb_dnsdir}/${adb_dnsprefix}.${list}" | uniq -u > "${adb_tmpdir}/tmp.blocklist"
  225. cat "${adb_tmpdir}/tmp.blocklist" > "${adb_dnsdir}/${adb_dnsprefix}.${list}"
  226. fi
  227. cat "${adb_dnsdir}/${adb_dnsprefix}.${list}" >> "${adb_tmpdir}/blocklist.overall"
  228. done
  229. fi
  230. # restart & check dnsmasq with generated set of block lists
  231. #
  232. if [ "${rev_done}" = "true" ] || [ "${rm_done}" = "true" ] || [ -n "${mv_done}" ]
  233. then
  234. "${adb_uci}" -q delete "adblock.global.adb_dnstoggle"
  235. /etc/init.d/dnsmasq restart
  236. sleep 1
  237. check="$(pgrep -f "dnsmasq")"
  238. if [ -n "${check}" ]
  239. then
  240. f_cntconfig
  241. f_log "block lists with overall ${adb_count} domains loaded"
  242. else
  243. f_rmdns
  244. sleep 1
  245. check="$(pgrep -f "dnsmasq")"
  246. if [ -n "${check}" ]
  247. then
  248. f_log "dnsmasq restart without block lists succeeded, please check your configuration"
  249. else
  250. f_log "dnsmasq restart without block lists failed, please check your configuration"
  251. fi
  252. rc=100
  253. f_exit
  254. fi
  255. else
  256. f_cntconfig
  257. f_log "block lists with overall ${adb_count} domains are still valid, no update required"
  258. fi
  259. # remove temporary files and exit
  260. #
  261. f_exit