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.

792 lines
22 KiB

  1. #!/bin/sh
  2. # banIP - ban incoming and outgoing ip adresses/subnets via ipset
  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. ban_ver="0.1.3"
  12. ban_sysver="unknown"
  13. ban_enabled=0
  14. ban_automatic="1"
  15. ban_sources=""
  16. ban_iface=""
  17. ban_debug=0
  18. ban_backup=0
  19. ban_backupboot=0
  20. ban_backupdir="/mnt"
  21. ban_maxqueue=4
  22. ban_fetchutil="uclient-fetch"
  23. ban_ip="$(command -v ip)"
  24. ban_ipt="$(command -v iptables)"
  25. ban_ipt_save="$(command -v iptables-save)"
  26. ban_ipt_restore="$(command -v iptables-restore)"
  27. ban_ipt6="$(command -v ip6tables)"
  28. ban_ipt6_save="$(command -v ip6tables-save)"
  29. ban_ipt6_restore="$(command -v ip6tables-restore)"
  30. ban_ipset="$(command -v ipset)"
  31. ban_chain="banIP"
  32. ban_action="${1:-"start"}"
  33. ban_pidfile="/var/run/banip.pid"
  34. ban_rtfile="/tmp/ban_runtime.json"
  35. ban_setcnt=0
  36. ban_cnt=0
  37. ban_rc=0
  38. # load environment
  39. #
  40. f_envload()
  41. {
  42. local sys_call sys_desc sys_model
  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. ban_sysver="${sys_model}, ${sys_desc}"
  51. fi
  52. # parse 'global' and 'extra' section by callback
  53. #
  54. config_cb()
  55. {
  56. local type="${1}"
  57. if [ "${type}" = "banip" ]
  58. then
  59. option_cb()
  60. {
  61. local option="${1}"
  62. local value="${2}"
  63. eval "${option}=\"${value}\""
  64. }
  65. else
  66. reset_cb
  67. fi
  68. }
  69. # parse 'source' typed sections
  70. #
  71. parse_config()
  72. {
  73. local value opt section="${1}" options="ban_src ban_src_6 ban_src_rset ban_src_rset_6 ban_src_settype ban_src_ruletype ban_src_on ban_src_on_6 ban_src_cat"
  74. for opt in ${options}
  75. do
  76. config_get value "${section}" "${opt}"
  77. if [ -n "${value}" ]
  78. then
  79. eval "${opt}_${section}=\"${value}\""
  80. if [ "${opt}" = "ban_src" ]
  81. then
  82. eval "ban_sources=\"${ban_sources} ${section}\""
  83. elif [ "${opt}" = "ban_src_6" ]
  84. then
  85. eval "ban_sources=\"${ban_sources} ${section}_6\""
  86. fi
  87. fi
  88. done
  89. }
  90. # load config
  91. #
  92. config_load banip
  93. config_foreach parse_config source
  94. # create temp directory & files
  95. #
  96. f_temp
  97. # check status
  98. #
  99. if [ "${ban_enabled}" -eq 0 ]
  100. then
  101. f_jsnup disabled
  102. f_ipset destroy
  103. f_rmbackup
  104. f_rmtemp
  105. f_log "info" "banIP is currently disabled, please set ban_enabled to '1' to use this service"
  106. exit 0
  107. fi
  108. }
  109. # check environment
  110. #
  111. f_envcheck()
  112. {
  113. local ssl_lib tmp
  114. # check fetch utility
  115. #
  116. case "${ban_fetchutil}" in
  117. uclient-fetch)
  118. if [ -f "/lib/libustream-ssl.so" ]
  119. then
  120. ban_fetchparm="${ban_fetchparm:-"--timeout=20 --no-check-certificate -O"}"
  121. ssl_lib="libustream-ssl"
  122. else
  123. ban_fetchparm="${ban_fetchparm:-"--timeout=20 -O"}"
  124. fi
  125. ;;
  126. wget)
  127. ban_fetchparm="${ban_fetchparm:-"--no-cache --no-cookies --max-redirect=0 --timeout=20 --no-check-certificate -O"}"
  128. ssl_lib="built-in"
  129. ;;
  130. wget-nossl)
  131. ban_fetchparm="${ban_fetchparm:-"--no-cache --no-cookies --max-redirect=0 --timeout=20 -O"}"
  132. ;;
  133. busybox)
  134. ban_fetchparm="${ban_fetchparm:-"-O"}"
  135. ;;
  136. curl)
  137. ban_fetchparm="${ban_fetchparm:-"--connect-timeout 20 --insecure -o"}"
  138. ssl_lib="built-in"
  139. ;;
  140. aria2c)
  141. ban_fetchparm="${ban_fetchparm:-"--timeout=20 --allow-overwrite=true --auto-file-renaming=false --check-certificate=false -o"}"
  142. ssl_lib="built-in"
  143. ;;
  144. esac
  145. ban_fetchutil="$(command -v "${ban_fetchutil}")"
  146. ban_fetchinfo="${ban_fetchutil:-"-"} (${ssl_lib:-"-"})"
  147. if [ ! -x "${ban_fetchutil}" ] || [ -z "${ban_fetchutil}" ] || [ -z "${ban_fetchparm}" ]
  148. then
  149. f_log "err" "download utility not found, please install 'uclient-fetch' with 'libustream-mbedtls' or the full 'wget' package"
  150. fi
  151. # get wan device and wan subnets
  152. #
  153. if [ "${ban_automatic}" = "1" ]
  154. then
  155. network_find_wan ban_iface
  156. if [ -z "${ban_iface}" ]
  157. then
  158. network_find_wan6 ban_iface
  159. fi
  160. fi
  161. for iface in ${ban_iface}
  162. do
  163. network_get_device tmp "${iface}"
  164. if [ -n "${tmp}" ]
  165. then
  166. ban_dev="${ban_dev} ${tmp}"
  167. else
  168. network_get_physdev tmp "${iface}"
  169. if [ -n "${tmp}" ]
  170. then
  171. ban_dev="${ban_dev} ${tmp}"
  172. fi
  173. fi
  174. network_get_subnets tmp "${iface}"
  175. if [ -n "${tmp}" ]
  176. then
  177. ban_subnets="${ban_subnets} ${tmp}"
  178. fi
  179. network_get_subnets6 tmp "${iface}"
  180. if [ -n "${tmp}" ]
  181. then
  182. ban_subnets6="${ban_subnets6} ${tmp}"
  183. fi
  184. done
  185. if [ -z "${ban_iface}" ] || [ -z "${ban_dev}" ]
  186. then
  187. f_log "err" "wan interface(s)/device(s) (${ban_iface:-"-"}/${ban_dev:-"-"}) not found, please please check your configuration"
  188. fi
  189. ban_dev_all="$(${ban_ip} link show | awk 'BEGIN{FS="[@: ]"}/^[0-9:]/{if(($3!="lo")&&($3!="br-lan")){print $3}}')"
  190. uci_set banip global ban_iface "${ban_iface}"
  191. uci_commit banip
  192. f_jsnup "running"
  193. f_log "info" "start banIP processing (${ban_action})"
  194. }
  195. # create temporary files and directories
  196. #
  197. f_temp()
  198. {
  199. if [ -z "${ban_tmpdir}" ]
  200. then
  201. ban_tmpdir="$(mktemp -p /tmp -d)"
  202. ban_tmpload="$(mktemp -p "${ban_tmpdir}" -tu)"
  203. ban_tmpfile="$(mktemp -p "${ban_tmpdir}" -tu)"
  204. fi
  205. if [ ! -s "${ban_pidfile}" ]
  206. then
  207. printf '%s' "${$}" > "${ban_pidfile}"
  208. fi
  209. }
  210. # remove temporary files and directories
  211. #
  212. f_rmtemp()
  213. {
  214. if [ -d "${ban_tmpdir}" ]
  215. then
  216. rm -rf "${ban_tmpdir}"
  217. fi
  218. > "${ban_pidfile}"
  219. }
  220. # remove backup files
  221. #
  222. f_rmbackup()
  223. {
  224. if [ -d "${ban_backupdir}" ]
  225. then
  226. rm -f "${ban_backupdir}"/banIP.*.gz
  227. fi
  228. }
  229. # iptables rules engine
  230. #
  231. f_iptrule()
  232. {
  233. local rc timeout="-w 5" action="${1}" rule="${2}"
  234. if [ "${src_name##*_}" = "6" ]
  235. then
  236. if [ -x "${ban_ipt6}" ]
  237. then
  238. rc="$("${ban_ipt6}" "${timeout}" -C ${rule} 2>/dev/null; printf '%u' ${?})"
  239. if { [ "${rc}" -ne 0 ] && { [ "${action}" = "-A" ] || [ "${action}" = "-I" ]; } } || \
  240. { [ "${rc}" -eq 0 ] && [ "${action}" = "-D" ]; }
  241. then
  242. "${ban_ipt6}" "${timeout}" "${action}" ${rule}
  243. fi
  244. fi
  245. else
  246. if [ -x "${ban_ipt}" ]
  247. then
  248. rc="$("${ban_ipt}" "${timeout}" -C ${rule} 2>/dev/null; printf '%u' ${?})"
  249. if { [ "${rc}" -ne 0 ] && { [ "${action}" = "-A" ] || [ "${action}" = "-I" ]; } } || \
  250. { [ "${rc}" -eq 0 ] && [ "${action}" = "-D" ]; }
  251. then
  252. "${ban_ipt}" "${timeout}" "${action}" ${rule}
  253. fi
  254. fi
  255. fi
  256. }
  257. # remove/add iptables rules
  258. #
  259. f_iptadd()
  260. {
  261. local rm="${1}" dev
  262. for dev in ${ban_dev_all}
  263. do
  264. f_iptrule "-D" "${ban_chain} -i ${dev} -m conntrack --ctstate NEW -m set --match-set ${src_name} src -j ${target_src}"
  265. f_iptrule "-D" "${ban_chain} -o ${dev} -m conntrack --ctstate NEW -m set --match-set ${src_name} dst -j ${target_dst}"
  266. done
  267. if [ -z "${rm}" ] && [ "${cnt}" -gt 0 ]
  268. then
  269. if [ "${src_ruletype}" != "dst" ]
  270. then
  271. if [ "${src_name##*_}" = "6" ]
  272. then
  273. # dummy, special IPv6 rules
  274. /bin/true
  275. else
  276. f_iptrule "-I" "${wan_input} -p udp --dport 67:68 --sport 67:68 -j RETURN"
  277. fi
  278. f_iptrule "-A" "${wan_input} -j ${ban_chain}"
  279. f_iptrule "-A" "${wan_forward} -j ${ban_chain}"
  280. for dev in ${ban_dev}
  281. do
  282. f_iptrule "${action:-"-A"}" "${ban_chain} -i ${dev} -m conntrack --ctstate NEW -m set --match-set ${src_name} src -j ${target_src}"
  283. done
  284. fi
  285. if [ "${src_ruletype}" != "src" ]
  286. then
  287. if [ "${src_name##*_}" = "6" ]
  288. then
  289. # dummy, special IPv6 rules
  290. /bin/true
  291. else
  292. f_iptrule "-I" "${lan_input} -p udp --dport 67:68 --sport 67:68 -j RETURN"
  293. fi
  294. f_iptrule "-A" "${lan_input} -j ${ban_chain}"
  295. f_iptrule "-A" "${lan_forward} -j ${ban_chain}"
  296. for dev in ${ban_dev}
  297. do
  298. f_iptrule "${action:-"-A"}" "${ban_chain} -o ${dev} -m conntrack --ctstate NEW -m set --match-set ${src_name} dst -j ${target_dst}"
  299. done
  300. fi
  301. else
  302. if [ -x "${ban_ipset}" ] && [ -n "$("${ban_ipset}" -n list "${src_name}" 2>/dev/null)" ]
  303. then
  304. "${ban_ipset}" destroy "${src_name}"
  305. fi
  306. fi
  307. }
  308. # ipset/iptables actions
  309. #
  310. f_ipset()
  311. {
  312. local rc cnt cnt_ip cnt_cidr size source action ruleset ruleset_6 rule timeout="-w 5" mode="${1}"
  313. if [ "${src_name%_6*}" = "whitelist" ]
  314. then
  315. target_src="RETURN"
  316. target_dst="RETURN"
  317. action="-I"
  318. fi
  319. case "${mode}" in
  320. backup)
  321. ban_rc=4
  322. if [ -d "${ban_backupdir}" ]
  323. then
  324. gzip -cf "${tmp_load}" 2>/dev/null > "${ban_backupdir}/banIP.${src_name}.gz"
  325. ban_rc=${?}
  326. fi
  327. f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}, rc: ${ban_rc}"
  328. ;;
  329. restore)
  330. ban_rc=4
  331. if [ -d "${ban_backupdir}" ] && [ -f "${ban_backupdir}/banIP.${src_name}.gz" ]
  332. then
  333. gunzip -cf "${ban_backupdir}/banIP.${src_name}.gz" 2>/dev/null > "${tmp_load}"
  334. ban_rc=${?}
  335. fi
  336. f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}, rc: ${ban_rc}"
  337. ;;
  338. remove)
  339. if [ -d "${ban_backupdir}" ] && [ -f "${ban_backupdir}/banIP.${src_name}.gz" ]
  340. then
  341. rm -f "${ban_backupdir}/banIP.${src_name}.gz"
  342. fi
  343. f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}"
  344. ;;
  345. initial)
  346. if [ -x "${ban_ipt}" ] && [ -z "$("${ban_ipt}" "${timeout}" -nL "${ban_chain}" 2>/dev/null)" ]
  347. then
  348. "${ban_ipt}" "${timeout}" -N "${ban_chain}"
  349. elif [ -x "${ban_ipt}" ]
  350. then
  351. src_name="ruleset"
  352. ruleset="${ban_wan_input_chain:-"input_wan_rule"} ${ban_wan_forward_chain:-"forwarding_wan_rule"} ${ban_lan_input_chain:-"input_lan_rule"} ${ban_lan_forward_chain:-"forwarding_lan_rule"}"
  353. for rule in ${ruleset}
  354. do
  355. f_iptrule "-D" "${rule} -j ${ban_chain}"
  356. done
  357. fi
  358. if [ -x "${ban_ipt6}" ] && [ -z "$("${ban_ipt6}" "${timeout}" -nL "${ban_chain}" 2>/dev/null)" ]
  359. then
  360. "${ban_ipt6}" "${timeout}" -N "${ban_chain}"
  361. elif [ -x "${ban_ipt6}" ]
  362. then
  363. src_name="ruleset_6"
  364. ruleset_6="${ban_wan_input_chain_6:-"input_wan_rule"} ${ban_wan_forward_chain_6:-"forwarding_wan_rule"} ${ban_lan_input_chain_6:-"input_lan_rule"} ${ban_lan_forward_chain_6:-"forwarding_lan_rule"}"
  365. for rule in ${ruleset_6}
  366. do
  367. f_iptrule "-D" "${rule} -j ${ban_chain}"
  368. done
  369. fi
  370. f_log "debug" "f_ipset ::: name: -, mode: ${mode:-"-"}, chain: ${ban_chain:-"-"}, ruleset: ${ruleset:-"-"}, ruleset_6: ${ruleset_6:-"-"}"
  371. ;;
  372. create)
  373. cnt="$(wc -l 2>/dev/null < "${tmp_file}")"
  374. cnt_cidr="$(grep -cF "/" "${tmp_file}")"
  375. cnt_ip="$((cnt-cnt_cidr))"
  376. size="$((cnt/4))"
  377. if [ "${cnt}" -gt 0 ]
  378. then
  379. if [ -x "${ban_ipset}" ] && [ -z "$("${ban_ipset}" -n list "${src_name}" 2>/dev/null)" ]
  380. then
  381. "${ban_ipset}" create "${src_name}" hash:"${src_settype}" hashsize "${size}" maxelem 262144 family "${src_setipv}" counters
  382. else
  383. "${ban_ipset}" flush "${src_name}"
  384. fi
  385. "${ban_ipset}" -! restore < "${tmp_file}"
  386. printf "%s\n" "1" > "${tmp_set}"
  387. printf "%s\n" "${cnt}" > "${tmp_cnt}"
  388. fi
  389. f_iptadd
  390. end_ts="$(date +%s)"
  391. f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}, settype: ${src_settype:-"-"}, setipv: ${src_setipv:-"-"}, ruletype: ${src_ruletype:-"-"}, count(sum/ip/cidr): ${cnt:-0}/${cnt_ip:-0}/${cnt_cidr:-0}, time(s): $((end_ts-start_ts))"
  392. ;;
  393. refresh)
  394. if [ -x "${ban_ipset}" ] && [ -n "$("${ban_ipset}" -n list "${src_name}" 2>/dev/null)" ]
  395. then
  396. "${ban_ipset}" save "${src_name}" > "${tmp_file}"
  397. if [ -s "${tmp_file}" ]
  398. then
  399. cnt="$(($(wc -l 2>/dev/null < "${tmp_file}")-1))"
  400. cnt_cidr="$(grep -cF "/" "${tmp_file}")"
  401. cnt_ip="$((cnt-cnt_cidr))"
  402. printf "%s\n" "1" > "${tmp_set}"
  403. printf "%s\n" "${cnt}" > "${tmp_cnt}"
  404. fi
  405. f_iptadd
  406. fi
  407. end_ts="$(date +%s)"
  408. f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}, count: ${cnt:-0}/${cnt_ip:-0}/${cnt_cidr:-0}, time(s): $((end_ts-start_ts))"
  409. ;;
  410. flush)
  411. f_iptadd "remove"
  412. if [ -x "${ban_ipset}" ] && [ -n "$("${ban_ipset}" -n list "${src_name}" 2>/dev/null)" ]
  413. then
  414. "${ban_ipset}" flush "${src_name}"
  415. "${ban_ipset}" destroy "${src_name}"
  416. fi
  417. f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}"
  418. ;;
  419. destroy)
  420. if [ -x "${ban_ipt}" ] && [ -x "${ban_ipt_save}" ] && [ -x "${ban_ipt_restore}" ] && \
  421. [ -n "$("${ban_ipt}" "${timeout}" -nL "${ban_chain}" 2>/dev/null)" ]
  422. then
  423. "${ban_ipt_save}" | grep -v -- "-j ${ban_chain}" | "${ban_ipt_restore}"
  424. "${ban_ipt}" "${timeout}" -F "${ban_chain}"
  425. "${ban_ipt}" "${timeout}" -X "${ban_chain}"
  426. fi
  427. if [ -x "${ban_ipt6}" ] && [ -x "${ban_ipt6_save}" ] && [ -x "${ban_ipt6_restore}" ] && \
  428. [ -n "$("${ban_ipt6}" "${timeout}" -nL "${ban_chain}" 2>/dev/null)" ]
  429. then
  430. "${ban_ipt6_save}" | grep -v -- "-j ${ban_chain}" | "${ban_ipt6_restore}"
  431. "${ban_ipt6}" "${timeout}" -F "${ban_chain}"
  432. "${ban_ipt6}" "${timeout}" -X "${ban_chain}"
  433. fi
  434. for source in ${ban_sources}
  435. do
  436. if [ -x "${ban_ipset}" ] && [ -n "$("${ban_ipset}" -n list "${source}" 2>/dev/null)" ]
  437. then
  438. "${ban_ipset}" destroy "${source}"
  439. fi
  440. done
  441. f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}"
  442. ;;
  443. esac
  444. }
  445. # write to syslog
  446. #
  447. f_log()
  448. {
  449. local class="${1}" log_msg="${2}"
  450. if [ -n "${log_msg}" ] && { [ "${class}" != "debug" ] || [ "${ban_debug}" -eq 1 ]; }
  451. then
  452. logger -p "${class}" -t "banIP-[${ban_ver}]" "${log_msg}"
  453. if [ "${class}" = "err" ]
  454. then
  455. f_jsnup error
  456. f_ipset destroy
  457. f_rmbackup
  458. f_rmtemp
  459. logger -p "${class}" -t "banIP-[${ban_ver}]" "Please also check 'https://github.com/openwrt/packages/blob/master/net/banip/files/README.md'"
  460. exit 1
  461. fi
  462. fi
  463. }
  464. # main function for banIP processing
  465. #
  466. f_main()
  467. {
  468. local pid pid_list start_ts end_ts ip tmp_raw tmp_cnt tmp_load tmp_file mem_total mem_free cnt=1
  469. local src_name src_on src_url src_rset src_setipv src_settype src_ruletype src_cat src_log src_addon
  470. local wan_input wan_forward lan_input lan_forward target_src target_dst log_content
  471. log_content="$(logread -e "dropbear")"
  472. mem_total="$(awk '/^MemTotal/ {print int($2/1000)}' "/proc/meminfo" 2>/dev/null)"
  473. mem_free="$(awk '/^MemFree/ {print int($2/1000)}' "/proc/meminfo" 2>/dev/null)"
  474. f_log "debug" "f_main ::: fetch_util: ${ban_fetchinfo:-"-"}, fetch_parm: ${ban_fetchparm:-"-"}, interface(s): ${ban_iface:-"-"}, device(s): ${ban_dev:-"-"}, all_devices: ${ban_dev_all:-"-"}, backup: ${ban_backup:-"-"}, backup_boot: ${ban_backupboot:-"-"}, backup_dir: ${ban_backupdir:-"-"}, mem_total: ${mem_total:-0}, mem_free: ${mem_free:-0}, max_queue: ${ban_maxqueue}"
  475. f_ipset initial
  476. # main loop
  477. #
  478. for src_name in ${ban_sources}
  479. do
  480. unset src_on
  481. if [ "${src_name##*_}" = "6" ]
  482. then
  483. if [ -x "${ban_ipt6}" ]
  484. then
  485. src_on="$(eval printf '%s' \"\${ban_src_on_6_${src_name%_6*}\}\")"
  486. src_url="$(eval printf '%s' \"\${ban_src_6_${src_name%_6*}\}\")"
  487. src_rset="$(eval printf '%s' \"\${ban_src_rset_6_${src_name%_6*}\}\")"
  488. src_setipv="inet6"
  489. wan_input="${ban_wan_input_chain_6:-"input_wan_rule"}"
  490. wan_forward="${ban_wan_forward_chain_6:-"forwarding_wan_rule"}"
  491. lan_input="${ban_lan_input_chain_6:-"input_lan_rule"}"
  492. lan_forward="${ban_lan_forward_chain_6:-"forwarding_lan_rule"}"
  493. target_src="${ban_target_src_6:-"DROP"}"
  494. target_dst="${ban_target_dst_6:-"REJECT"}"
  495. fi
  496. else
  497. if [ -x "${ban_ipt}" ]
  498. then
  499. src_on="$(eval printf '%s' \"\${ban_src_on_${src_name}\}\")"
  500. src_url="$(eval printf '%s' \"\${ban_src_${src_name}\}\")"
  501. src_rset="$(eval printf '%s' \"\${ban_src_rset_${src_name}\}\")"
  502. src_setipv="inet"
  503. wan_input="${ban_wan_input_chain:-"input_wan_rule"}"
  504. wan_forward="${ban_wan_forward_chain:-"forwarding_wan_rule"}"
  505. lan_input="${ban_lan_input_chain:-"input_lan_rule"}"
  506. lan_forward="${ban_lan_forward_chain:-"forwarding_lan_rule"}"
  507. target_src="${ban_target_src:-"DROP"}"
  508. target_dst="${ban_target_dst:-"REJECT"}"
  509. fi
  510. fi
  511. src_settype="$(eval printf '%s' \"\${ban_src_settype_${src_name%_6*}\}\")"
  512. src_ruletype="$(eval printf '%s' \"\${ban_src_ruletype_${src_name%_6*}\}\")"
  513. src_cat="$(eval printf '%s' \"\${ban_src_cat_${src_name%_6*}\}\")"
  514. src_addon=""
  515. tmp_load="${ban_tmpload}.${src_name}"
  516. tmp_file="${ban_tmpfile}.${src_name}"
  517. tmp_raw="${tmp_load}.raw"
  518. tmp_cnt="${tmp_file}.cnt"
  519. tmp_set="${tmp_file}.setcnt"
  520. # basic pre-checks
  521. #
  522. f_log "debug" "f_main ::: name: ${src_name}, src_on: ${src_on:-"-"}"
  523. if [ -z "${src_on}" ] || [ "${src_on}" != "1" ] || [ -z "${src_url}" ] || \
  524. [ -z "${src_rset}" ] || [ -z "${src_settype}" ] || [ -z "${src_ruletype}" ]
  525. then
  526. f_ipset flush
  527. f_ipset remove
  528. continue
  529. elif [ "${ban_action}" = "refresh" ]
  530. then
  531. f_ipset refresh
  532. continue
  533. fi
  534. # download queue processing
  535. #
  536. (
  537. start_ts="$(date +%s)"
  538. if [ ! -f "${src_url}" ] && [ ${ban_backup} -eq 1 ] && [ ${ban_backupboot} -eq 1 ] && [ "${ban_action}" = "start" ]
  539. then
  540. f_ipset restore
  541. fi
  542. if [ ${ban_rc} -ne 0 ] || [ ! -s "${tmp_load}" ]
  543. then
  544. if [ -f "${src_url}" ]
  545. then
  546. src_log="$(cat "${src_url}" 2>/dev/null > "${tmp_load}")"
  547. ban_rc=${?}
  548. case "${src_name}" in
  549. whitelist)
  550. src_addon="${ban_subnets}"
  551. ;;
  552. whitelist_6)
  553. src_addon="${ban_subnets6}"
  554. ;;
  555. blacklist)
  556. pid_list="$(printf "%s\n" "${log_content}" | grep -F "Exit before auth" | awk 'match($0,/(\[[0-9]+\])/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
  557. for pid in ${pid_list}
  558. do
  559. src_addon="${src_addon} $(printf "%s\n" "${log_content}" | grep -F "${pid}" | awk 'match($0,/([0-9]{1,3}\.){3}[0-9]{1,3}/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
  560. done
  561. ;;
  562. blacklist_6)
  563. pid_list="$(printf "%s\n" "${log_content}" | grep -F "Exit before auth" | awk 'match($0,/(\[[0-9]+\])/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
  564. for pid in ${pid_list}
  565. do
  566. src_addon="${src_addon} $(printf "%s\n" "${log_content}" | grep -F "${pid}" | awk 'match($0,/([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
  567. done
  568. ;;
  569. esac
  570. for ip in ${src_addon}
  571. do
  572. if [ -z "$(grep -F "${ip}" "${src_url}")" ]
  573. then
  574. printf '%s\n' "${ip}" >> "${tmp_load}"
  575. printf '%s\n' "${ip}" >> "${src_url}"
  576. fi
  577. done
  578. elif [ -n "${src_cat}" ]
  579. then
  580. if [ "${src_cat//[0-9]/}" != "${src_cat}" ]
  581. then
  582. for as in ${src_cat}
  583. do
  584. src_log="$("${ban_fetchutil}" ${ban_fetchparm} "${tmp_raw}" "${src_url}AS${as}" 2>&1)"
  585. ban_rc=${?}
  586. if [ ${ban_rc} -eq 0 ]
  587. then
  588. jsonfilter -i "${tmp_raw}" -e '@.data.prefixes.*.prefix' 2>/dev/null >> "${tmp_load}"
  589. else
  590. break
  591. fi
  592. done
  593. if [ ${ban_rc} -eq 0 ] && [ ${ban_backup} -eq 1 ]
  594. then
  595. f_ipset backup
  596. elif [ ${ban_backup} -eq 1 ]
  597. then
  598. f_ipset restore
  599. fi
  600. else
  601. for co in ${src_cat}
  602. do
  603. src_log="$("${ban_fetchutil}" ${ban_fetchparm} "${tmp_raw}" "${src_url}${co}&v4_format=prefix" 2>&1)"
  604. ban_rc=${?}
  605. if [ ${ban_rc} -eq 0 ]
  606. then
  607. if [ "${src_name##*_}" = "6" ]
  608. then
  609. jsonfilter -i "${tmp_raw}" -e '@.data.resources.ipv6.*' 2>/dev/null >> "${tmp_load}"
  610. else
  611. jsonfilter -i "${tmp_raw}" -e '@.data.resources.ipv4.*' 2>/dev/null >> "${tmp_load}"
  612. fi
  613. else
  614. break
  615. fi
  616. done
  617. if [ ${ban_rc} -eq 0 ] && [ ${ban_backup} -eq 1 ]
  618. then
  619. f_ipset backup
  620. elif [ ${ban_backup} -eq 1 ]
  621. then
  622. f_ipset restore
  623. fi
  624. fi
  625. else
  626. src_log="$("${ban_fetchutil}" ${ban_fetchparm} "${tmp_raw}" "${src_url}" 2>&1)"
  627. ban_rc=${?}
  628. if [ ${ban_rc} -eq 0 ]
  629. then
  630. zcat "${tmp_raw}" 2>/dev/null > "${tmp_load}"
  631. ban_rc=${?}
  632. if [ ${ban_rc} -ne 0 ]
  633. then
  634. mv -f "${tmp_raw}" "${tmp_load}"
  635. ban_rc=${?}
  636. fi
  637. if [ ${ban_rc} -eq 0 ] && [ ${ban_backup} -eq 1 ]
  638. then
  639. f_ipset backup
  640. fi
  641. elif [ ${ban_backup} -eq 1 ]
  642. then
  643. f_ipset restore
  644. fi
  645. fi
  646. fi
  647. if [ ${ban_rc} -eq 0 ]
  648. then
  649. awk "${src_rset}" "${tmp_load}" 2>/dev/null > "${tmp_file}"
  650. ban_rc=${?}
  651. if [ ${ban_rc} -eq 0 ]
  652. then
  653. f_ipset create
  654. else
  655. f_ipset refresh
  656. fi
  657. else
  658. src_log="$(printf '%s' "${src_log}" | awk '{ORS=" ";print $0}')"
  659. f_log "debug" "f_main ::: name: ${src_name}, url: ${src_url}, rc: ${ban_rc}, log: ${src_log:-"-"}"
  660. f_ipset refresh
  661. fi
  662. ) &
  663. hold="$((cnt%ban_maxqueue))"
  664. if [ "${hold}" -eq 0 ]
  665. then
  666. wait
  667. fi
  668. cnt="$((cnt+1))"
  669. done
  670. wait
  671. if [ "${ban_rc}" -eq 0 ]
  672. then
  673. for cnt in $(cat "${ban_tmpfile}".*.setcnt 2>/dev/null)
  674. do
  675. ban_setcnt="$((ban_setcnt+cnt))"
  676. done
  677. for cnt in $(cat "${ban_tmpfile}".*.cnt 2>/dev/null)
  678. do
  679. ban_cnt="$((ban_cnt+cnt))"
  680. done
  681. f_log "info" "${ban_setcnt} IPSets with overall ${ban_cnt} IPs/Prefixes loaded successfully (${ban_sysver})"
  682. fi
  683. f_jsnup
  684. f_rmtemp
  685. exit ${ban_rc}
  686. }
  687. # update runtime information
  688. #
  689. f_jsnup()
  690. {
  691. local rundate mode status="${1:-"enabled"}"
  692. rundate="$(/bin/date "+%d.%m.%Y %H:%M:%S")"
  693. mode="normal mode"
  694. ban_cntinfo="${ban_setcnt} IPSets with overall ${ban_cnt} IPs/Prefixes"
  695. if [ "${ban_backupboot}" -eq 1 ]
  696. then
  697. mode="backup mode"
  698. fi
  699. > "${ban_rtfile}"
  700. json_load_file "${ban_rtfile}" >/dev/null 2>&1
  701. json_init
  702. json_add_object "data"
  703. json_add_string "status" "${status}"
  704. json_add_string "version" "${ban_ver}"
  705. json_add_string "fetch_info" "${ban_fetchinfo:-"-"}"
  706. json_add_string "ipset_info" "${ban_cntinfo:-"-"} (${mode})"
  707. json_add_string "last_run" "${rundate:-"-"}"
  708. json_add_string "system" "${ban_sysver}"
  709. json_close_object
  710. json_dump > "${ban_rtfile}"
  711. f_log "debug" "f_jsnup ::: status: ${status}, setcnt: ${ban_setcnt}, cnt: ${ban_cnt}"
  712. }
  713. # source required system libraries
  714. #
  715. if [ -r "/lib/functions.sh" ] && [ -r "/lib/functions/network.sh" ] && [ -r "/usr/share/libubox/jshn.sh" ]
  716. then
  717. . "/lib/functions.sh"
  718. . "/lib/functions/network.sh"
  719. . "/usr/share/libubox/jshn.sh"
  720. else
  721. f_log "err" "system libraries not found"
  722. fi
  723. # handle different banIP actions
  724. #
  725. f_envload
  726. case "${ban_action}" in
  727. stop)
  728. f_jsnup stopped
  729. f_ipset destroy
  730. f_rmbackup
  731. f_rmtemp
  732. ;;
  733. start|restart|reload|refresh)
  734. f_envcheck
  735. f_main
  736. ;;
  737. esac