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.

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