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.

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