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.

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