├── etc ├── antiscan │ ├── ascn_custom_blacklist.txt │ ├── ascn_custom_exclude.txt │ ├── ascn_custom_whitelist.txt │ ├── ascn_crontab.conf │ ├── ascn.conf │ └── scripts │ │ ├── log.sh │ │ ├── iptables.sh │ │ ├── show_data.sh │ │ ├── config.sh │ │ ├── geo.sh │ │ └── ipsets.sh ├── ndm │ └── netfilter.d │ │ └── 099-ascn.sh └── init.d │ └── S99ascn ├── ipk ├── prerm ├── postrm ├── conffiles ├── postinst └── preinst ├── Makefile ├── LICENSE ├── repository.mk ├── package.mk ├── install.sh ├── .github └── workflows │ └── build.yml └── README.md /etc/antiscan/ascn_custom_blacklist.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /etc/antiscan/ascn_custom_exclude.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /etc/antiscan/ascn_custom_whitelist.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ipk/prerm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ANTISCAN_LINK="/opt/bin/antiscan" 3 | /opt/etc/init.d/S99ascn stop 4 | if [ -L "$ANTISCAN_LINK" ]; then 5 | rm "$ANTISCAN_LINK" 6 | fi 7 | -------------------------------------------------------------------------------- /ipk/postrm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | crontab_bin="/opt/bin/crontab" 3 | if [ -f "$crontab_bin" ]; then 4 | crontab -l | sed '/S99ascn/d' | crontab - 5 | else 6 | echo "crontab не найден! У вас не установлен cron?" 7 | fi 8 | -------------------------------------------------------------------------------- /ipk/conffiles: -------------------------------------------------------------------------------- 1 | /opt/etc/antiscan/ascn.conf 2 | /opt/etc/antiscan/ascn_crontab.conf 3 | /opt/etc/antiscan/ascn_custom_blacklist.txt 4 | /opt/etc/antiscan/ascn_custom_exclude.txt 5 | /opt/etc/antiscan/ascn_custom_whitelist.txt 6 | -------------------------------------------------------------------------------- /etc/ndm/netfilter.d/099-ascn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ASCN_TEMP_FILE="/tmp/ascn.run" 4 | 5 | [ "$type" == "ip6tables" ] && exit 6 | [ "$table" != "filter" ] && exit 7 | [ ! -f "$ASCN_TEMP_FILE" ] && exit 8 | 9 | /opt/etc/init.d/S99ascn update_rules 2>/dev/null -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | VERSION := $(shell sed -n 's/^ASCN_VERSION="\([^"]*\)"$$/\1/p' etc/init.d/S99ascn) 3 | 4 | include package.mk 5 | include repository.mk 6 | 7 | .DEFAULT_GOAL := package 8 | 9 | clean: 10 | rm -rf out/$(BUILD_DIR) 11 | -------------------------------------------------------------------------------- /etc/antiscan/ascn_crontab.conf: -------------------------------------------------------------------------------- 1 | */1 * * * * /opt/etc/init.d/S99ascn read_candidates & 2 | */2 * * * * /opt/etc/init.d/S99ascn read_ndm_ipsets & 3 | 0 0 */5 * * /opt/etc/init.d/S99ascn save_ipsets & 4 | 0 5 */15 * * /opt/etc/init.d/S99ascn update_ipsets geo & 5 | -------------------------------------------------------------------------------- /etc/antiscan/ascn.conf: -------------------------------------------------------------------------------- 1 | ISP_INTERFACES="eth3" 2 | PORTS="22,80,443" 3 | PORTS_FORWARDED="22,80,443" 4 | 5 | ENABLE_HONEYPOT=0 6 | HONEYPOT_PORTS="" 7 | HONEYPOT_BANTIME=864000 8 | 9 | ENABLE_IPS_BAN=1 10 | RULES_MASK="255.255.255.255" 11 | RECENT_CONNECTIONS_TIME=30 12 | RECENT_CONNECTIONS_HITCOUNT=15 13 | RECENT_CONNECTIONS_LIMIT=20 14 | RECENT_CONNECTIONS_BANTIME=864000 15 | 16 | DIFFERENT_IP_CANDIDATES_STORAGETIME=864000 17 | DIFFERENT_IP_THRESHOLD=5 18 | SUBNETS_BANTIME=864000 19 | 20 | IPSETS_DIRECTORY="" 21 | SAVE_IPSETS=0 22 | SAVE_ON_EXIT=0 23 | USE_CUSTOM_EXCLUDE_LIST=0 24 | CUSTOM_LISTS_BLOCK_MODE=0 25 | GEOBLOCK_MODE=0 26 | GEOBLOCK_COUNTRIES="" 27 | GEO_EXCLUDE_COUNTRIES="" 28 | 29 | READ_NDM_LOCKOUT_IPSETS=0 30 | LOCKOUT_IPSET_BANTIME=864000 -------------------------------------------------------------------------------- /etc/antiscan/scripts/log.sh: -------------------------------------------------------------------------------- 1 | RED_COLOR="\033[1;31m" 2 | GREEN_COLOR="\033[1;32m" 3 | YELLOW_COLOR="\033[1;33m" 4 | BOLD_TEXT="\033[1m" 5 | NO_STYLE="\033[0m" 6 | 7 | print_message() { 8 | local msg_type="$1" 9 | local msg_text="$2" 10 | if [ "$msg_type" != "console" ]; then 11 | logger -p "${msg_type}" -t "Antiscan" "${msg_text}" 12 | fi 13 | case $msg_type in 14 | error) 15 | [ -z "$3" ] && printf "${RED_COLOR}${msg_text}${NO_STYLE}\n" >&2 16 | ;; 17 | notice) 18 | [ -z "$3" ] && printf "${BOLD_TEXT}${msg_text}${NO_STYLE}\n" 19 | ;; 20 | warning) 21 | [ "$3" == "1" ] && printf "${YELLOW_COLOR}${msg_text}${NO_STYLE}\n" >&2 22 | ;; 23 | console) 24 | printf "${BOLD_TEXT}${msg_text}${NO_STYLE}\n" 25 | ;; 26 | esac 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 dimon27254 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ipk/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ANTISCAN_LINK="/opt/bin/antiscan" 3 | ANTISCAN_DIR="/opt/etc/antiscan" 4 | CONFIG_FILE="$ANTISCAN_DIR/ascn.conf" 5 | OLD_CONFIG_FILES="/opt/etc/ascn.conf-opkg /opt/etc/ascn.conf-opkg.backup" 6 | BOLD_TEXT="\033[1m" 7 | NO_STYLE="\033[0m" 8 | 9 | if [ ! -L "$ANTISCAN_LINK" ]; then 10 | ln -s /opt/etc/init.d/S99ascn "$ANTISCAN_LINK" 11 | fi 12 | 13 | source "$CONFIG_FILE" 14 | if [ -n "$IPSETS_DIRECTORY" ]; then 15 | ascn_custom_directory="$IPSETS_DIRECTORY/custom" 16 | ascn_geo_directory="$IPSETS_DIRECTORY/geo" 17 | ascn_custom_files="ascn_custom_blacklist.txt ascn_custom_whitelist.txt ascn_custom_exclude.txt" 18 | 19 | if [ -d "$ascn_custom_directory" ]; then 20 | for custom_file in $ascn_custom_files; do 21 | if [ -f "$ascn_custom_directory/$custom_file" ]; then 22 | mv -f "$ascn_custom_directory/$custom_file" "$ANTISCAN_DIR/$custom_file" && printf "Имеющийся $custom_file был перемещен в каталог ${BOLD_TEXT}/opt/etc/antiscan${NO_STYLE}\n" 23 | fi 24 | done 25 | rm -r "$ascn_custom_directory" 26 | fi 27 | 28 | if [ ! -d "$ascn_geo_directory" ]; then 29 | mkdir "$ascn_geo_directory" 30 | fi 31 | fi 32 | 33 | for old_file in $OLD_CONFIG_FILES; do 34 | if [ -f "$old_file" ]; then 35 | rm "$old_file" 36 | fi 37 | done 38 | -------------------------------------------------------------------------------- /repository.mk: -------------------------------------------------------------------------------- 1 | _repo-clean: 2 | rm -rf out/_pages/$(BUILD_DIR) 3 | mkdir -p out/_pages/$(BUILD_DIR) 4 | 5 | _repo-copy: 6 | cp "out/$(FILENAME)" "out/_pages/$(BUILD_DIR)/" 7 | 8 | _repo-html: 9 | echo 'Antiscan repo' > out/_pages/$(BUILD_DIR)/index.html 10 | echo '

Index of /$(BUILD_DIR)/


' >> out/_pages/$(BUILD_DIR)/index.html 11 | echo '
' >> out/_pages/$(BUILD_DIR)/index.html
12 | 	echo '../' >> out/_pages/$(BUILD_DIR)/index.html
13 | 	echo 'Packages' >> out/_pages/$(BUILD_DIR)/index.html
14 | 	echo 'Packages.gz' >> out/_pages/$(BUILD_DIR)/index.html
15 | 	echo '$(FILENAME)' >> out/_pages/$(BUILD_DIR)/index.html
16 | 	echo '
' >> out/_pages/$(BUILD_DIR)/index.html 17 | echo '
' >> out/_pages/$(BUILD_DIR)/index.html 18 | 19 | _repo-index: 20 | echo 'Antiscan repo' > out/_pages/index.html 21 | echo '

Index of /


' >> out/_pages/index.html 22 | echo '
' >> out/_pages/index.html
23 | 	echo 'all/' >> out/_pages/index.html
24 | 	echo '
' >> out/_pages/index.html 25 | echo '
' >> out/_pages/index.html 26 | 27 | _repository: 28 | make _repo-clean 29 | make _repo-copy 30 | 31 | echo "Package: antiscan" > out/_pages/$(BUILD_DIR)/Packages 32 | echo "Version: $(VERSION)" >> out/_pages/$(BUILD_DIR)/Packages 33 | echo "Depends: libc, libssp, librt, libpthread, ipset, iptables, curl, jq" >> out/_pages/$(BUILD_DIR)/Packages 34 | echo "Section: net" >> out/_pages/$(BUILD_DIR)/Packages 35 | echo "Architecture: all" >> out/_pages/$(BUILD_DIR)/Packages 36 | echo "Filename: $(FILENAME)" >> out/_pages/$(BUILD_DIR)/Packages 37 | echo "Size: $(shell wc -c out/$(FILENAME) | awk '{print $$1}')" >> out/_pages/$(BUILD_DIR)/Packages 38 | echo "SHA256sum: $(shell sha256sum out/$(FILENAME) | awk '{print $$1}')" >> out/_pages/$(BUILD_DIR)/Packages 39 | echo "Description: Antiscan utility" >> out/_pages/$(BUILD_DIR)/Packages 40 | echo "" >> out/_pages/$(BUILD_DIR)/Packages 41 | 42 | gzip -k out/_pages/$(BUILD_DIR)/Packages 43 | 44 | @make _repo-html 45 | 46 | repo: 47 | @make \ 48 | BUILD_DIR=all \ 49 | FILENAME=antiscan_$(VERSION)_all.ipk \ 50 | _repository 51 | 52 | repository: repo _repo-index 53 | -------------------------------------------------------------------------------- /package.mk: -------------------------------------------------------------------------------- 1 | _clean: 2 | rm -rf out/$(BUILD_DIR) 3 | mkdir -p out/$(BUILD_DIR)/control 4 | mkdir -p out/$(BUILD_DIR)/data 5 | 6 | _conffiles: 7 | cp ipk/conffiles out/$(BUILD_DIR)/control/conffiles 8 | 9 | _control: 10 | echo "Package: antiscan" > out/$(BUILD_DIR)/control/control 11 | echo "Version: $(VERSION)" >> out/$(BUILD_DIR)/control/control 12 | echo "Depends: libc, libssp, librt, libpthread, ipset, iptables, curl, jq" >> out/$(BUILD_DIR)/control/control 13 | echo "License: MIT" >> out/$(BUILD_DIR)/control/control 14 | echo "Section: net" >> out/$(BUILD_DIR)/control/control 15 | echo "URL: https://github.com/dimon27254/antiscan" >> out/$(BUILD_DIR)/control/control 16 | echo "Architecture: all" >> out/$(BUILD_DIR)/control/control 17 | echo "Description: Antiscan utility" >> out/$(BUILD_DIR)/control/control 18 | echo "" >> out/$(BUILD_DIR)/control/control 19 | 20 | _scripts: 21 | cp ipk/preinst out/$(BUILD_DIR)/control/preinst 22 | cp ipk/postinst out/$(BUILD_DIR)/control/postinst 23 | cp ipk/prerm out/$(BUILD_DIR)/control/prerm 24 | cp ipk/postrm out/$(BUILD_DIR)/control/postrm 25 | chmod +x out/$(BUILD_DIR)/control/preinst 26 | chmod +x out/$(BUILD_DIR)/control/postinst 27 | chmod +x out/$(BUILD_DIR)/control/prerm 28 | chmod +x out/$(BUILD_DIR)/control/postrm 29 | 30 | _startup: 31 | cp -r etc/init.d out/$(BUILD_DIR)/data/opt/etc/init.d 32 | 33 | chmod +x out/$(BUILD_DIR)/data/opt/etc/init.d/S99ascn 34 | 35 | _hook: 36 | cp -r etc/ndm out/$(BUILD_DIR)/data/opt/etc/ndm 37 | chmod +x out/$(BUILD_DIR)/data/opt/etc/ndm/netfilter.d/099-ascn.sh 38 | 39 | _ipk: 40 | make _clean 41 | 42 | # control.tar.gz 43 | make _conffiles 44 | make _control 45 | make _scripts 46 | cd out/$(BUILD_DIR)/control; tar czvf ../control.tar.gz .; cd ../../.. 47 | 48 | # data.tar.gz 49 | mkdir -p out/$(BUILD_DIR)/data/opt/etc 50 | 51 | make _startup 52 | 53 | cp -r etc/antiscan out/$(BUILD_DIR)/data/opt/etc/antiscan 54 | chmod +x -R out/$(BUILD_DIR)/data/opt/etc/antiscan/scripts 55 | 56 | make _hook 57 | 58 | cd out/$(BUILD_DIR)/data; tar czvf ../data.tar.gz .; cd ../../.. 59 | 60 | # ipk 61 | echo 2.0 > out/$(BUILD_DIR)/debian-binary 62 | cd out/$(BUILD_DIR); \ 63 | tar czvf ../$(FILENAME) control.tar.gz data.tar.gz debian-binary; \ 64 | cd ../.. 65 | 66 | package: 67 | @make \ 68 | BUILD_DIR=antiscan \ 69 | FILENAME=antiscan_$(VERSION)_all.ipk \ 70 | _ipk -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | RED_COLOR="\033[1;31m" 6 | GREEN_COLOR="\033[1;32m" 7 | BOLD_TEXT="\033[1m" 8 | NO_STYLE="\033[0m" 9 | CRONTABS_DIR="/opt/var/spool/cron/crontabs" 10 | antiscan_string="$(opkg list-installed antiscan)" 11 | REPO_URL="https://dimon27254.github.io/antiscan/all" 12 | 13 | print_message() { 14 | msg_type="$1" 15 | msg_text="$2" 16 | case $msg_type in 17 | error) 18 | printf "${RED_COLOR}${msg_text}${NO_STYLE}\n" >&2 19 | ;; 20 | notice) 21 | printf "${BOLD_TEXT}${msg_text}${NO_STYLE}\n" 22 | ;; 23 | success) 24 | printf "${GREEN_COLOR}${msg_text}${NO_STYLE}\n" 25 | ;; 26 | esac 27 | } 28 | 29 | cron_installed() { 30 | cron_string="$(opkg list-installed cron)" 31 | crond_busybox_string="$(opkg list-installed crond-busybox)" 32 | if [ -z "$cron_string" ] && [ -z "$crond_busybox_string" ]; then 33 | cron_init_scripts="$(find /opt/etc/init.d -regex '.*\/[sS][0-9]+cron.*')" 34 | if [ -z "$cron_init_scripts" ]; then 35 | return 1 36 | else 37 | if [ ! -d "$CRONTABS_DIR" ]; then 38 | return 1 39 | else 40 | return 0 41 | fi 42 | fi 43 | else 44 | return 0 45 | fi 46 | } 47 | 48 | print_message "notice" "Устанавливаем пакеты для доступа к репозиторию Antiscan..." 49 | if opkg update && opkg install wget-ssl ca-bundle; then 50 | print_message "success" "wget-ssl и ca-bundle успешно установлены" 51 | print_message "notice" "Добавляем репозиторий Antiscan..." 52 | mkdir -p /opt/etc/opkg 53 | echo "src/gz antiscan ${REPO_URL}" >"/opt/etc/opkg/antiscan.conf" 54 | if opkg update; then 55 | print_message "notice" "Проверяем наличие cron..." 56 | if ! cron_installed; then 57 | print_message "notice" "Cron не найден. Устанавливаем..." 58 | if opkg install cron; then 59 | print_message "success" "Cron успешно установлен" 60 | print_message "notice" "Настраиваем cron..." 61 | if [ ! -d "$CRONTABS_DIR" ]; then 62 | mkdir -p "$CRONTABS_DIR" 63 | fi 64 | if ! crontab -l >/dev/null 2>&1; then 65 | echo | crontab - 66 | fi 67 | sed -i 's/="-s"/=""/' "/opt/etc/init.d/S10cron" 68 | if "/opt/etc/init.d/S10cron" start; then 69 | print_message "success" "Cron готов к работе" 70 | print_message "notice" "Переходим к установке Antiscan..." 71 | else 72 | print_message "error" "Не удалось запустить cron" 73 | return 1 74 | fi 75 | else 76 | print_message "error" "Не удалось установить cron" 77 | return 1 78 | fi 79 | else 80 | print_message "notice" "Cron найден. Переходим к установке Antiscan..." 81 | fi 82 | 83 | if opkg install antiscan --force-reinstall; then 84 | if [ -z "$antiscan_string" ]; then 85 | print_message "success" "Antiscan успешно установлен!" 86 | print_message "notice" "Выполните настройку в ascn.conf и запустите Antiscan." 87 | else 88 | print_message "success" "Antiscan успешно обновлен!" 89 | print_message "notice" "Не забудьте его запустить." 90 | fi 91 | else 92 | print_message "error" "Не удалось установить Antiscan" 93 | fi 94 | else 95 | print_message "error" "Не обновить список пакетов" 96 | fi 97 | else 98 | print_message "error" "При установке wget-ssl и ca-bundle что-то пошло не так" 99 | fi 100 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and publish 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | permissions: 7 | contents: write 8 | pages: write 9 | id-token: write 10 | 11 | concurrency: 12 | group: "pages" 13 | cancel-in-progress: false 14 | 15 | jobs: 16 | build-package: 17 | runs-on: ubuntu-22.04 18 | 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v4 22 | 23 | - name: Build package 24 | run: make package 25 | 26 | - name: Upload files 27 | uses: actions/upload-artifact@v4 28 | with: 29 | name: package 30 | path: ./out/antiscan_*_all.ipk 31 | if-no-files-found: error 32 | 33 | - name: Summary 34 | run: | 35 | echo '```' >> $GITHUB_STEP_SUMMARY 36 | ls ./out/antiscan_*_all.ipk >> $GITHUB_STEP_SUMMARY 37 | echo '```' >> $GITHUB_STEP_SUMMARY 38 | 39 | create-release: 40 | runs-on: ubuntu-22.04 41 | needs: [build-package] 42 | 43 | steps: 44 | - name: Checkout repository 45 | uses: actions/checkout@v4 46 | 47 | - name: Read version 48 | id: version 49 | run: | 50 | version=$(sed -n 's/^ASCN_VERSION="\([^"]*\)"$/\1/p' etc/init.d/S99ascn) 51 | echo "content=$version" >> $GITHUB_OUTPUT 52 | 53 | - name: Download artifacts 54 | uses: actions/download-artifact@v4 55 | with: 56 | path: out 57 | 58 | - name: Display artifacts 59 | run: ls -R ./out 60 | 61 | - name: Create tag 62 | run: | 63 | git config --local user.email "github-actions[bot]@users.noreply.github.com" 64 | git config --local user.name "github-actions[bot]" 65 | git tag -a ${{ steps.version.outputs.content }} -m "Release ${{ steps.version.outputs.content }}" 66 | git push origin ${{ steps.version.outputs.content }} 67 | git push 68 | 69 | - name: Create and upload release 70 | uses: softprops/action-gh-release@v2.3.2 71 | with: 72 | tag_name: ${{ steps.version.outputs.content }} 73 | make_latest: true 74 | files: ./out/package/antiscan_${{ steps.version.outputs.content }}_all.ipk 75 | 76 | - name: Summary 77 | run: | 78 | echo "Release ${{ steps.version.outputs.content }} created" >> $GITHUB_STEP_SUMMARY 79 | 80 | build-repository: 81 | runs-on: ubuntu-22.04 82 | needs: [build-package] 83 | 84 | steps: 85 | - name: Checkout 86 | uses: actions/checkout@v4 87 | 88 | - name: Download artifacts 89 | uses: actions/download-artifact@v4 90 | with: 91 | path: out 92 | merge-multiple: true 93 | 94 | - name: Display artifacts 95 | run: ls ./out 96 | 97 | - name: Build repository 98 | run: make repository 99 | 100 | - name: Upload pages artifact 101 | uses: actions/upload-pages-artifact@v3 102 | with: 103 | path: ./out/_pages 104 | 105 | - name: Summary 106 | run: | 107 | echo '```' >> $GITHUB_STEP_SUMMARY 108 | ls -R ./out/_pages >> $GITHUB_STEP_SUMMARY 109 | echo '```' >> $GITHUB_STEP_SUMMARY 110 | 111 | deploy-repository: 112 | runs-on: ubuntu-22.04 113 | needs: [build-repository] 114 | 115 | steps: 116 | - name: Setup Pages 117 | uses: actions/configure-pages@v5 118 | 119 | - name: Deploy to GitHub Pages 120 | id: deployment 121 | uses: actions/deploy-pages@v4 122 | 123 | - name: Summary 124 | run: | 125 | echo "Repository deployed" >> $GITHUB_STEP_SUMMARY 126 | -------------------------------------------------------------------------------- /ipk/preinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ANTISCAN_DIR="/opt/etc/antiscan" 3 | OLD_CONFIG_FILE="/opt/etc/ascn.conf" 4 | CONFIG_FILE="$ANTISCAN_DIR/ascn.conf" 5 | CRONTAB_FILE="$ANTISCAN_DIR/ascn_crontab.conf" 6 | BOLD_TEXT="\033[1m" 7 | NO_STYLE="\033[0m" 8 | if [ -s "$OLD_CONFIG_FILE" ]; then 9 | if [ ! -d "$ANTISCAN_DIR" ]; then 10 | mkdir "$ANTISCAN_DIR" 11 | fi 12 | if cp -f "$OLD_CONFIG_FILE" "$CONFIG_FILE"; then 13 | printf "Имеющийся ascn.conf был перемещен в каталог ${BOLD_TEXT}/opt/etc/antiscan${NO_STYLE}\n" 14 | fi 15 | fi 16 | if [ -s "$CONFIG_FILE" ]; then 17 | rules_mask_str="$(grep "RULES_MASK" "$CONFIG_FILE")" 18 | save_ipsets_str="$(grep "SAVE_IPSETS" "$CONFIG_FILE")" 19 | ipset_save_path_old_str="$(grep "IPSETS_SAVE_PATH" "$CONFIG_FILE")" 20 | use_custom_exclude_str="$(grep "USE_CUSTOM_EXCLUDE_LIST" "$CONFIG_FILE")" 21 | custom_lists_block_mode_str="$(grep "CUSTOM_LISTS_BLOCK_MODE" "$CONFIG_FILE")" 22 | geoblock_mode_str="$(grep "GEOBLOCK_MODE" "$CONFIG_FILE")" 23 | geoblock_countries_str="$(grep "GEOBLOCK_COUNTRIES" "$CONFIG_FILE")" 24 | read_ndm_str="$(grep "READ_NDM_LOCKOUT_IPSETS" "$CONFIG_FILE")" 25 | ndm_lockout_time_str="$(grep "LOCKOUT_IPSET_BANTIME" "$CONFIG_FILE")" 26 | ports_forwarded_str="$(grep "PORTS_FORWARDED" "$CONFIG_FILE")" 27 | honeypot_ports_str="$(grep "HONEYPOT_PORTS" "$CONFIG_FILE")" 28 | honeypot_bantime_str="$(grep "HONEYPOT_BANTIME" "$CONFIG_FILE")" 29 | save_on_exit_str="$(grep "SAVE_ON_EXIT" "$CONFIG_FILE")" 30 | enable_ips_ban_str="$(grep "ENABLE_IPS_BAN" "$CONFIG_FILE")" 31 | enable_honeypot_str="$(grep "ENABLE_HONEYPOT" "$CONFIG_FILE")" 32 | geoexclude_countries_str="$(grep "GEO_EXCLUDE_COUNTRIES" "$CONFIG_FILE")" 33 | 34 | if [ -z "$rules_mask_str" ]; then 35 | sed -i '/^RECENT_CONNECTIONS_TIME=/iRULES_MASK=\"255.255.255.255\"' "$CONFIG_FILE" 36 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}RULES_MASK=\"255.255.255.255\"${NO_STYLE}\n" 37 | fi 38 | if [ -n "$ipset_save_path_old_str" ]; then 39 | sed -i 's/^IPSETS_SAVE_PATH/IPSETS_DIRECTORY/' "$CONFIG_FILE" 40 | printf "В имеющемся ascn.conf строка ${BOLD_TEXT}IPSETS_SAVE_PATH${NO_STYLE} заменена на ${BOLD_TEXT}IPSETS_DIRECTORY${NO_STYLE}\n" 41 | fi 42 | if [ -z "$(grep "IPSETS_DIRECTORY" "$CONFIG_FILE")" ]; then 43 | printf "\n\nIPSETS_DIRECTORY=\"\"\n" >>"$CONFIG_FILE" 44 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}IPSETS_DIRECTORY=\"\"${NO_STYLE}\n" 45 | fi 46 | if [ -z "$save_ipsets_str" ]; then 47 | printf "\nSAVE_IPSETS=0\n" >>"$CONFIG_FILE" 48 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}SAVE_IPSETS=0${NO_STYLE}\n" 49 | fi 50 | if [ -z "$use_custom_exclude_str" ]; then 51 | printf "\nUSE_CUSTOM_EXCLUDE_LIST=0\n" >>"$CONFIG_FILE" 52 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}USE_CUSTOM_EXCLUDE_LIST=0${NO_STYLE}\n" 53 | fi 54 | if [ -z "$custom_lists_block_mode_str" ]; then 55 | printf "CUSTOM_LISTS_BLOCK_MODE=0\n" >>"$CONFIG_FILE" 56 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}CUSTOM_LISTS_BLOCK_MODE=0${NO_STYLE}\n" 57 | fi 58 | if [ -z "$geoblock_mode_str" ]; then 59 | printf "GEOBLOCK_MODE=0\n" >>"$CONFIG_FILE" 60 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}GEOBLOCK_MODE=0${NO_STYLE}\n" 61 | fi 62 | if [ -z "$geoblock_countries_str" ]; then 63 | printf "GEOBLOCK_COUNTRIES=\"\"\n" >>"$CONFIG_FILE" 64 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}GEOBLOCK_COUNTRIES=\"\"${NO_STYLE}\n" 65 | fi 66 | if [ -z "$read_ndm_str" ]; then 67 | printf "\nREAD_NDM_LOCKOUT_IPSETS=0\n" >>"$CONFIG_FILE" 68 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}READ_NDM_LOCKOUT_IPSETS=0${NO_STYLE}\n" 69 | fi 70 | if [ -z "$ndm_lockout_time_str" ]; then 71 | printf "LOCKOUT_IPSET_BANTIME=864000\n" >>"$CONFIG_FILE" 72 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}LOCKOUT_IPSET_BANTIME=864000${NO_STYLE}\n" 73 | fi 74 | if [ -z "$ports_forwarded_str" ]; then 75 | source "$CONFIG_FILE" 76 | sed -i "/^PORTS=/aPORTS_FORWARDED=\"$PORTS\"" "$CONFIG_FILE" 77 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}PORTS_FORWARDED${NO_STYLE}\n" 78 | fi 79 | if [ -z "$honeypot_ports_str" ]; then 80 | sed -i "/^PORTS_FORWARDED=/aHONEYPOT_PORTS=\"\"" "$CONFIG_FILE" 81 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}HONEYPOT_PORTS=\"\"${NO_STYLE}\n" 82 | fi 83 | if [ -z "$honeypot_bantime_str" ]; then 84 | sed -i "/^HONEYPOT_PORTS=/aHONEYPOT_BANTIME=864000" "$CONFIG_FILE" 85 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}HONEYPOT_BANTIME=864000${NO_STYLE}\n" 86 | fi 87 | if [ -z "$save_on_exit_str" ]; then 88 | sed -i "/^SAVE_IPSETS=/aSAVE_ON_EXIT=0" "$CONFIG_FILE" 89 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}SAVE_ON_EXIT=0${NO_STYLE}\n" 90 | fi 91 | if [ -z "$enable_honeypot_str" ]; then 92 | source "$CONFIG_FILE" 93 | honeypot_var="" 94 | [ -z "$HONEYPOT_PORTS" ] && honeypot_var="ENABLE_HONEYPOT=0" || honeypot_var="ENABLE_HONEYPOT=1" 95 | sed -i "/^PORTS_FORWARDED=/a${honeypot_var}" "$CONFIG_FILE" 96 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}${honeypot_var}${NO_STYLE}\n" 97 | fi 98 | if [ -z "$enable_ips_ban_str" ]; then 99 | sed -i "/^HONEYPOT_BANTIME=/aENABLE_IPS_BAN=1" "$CONFIG_FILE" 100 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}ENABLE_IPS_BAN=1${NO_STYLE}\n" 101 | fi 102 | if [ -z "$geoexclude_countries_str" ]; then 103 | sed -i "/^GEOBLOCK_COUNTRIES=/aGEO_EXCLUDE_COUNTRIES=\"\"" "$CONFIG_FILE" 104 | printf "В имеющийся ascn.conf добавлена новая строка ${BOLD_TEXT}GEO_EXCLUDE_COUNTRIES=\"\"${NO_STYLE}\n" 105 | fi 106 | fi 107 | if [ -s "$CRONTAB_FILE" ]; then 108 | read_ndm_task_str="$(grep 'read_ndm_ipsets' "$CRONTAB_FILE")" 109 | if [ -z "$read_ndm_task_str" ]; then 110 | printf "\n*/2 * * * * /opt/etc/init.d/S99ascn read_ndm_ipsets &\n" >>"$CRONTAB_FILE" 111 | sed -n -i '\:S99ascn:p' "$CRONTAB_FILE" 112 | printf "В имеющийся ascn_crontab.conf добавлена задача для чтения списков NDM ip lockout-policy\n" 113 | fi 114 | fi 115 | -------------------------------------------------------------------------------- /etc/init.d/S99ascn: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ANTISCAN_DIR="/opt/etc/antiscan" 4 | CRONTAB_FILE="$ANTISCAN_DIR/ascn_crontab.conf" 5 | 6 | ANTISCAN_SCRIPTS_DIR="$ANTISCAN_DIR/scripts" 7 | 8 | ASCN_TEMP_FILE="/tmp/ascn.run" 9 | ASCN_VERSION="1.10" 10 | 11 | PATH=/opt/bin:/opt/sbin:/sbin:/usr/sbin:/bin:/usr/bin 12 | 13 | source "${ANTISCAN_SCRIPTS_DIR}/geo.sh" 14 | source "${ANTISCAN_SCRIPTS_DIR}/log.sh" 15 | source "${ANTISCAN_SCRIPTS_DIR}/config.sh" 16 | source "${ANTISCAN_SCRIPTS_DIR}/iptables.sh" 17 | source "${ANTISCAN_SCRIPTS_DIR}/ipsets.sh" 18 | source "${ANTISCAN_SCRIPTS_DIR}/show_data.sh" 19 | 20 | read_config "$1" 21 | 22 | start() { 23 | if ascn_is_running; then 24 | print_message "error" "Antiscan уже работает" 25 | exit 1 26 | else 27 | if config_is_reloading; then 28 | print_message "error" "Запуск Antiscan невозможен, пока идёт обновление конфигурации" 29 | exit 2 30 | fi 31 | 32 | if geo_is_loading; then 33 | print_message "error" "Запуск Antiscan невозможен, пока идёт обновление списков подсетей стран" 34 | exit 2 35 | fi 36 | 37 | update_cron 38 | load_kernel_modules 39 | write_temp_config 40 | create_ipsets 41 | add_rules 42 | create_status_file 43 | 44 | show_no_protection_warning 45 | print_message "notice" "Antiscan запущен" 46 | fi 47 | } 48 | 49 | stop() { 50 | if ! ascn_is_running; then 51 | print_message "error" "Antiscan не запущен" 52 | else 53 | 54 | if config_is_reloading; then 55 | print_message "error" "Остановка Antiscan невозможна, пока идёт обновление конфигурации" 56 | exit 2 57 | fi 58 | 59 | if geo_is_loading; then 60 | print_message "error" "Остановка Antiscan невозможна, пока идёт обновление списков подсетей стран" 61 | exit 2 62 | fi 63 | 64 | if [ "$SAVE_ON_EXIT" == "1" ] || [ "$1" == "1" ]; then 65 | export_ipsets 66 | fi 67 | 68 | remove_rules 69 | destroy_ipsets 70 | destroy_temp_config 71 | remove_status_file 72 | print_message "notice" "Antiscan остановлен" 73 | fi 74 | } 75 | 76 | create_status_file() { 77 | echo "1" >"$ASCN_TEMP_FILE" 78 | } 79 | 80 | remove_status_file() { 81 | if ascn_is_running; then 82 | rm "$ASCN_TEMP_FILE" 83 | fi 84 | } 85 | 86 | ascn_is_running() { 87 | if [ -f "$ASCN_TEMP_FILE" ]; then 88 | return 0 89 | else 90 | return 1 91 | fi 92 | } 93 | 94 | all_protections_disabled() { 95 | if [ "$ENABLE_HONEYPOT" != "1" ] && [ "$ENABLE_IPS_BAN" != "1" ] && [ "$CUSTOM_LISTS_BLOCK_MODE" != "blacklist" ] && [ "$CUSTOM_LISTS_BLOCK_MODE" != "whitelist" ] && 96 | [ "$GEOBLOCK_MODE" != "blacklist" ] && [ "$GEOBLOCK_MODE" != "whitelist" ] && [ "$READ_NDM_LOCKOUT_IPSETS" != "1" ]; then 97 | return 0 98 | else 99 | return 1 100 | fi 101 | } 102 | 103 | show_no_protection_warning() { 104 | all_protections_disabled && print_message "warning" "Все виды защиты Antiscan отключены пользователем" 1 105 | } 106 | 107 | update_cron() { 108 | crontab_bin="/opt/bin/crontab" 109 | if [ -f "$crontab_bin" ]; then 110 | if [ -s "$CRONTAB_FILE" ]; then 111 | if [ ! -d "/opt/var/spool/cron/crontabs" ]; then 112 | print_message "error" "При чтении списка задач crontab что-то пошло не так. У вас не настроен cron?" 113 | else 114 | local tasks_from_crontab="$(crontab -l | grep 'S99ascn')" 115 | local tasks_from_file="$(grep 'S99ascn' "$CRONTAB_FILE")" 116 | if [ "$tasks_from_crontab" != "$tasks_from_file" ]; then 117 | print_message "notice" "Обновляем crontab" 118 | crontab -l | sed '/S99ascn/d; /# DO/d; /# (/d' >"/tmp/crontasks" 119 | echo "$tasks_from_file" >>"/tmp/crontasks" 120 | if ! crontab "/tmp/crontasks"; then 121 | print_message "error" "При обновлении crontab что-то пошло не так :(" 122 | fi 123 | rm "/tmp/crontasks" 124 | fi 125 | fi 126 | else 127 | print_message "error" "Невозможно обновить crontab! Файл ascn_crontab.conf пуст." 128 | fi 129 | else 130 | print_message "error" "crontab не найден! У вас не установлен cron?" 131 | fi 132 | } 133 | 134 | edit_file() { 135 | local file_to_open="" 136 | case "$1" in 137 | config | conf) 138 | file_to_open="$CONFIG_FILE" 139 | ;; 140 | crontab | cron) 141 | file_to_open="$CRONTAB_FILE" 142 | ;; 143 | custom_exclude | custom_whitelist | custom_blacklist) 144 | file_to_open="$ANTISCAN_DIR/ascn_$1.txt" 145 | ;; 146 | *) 147 | print_message "console" "Использование: $0 edit {config|crontab|custom_exclude|custom_blacklist|custom_whitelist}" 148 | exit 1 149 | ;; 150 | esac 151 | if [ -f "/opt/bin/nano" ]; then 152 | nano "$file_to_open" 153 | elif [ -f "/opt/bin/vim" ]; then 154 | vim "$file_to_open" 155 | elif [ -f "/opt/bin/vi" ]; then 156 | vi "$file_to_open" 157 | else 158 | print_message "error" "Не удалось найти поддерживаемый текстовый редактор" 159 | exit 1 160 | fi 161 | local editor_exitcode="$?" 162 | if [ "$editor_exitcode" == "0" ]; then 163 | if [ "$file_to_open" == "$CONFIG_FILE" ]; then 164 | ( 165 | source "$CONFIG_FILE" 166 | check_config 167 | ) 168 | local check_result="$?" 169 | if ascn_is_running && [ "$check_result" == "0" ]; then 170 | if [ -f "$CONFIG_FILE_TEMP" ]; then 171 | source "$CONFIG_FILE_TEMP" 172 | else 173 | source "$CONFIG_FILE" 174 | fi 175 | reload_config 176 | fi 177 | elif [ "$file_to_open" == "$CRONTAB_FILE" ]; then 178 | update_cron 179 | else 180 | update_ipsets "custom" 181 | fi 182 | fi 183 | } 184 | 185 | case "$1" in 186 | start) 187 | start 188 | ;; 189 | stop) 190 | stop 191 | ;; 192 | restart) 193 | stop 1 194 | start 195 | ;; 196 | status) 197 | get_status 198 | ;; 199 | list) 200 | show_ipsets "$2" 201 | ;; 202 | reload) 203 | reload_config 204 | ;; 205 | flush) 206 | flush_ipsets "$2" 207 | ;; 208 | update_rules) 209 | update_iptables 210 | ;; 211 | read_candidates | read) 212 | read_ip_candidates 213 | ;; 214 | read_ndm_ipsets | read_ndm) 215 | read_ndm_ipsets 216 | ;; 217 | save_ipsets | save) 218 | export_ipsets 219 | ;; 220 | update_ipsets) 221 | update_ipsets "$2" 222 | ;; 223 | update_crontab) 224 | update_cron 225 | ;; 226 | retry_load_geo) 227 | retry_load_geo 228 | ;; 229 | version) 230 | show_version 231 | ;; 232 | version_opkg) 233 | show_version "opkg" 234 | ;; 235 | edit) 236 | edit_file "$2" 237 | ;; 238 | config | conf) 239 | edit_file "config" 240 | ;; 241 | crontab | cron) 242 | edit_file "crontab" 243 | ;; 244 | *) 245 | print_message "console" "Использование: $0 {start|stop|restart|status|list|reload|flush|version|edit|update_rules|read_candidates|read_ndm_ipsets|save_ipsets|update_ipsets|update_crontab}" 246 | ;; 247 | esac 248 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Antiscan - простой инструмент для выявления и блокировки IP с подозрительной активностью. 2 | 3 | ## Antiscan предназначен для устройств Keenetic/Netcraze, поддерживающих Entware. 4 | 5 | ### Возможности: 6 | 1) Блокировка хостов, открывающих множество соединений с одного IP-адреса. 7 | 2) Блокировка хостов, открывающих единичные соединения с множества IP, принадлежащих одной подсети /24. 8 | 3) Блокировка хостов по пользовательскому черному/белому списку. 9 | 4) Геоблокировка в режиме черного/белого списка. 10 | 5) Блокировка хостов с помощью "ловушки" (honeypot). 11 | 12 | > [!IMPORTANT] 13 | > Antiscan является IPv4-only, работает только для протокола TCP. 14 | 15 | ### Подробное описание возможностей Antiscan, а также обсуждение работы ведется на форуме Keenetic Communtity: https://forum.keenetic.ru/topic/21009-antiscan/ 16 | 17 | 18 | ### Требования для корректной работы скрипта: 19 | 1. Установленный компонент "Модули ядра для подсистемы Netfilter" (начиная с версии ПО 4.3 доступен без "Протокол IPv6"). 20 | 21 | ### Установка: 22 | 1. Выполнить команду `opkg update && opkg install curl && curl -fsSL https://raw.githubusercontent.com/dimon27254/antiscan/refs/heads/main/install.sh | sh` 23 | 2. Указать unix-имена интерфейсов интернет-подключений в файле `"/opt/etc/antiscan/ascn.conf"`. В ПО версии 4.3 и выше просмотр unix-имен интерфейсов доступен по команде `show interface {интерфейс} system-name` 24 | 3. Настроить остальные параметры под собственные нужды, если это требуется, в файле `"/opt/etc/antiscan/ascn.conf"` 25 | 4. Запустить Antiscan командой `antiscan start` 26 | 27 | **Для версий Antiscan 1.4 и выше доступна настройка с помощью [web4static](https://github.com/spatiumstas/web4static) от [spatiumstas](https://github.com/spatiumstas).** 28 | 29 | ### Описание параметров в ascn.conf: 30 | ``` 31 | # Перечень интерфейсов, на которых работает Antiscan. Множество интерфейсов указывается через пробел, пример: "eth3 eth2.2 ppp0": 32 | ISP_INTERFACES="eth3" 33 | 34 | # Перечень портов служб устройства, на которых работает Antiscan. Множество портов указывается через запятую, пример: "22,80,443": 35 | PORTS="22,80,443" 36 | 37 | # Перечень портов хостов в локальной сети, на которые идет перенаправление трафика. Пример ввода множества портов: "22,80,443". 38 | # ОБРАТИТЕ ВНИМАНИЕ! Указываются порты из поля "направлять на порт" в правилах переадресации, а не "открыть порт". 39 | PORTS_FORWARDED="22,80,443" 40 | 41 | # Использовать блокировку хостов с помощью "ловушки". 0 - выключена, 1 - включена 42 | ENABLE_HONEYPOT=0 43 | # Перечень портов ловушки, на которых идет отслеживание входящих подключений. Пример ввода множества портов: "22,80,443". 44 | HONEYPOT_PORTS="" 45 | 46 | # Длительность блокировки IP ловушкой в секундах: 47 | HONEYPOT_BANTIME=864000 48 | 49 | # Использовать блокировку хостов по накопленным IP/подсетям. 0 - выключена, 1 - включена 50 | ENABLE_IPS_BAN=1 51 | # Настройки ограничения множественных соединений: 52 | # ДЛЯ ОПЫТНЫХ ПОЛЬЗОВАТЕЛЕЙ! Маска правил iptables для отслеживания соединений: 53 | RULES_MASK="255.255.255.255" 54 | 55 | # Время наблюдения за новыми соединениями с IP в секундах: 56 | RECENT_CONNECTIONS_TIME=30 57 | 58 | # Пороговое значение новых соединений за период RECENT_CONNECTIONS_TIME, после которого IP будет заблокирован: 59 | RECENT_CONNECTIONS_HITCOUNT=15 60 | 61 | # Общий лимит множественных соединений с одного адреса, после которого он будет заблокирован: 62 | RECENT_CONNECTIONS_LIMIT=20 63 | 64 | # Длительность блокировки IP в секундах: 65 | RECENT_CONNECTIONS_BANTIME=864000 66 | 67 | # Настройки ограничения соединений с разных IP: 68 | # Срок хранения IP-адресов-кандидатов на блокировку: 69 | DIFFERENT_IP_CANDIDATES_STORAGETIME=864000 70 | 71 | # Пороговое значение IP-кандидатов, начиная с которого будет создана подсеть для блокировки: 72 | DIFFERENT_IP_THRESHOLD=5 73 | 74 | # Длительность блокировки подсети в секундах: 75 | SUBNETS_BANTIME=864000 76 | 77 | # Путь к каталогу, внутри которого будут находиться все списки адресов. Пример: "/tmp/mnt/MYDISK/antiscan" 78 | IPSETS_DIRECTORY="" 79 | 80 | # Сохранять списки накопленных заблокированных IP и подсетей в файлы. 0 - выключено, 1 - включено 81 | SAVE_IPSETS=0 82 | 83 | # Сохранять списки накопленных заблокированных IP и подсетей при вызове antiscan stop. 0 - выключено, 1 - включено 84 | SAVE_ON_EXIT=0 85 | 86 | # Использовать пользовательский список адресов-исключений. 0 - выключено, 1 - включено 87 | USE_CUSTOM_EXCLUDE_LIST=0 88 | 89 | # Режим блокировки по пользовательским спискам. 0 - отключена, blacklist - черный список, whitelist - белый список 90 | CUSTOM_LISTS_BLOCK_MODE=0 91 | 92 | # Режим геоблокировки. 0 - отключена, blacklist - черный список, whitelist - белый список 93 | GEOBLOCK_MODE=0 94 | 95 | # Перечень стран для геоблокировки. Пример: одна страна - "US", множество стран - "RU DE" 96 | GEOBLOCK_COUNTRIES="" 97 | 98 | # Перечень стран-исключений. Пример: одна страна - "RU", множество стран - "RU DE" 99 | GEO_EXCLUDE_COUNTRIES="" 100 | 101 | # Чтение системных списков блокировки по ip lockout-policy. 0 - выключено, 1 - включено 102 | READ_NDM_LOCKOUT_IPSETS=0 103 | 104 | # Срок хранения записей, считанных из системных списков: 105 | LOCKOUT_IPSET_BANTIME=864000 106 | ``` 107 | > [!TIP] 108 | > 1) Период чтения списка кандидатов по умолчанию равен 1 минуте. 109 | > 110 | > Текст задачи в **ascn_crontab.conf**: `*/1 * * * * /opt/etc/init.d/S99ascn read_candidates &` 111 | > 112 | > 2) Период чтения системных списков блокировки по умолчанию равен 2 минутам. 113 | > 114 | > Текст задачи в **ascn_crontab.conf**: `*/2 * * * * /opt/etc/init.d/S99ascn read_ndm_ipsets &` 115 | > 116 | > 3) Списки адресов по умолчанию сохраняются каждые 5 дней в 00:00. 117 | > 118 | > Текст задачи в **ascn_crontab.conf**: `0 0 */5 * * /opt/etc/init.d/S99ascn save_ipsets &` 119 | > 120 | > 4) Списки подсетей для геоблокировки по умолчанию обновляются каждые 15 дней в 00:05. 121 | > 122 | > Текст задачи в **ascn_crontab.conf**: `0 5 */15 * * /opt/etc/init.d/S99ascn update_ipsets geo &` 123 | 124 | ### Использование Antiscan: 125 | ``` 126 | {start|stop|restart|status|list|reload|flush|version|edit|update_rules|read_candidates|read_ndm_ipsets|save_ipsets|update_ipsets|update_crontab} 127 | start начать работу скрипта (создать правила, ipset'ы, начать сбор IP) 128 | stop остановить работу скрипта (удалить правила, очистить ipset'ы, отменить блокировку) 129 | restart остановить и заново начать работу скрипта 130 | status отобразить статус работы Antiscan 131 | 132 | list {ips|subnets|ndm_lockout|honeypot} 133 | отобразить список и количество заблокированных IP/подсетей 134 | 135 | reload обновить конфигурацию Antiscan (перечитать файл ascn.conf) 136 | 137 | flush [candidates|ips|subnets|custom_whitelist|custom_blacklist|custom_exclude|geo|ndm_lockout|honeypot] 138 | очистить списки адресов и удалить их файлы 139 | 140 | version отобразить версию установленного Antiscan 141 | 142 | edit {config|crontab|custom_exclude|custom_blacklist|custom_whitelist} 143 | редактировать конфигурационные файлы Antiscan или пользовательские списки 144 | 145 | update_rules проверить наличие правил iptables, и добавить их при отсутствии (для hook-скрипта netfilter.d) 146 | read_candidates обработать список адресов кандидатов для блокировки по подсетям (запускается вручную или по расписанию) 147 | read_ndm_ipsets считать системные списки блокировки по ip lockout-policy (запускается вручную или по расписанию) 148 | save_ipsets сохранить списки накопленных адресов в файлы (запускается вручную или по расписанию) 149 | update_ipsets {custom|geo} обновить пользовательские списки адресов или подсети для геоблокировки (запускается вручную или по расписанию) 150 | update_crontab обновить задачи Antiscan в файле crontab 151 | ``` 152 | -------------------------------------------------------------------------------- /etc/antiscan/scripts/iptables.sh: -------------------------------------------------------------------------------- 1 | load_kernel_modules() { 2 | if [ -z "$(lsmod 2>/dev/null | grep "xt_recent ")" ]; then 3 | local xtrecent_mod_path=$(find "/lib/modules/$KERNEL" -name "xt_recent.ko*") 4 | if [ -n "$xtrecent_mod_path" ]; then 5 | insmod "$xtrecent_mod_path" >/dev/null 2>&1 6 | print_message "notice" "xt_recent.ko загружен" 7 | else 8 | print_message "error" "Не удалось найти модуль ядра xt_recent.ko" 9 | exit 1 10 | fi 11 | fi 12 | 13 | if [ -z "$(lsmod 2>/dev/null | grep "xt_multiport ")" ]; then 14 | local multiport_mod_path=$(find "/lib/modules/$KERNEL" -name "xt_multiport.ko*") 15 | if [ -n "$multiport_mod_path" ]; then 16 | insmod "$multiport_mod_path" >/dev/null 2>&1 17 | print_message "notice" "xt_multiport.ko загружен" 18 | else 19 | print_message "error" "Не удалось найти модуль ядра xt_multiport.ko" 20 | exit 1 21 | fi 22 | fi 23 | } 24 | 25 | _iptables() { 26 | local ACTION=$1 27 | shift 1 28 | local RULE="$@" 29 | 30 | iptables -w -C $RULE 2>/dev/null 31 | local exists=$? 32 | local chain_exists=0 33 | 34 | if echo "$RULE" | grep -q '\bANTISCAN\b'; then 35 | iptables -L ANTISCAN -w -t filter -n >/dev/null 2>&1 36 | chain_exists=$? 37 | elif echo "$RULE" | grep -q '\bANTISCAN_HONEYPOT\b'; then 38 | iptables -L ANTISCAN_HONEYPOT -w -t filter -n >/dev/null 2>&1 39 | chain_exists=$? 40 | else 41 | chain_exists=0 42 | fi 43 | 44 | if [ "$ACTION" == "-I" ] || [ "$ACTION" == "-A" ]; then 45 | if [ $exists -ne 0 ] && [ $chain_exists -eq 0 ]; then 46 | iptables $ACTION $RULE 47 | fi 48 | elif [ "$ACTION" == "-D" ] && [ $exists -eq 0 ] && [ $chain_exists -eq 0 ]; then 49 | iptables $ACTION $RULE 50 | fi 51 | } 52 | 53 | add_rules() { 54 | if ! iptables -L ANTISCAN -w -t filter -n >/dev/null 2>&1; then 55 | iptables -N ANTISCAN -w -t filter 56 | 57 | if [ -n "$(ipset -q -n list ascn_custom_exclude)" ]; then 58 | _iptables -A ANTISCAN -w -t filter -m set --match-set ascn_custom_exclude src -j RETURN 59 | fi 60 | if [ -n "$(ipset -q -n list ascn_geo_exclude)" ]; then 61 | _iptables -A ANTISCAN -w -t filter -m set --match-set ascn_geo_exclude src -j RETURN 62 | fi 63 | 64 | if [ -n "$(ipset -q -n list ascn_custom_blacklist)" ]; then 65 | _iptables -A ANTISCAN -w -t filter -m set --match-set ascn_custom_blacklist src -j DROP 66 | elif [ -n "$(ipset -q -n list ascn_custom_whitelist)" ]; then 67 | _iptables -A ANTISCAN -w -t filter -m set ! --match-set ascn_custom_whitelist src -j DROP 68 | fi 69 | 70 | if [ -n "$(ipset -q -n list ascn_geo_blacklist)" ]; then 71 | _iptables -A ANTISCAN -w -t filter -m set --match-set ascn_geo_blacklist src -j DROP 72 | elif [ -n "$(ipset -q -n list ascn_geo_whitelist)" ]; then 73 | _iptables -A ANTISCAN -w -t filter -m set ! --match-set ascn_geo_whitelist src -j DROP 74 | fi 75 | 76 | if [ -n "$(ipset -q -n list ascn_ndm_lockout)" ]; then 77 | _iptables -A ANTISCAN -w -t filter -m set --match-set ascn_ndm_lockout src -j DROP 78 | fi 79 | 80 | if [ "$ENABLE_HONEYPOT" == "1" ] && [ -n "$(ipset -q -n list ascn_honeypot)" ]; then 81 | _iptables -A ANTISCAN -w -t filter -m set --match-set ascn_honeypot src -j DROP 82 | fi 83 | 84 | if [ "$ENABLE_IPS_BAN" == "1" ]; then 85 | _iptables -A ANTISCAN -w -t filter -m set --match-set ascn_subnets src -j DROP 86 | _iptables -A ANTISCAN -w -t filter -m set --match-set ascn_ips src -j DROP 87 | _iptables -A ANTISCAN -w -t filter -j SET --add-set ascn_candidates src 88 | _iptables -A ANTISCAN -w -t filter -m connlimit --connlimit-above $RECENT_CONNECTIONS_LIMIT --connlimit-mask $RULES_MASK -j SET --add-set ascn_ips src 89 | _iptables -A ANTISCAN -w -t filter -m conntrack --ctstate NEW -m recent --update --seconds $RECENT_CONNECTIONS_TIME --hitcount $RECENT_CONNECTIONS_HITCOUNT --name scanners --mask $RULES_MASK -j SET --add-set ascn_ips src 90 | _iptables -A ANTISCAN -w -t filter -m conntrack --ctstate NEW -m recent --set --name scanners --mask $RULES_MASK 91 | fi 92 | 93 | _iptables -A ANTISCAN -w -t filter -j RETURN 94 | fi 95 | 96 | if iptables -L ANTISCAN -w -t filter -n >/dev/null 2>&1; then 97 | for INTERFACE in $ISP_INTERFACES; do 98 | if [ -n "$PORTS" ]; then 99 | _iptables -I INPUT -w -t filter -i $INTERFACE -p tcp -m multiport --dports $PORTS -j ANTISCAN 100 | fi 101 | if [ -n "$PORTS_FORWARDED" ]; then 102 | _iptables -I FORWARD -w -t filter -i $INTERFACE -p tcp -m multiport --dports $PORTS_FORWARDED -j ANTISCAN 103 | fi 104 | done 105 | fi 106 | 107 | if [ "$ENABLE_HONEYPOT" == "1" ]; then 108 | if ! iptables -L ANTISCAN_HONEYPOT -w -t filter -n >/dev/null 2>&1; then 109 | iptables -N ANTISCAN_HONEYPOT -w -t filter 110 | 111 | if [ -n "$(ipset -q -n list ascn_custom_exclude)" ]; then 112 | _iptables -A ANTISCAN_HONEYPOT -w -t filter -m set --match-set ascn_custom_exclude src -j RETURN 113 | fi 114 | if [ -n "$(ipset -q -n list ascn_geo_exclude)" ]; then 115 | _iptables -A ANTISCAN_HONEYPOT -w -t filter -m set --match-set ascn_geo_exclude src -j RETURN 116 | fi 117 | 118 | if [ -n "$(ipset -q -n list ascn_custom_blacklist)" ]; then 119 | _iptables -A ANTISCAN_HONEYPOT -w -t filter -m set --match-set ascn_custom_blacklist src -j DROP 120 | elif [ -n "$(ipset -q -n list ascn_custom_whitelist)" ]; then 121 | _iptables -A ANTISCAN_HONEYPOT -w -t filter -m set ! --match-set ascn_custom_whitelist src -j DROP 122 | fi 123 | 124 | if [ -n "$(ipset -q -n list ascn_geo_blacklist)" ]; then 125 | _iptables -A ANTISCAN_HONEYPOT -w -t filter -m set --match-set ascn_geo_blacklist src -j DROP 126 | elif [ -n "$(ipset -q -n list ascn_geo_whitelist)" ]; then 127 | _iptables -A ANTISCAN_HONEYPOT -w -t filter -m set ! --match-set ascn_geo_whitelist src -j DROP 128 | fi 129 | 130 | if [ -n "$(ipset -q -n list ascn_ndm_lockout)" ]; then 131 | _iptables -A ANTISCAN_HONEYPOT -w -t filter -m set --match-set ascn_ndm_lockout src -j DROP 132 | fi 133 | 134 | if [ -n "$(ipset -q -n list ascn_honeypot)" ]; then 135 | _iptables -A ANTISCAN_HONEYPOT -w -t filter -m set --match-set ascn_honeypot src -j DROP 136 | fi 137 | 138 | if [ "$ENABLE_IPS_BAN" == "1" ]; then 139 | _iptables -A ANTISCAN_HONEYPOT -w -t filter -m set --match-set ascn_subnets src -j DROP 140 | _iptables -A ANTISCAN_HONEYPOT -w -t filter -m set --match-set ascn_ips src -j DROP 141 | fi 142 | 143 | if [ -n "$(ipset -q -n list ascn_honeypot)" ]; then 144 | _iptables -A ANTISCAN_HONEYPOT -w -t filter -j SET --add-set ascn_honeypot src 145 | fi 146 | fi 147 | 148 | if iptables -L ANTISCAN_HONEYPOT -w -t filter -n >/dev/null 2>&1; then 149 | for INTERFACE in $ISP_INTERFACES; do 150 | _iptables -I INPUT -w -t filter -i $INTERFACE -p tcp -m multiport --dports $HONEYPOT_PORTS -j ANTISCAN_HONEYPOT 151 | done 152 | fi 153 | fi 154 | } 155 | 156 | remove_rules() { 157 | if iptables -L ANTISCAN -w -t filter -n >/dev/null 2>&1; then 158 | for INTERFACE in $ISP_INTERFACES; do 159 | if [ -n "$PORTS" ]; then 160 | _iptables -D INPUT -w -t filter -i $INTERFACE -p tcp -m multiport --dports $PORTS -j ANTISCAN 161 | fi 162 | if [ -n "$PORTS_FORWARDED" ]; then 163 | _iptables -D FORWARD -w -t filter -i $INTERFACE -p tcp -m multiport --dports $PORTS_FORWARDED -j ANTISCAN 164 | fi 165 | done 166 | iptables -F ANTISCAN -w -t filter 167 | iptables -X ANTISCAN -w -t filter 168 | fi 169 | 170 | if [ "$ENABLE_HONEYPOT" == "1" ]; then 171 | if iptables -L ANTISCAN_HONEYPOT -w -t filter -n >/dev/null 2>&1; then 172 | for INTERFACE in $ISP_INTERFACES; do 173 | _iptables -D INPUT -w -t filter -i $INTERFACE -p tcp -m multiport --dports $HONEYPOT_PORTS -j ANTISCAN_HONEYPOT 174 | done 175 | iptables -F ANTISCAN_HONEYPOT -w -t filter 176 | iptables -X ANTISCAN_HONEYPOT -w -t filter 177 | fi 178 | fi 179 | } 180 | 181 | update_iptables() { 182 | if ! ascn_is_running; then 183 | exit 1 184 | else 185 | local wait_timeout=15 186 | local log_message="Идет обновление конфигурации Antiscan, пробуем восстановить правила за 15 секунд... " 187 | while config_is_reloading && [ "$wait_timeout" -gt 0 ]; do 188 | if [ $wait_timeout -eq 15 ]; then echo -n "$log_message" >&2; fi 189 | wait_timeout=$((wait_timeout - 1)) 190 | sleep 1 191 | done 192 | if config_is_reloading; then 193 | log_message="${log_message} неудачно" 194 | print_message "warning" "${log_message}" 1 195 | exit 2 196 | else 197 | if [ $wait_timeout -ne 15 ]; then 198 | log_message="${log_message} успешно" 199 | print_message "warning" "${log_message}" 1 200 | fi 201 | add_rules 202 | fi 203 | fi 204 | } 205 | -------------------------------------------------------------------------------- /etc/antiscan/scripts/show_data.sh: -------------------------------------------------------------------------------- 1 | get_status() { 2 | printf "Версия Antiscan:\t${BOLD_TEXT}$ASCN_VERSION${NO_STYLE}\n" 3 | printf "Статус:\t\t\t" 4 | if ascn_is_running; then 5 | if config_is_reloading; then 6 | printf "${YELLOW_COLOR}обновление конфигурации${NO_STYLE}\n" 7 | elif geo_is_loading; then 8 | printf "${YELLOW_COLOR}обновление списков подсетей стран${NO_STYLE}\n" 9 | else 10 | if all_protections_disabled; then 11 | printf "${YELLOW_COLOR}без защиты${NO_STYLE}\n" 12 | else 13 | printf "${GREEN_COLOR}работает${NO_STYLE}\n" 14 | fi 15 | 16 | if [ "$ENABLE_IPS_BAN" == "1" ]; then 17 | local banned_ip_count="$(ipset list ascn_ips | tail -n +8 | grep -c '^')" 18 | local banned_subnets_count="$(ipset list ascn_subnets | tail -n +8 | grep -c '^')" 19 | printf "Заблокировано адресов:\t${BOLD_TEXT}$banned_ip_count${NO_STYLE}\n" 20 | printf "Заблокировано подсетей:\t${BOLD_TEXT}$banned_subnets_count${NO_STYLE}\n" 21 | else 22 | printf "Блокировка IP/подсетей:\t${RED_COLOR}отключена${NO_STYLE}\n" 23 | fi 24 | 25 | if [ "$ENABLE_HONEYPOT" == "1" ]; then 26 | local banned_ip_honeypot_count="$(ipset list ascn_honeypot | tail -n +8 | grep -c '^')" 27 | printf "Заблокировано ловушкой:\t${BOLD_TEXT}$banned_ip_honeypot_count${NO_STYLE}\n" 28 | else 29 | printf "Блокировка ловушкой:\t${RED_COLOR}отключена${NO_STYLE}\n" 30 | fi 31 | 32 | if [ "$READ_NDM_LOCKOUT_IPSETS" == "1" ]; then 33 | local banned_ip_ndm_count="$(ipset list ascn_ndm_lockout | tail -n +8 | grep -c '^')" 34 | printf "Заблокировано NDMS:\t${BOLD_TEXT}$banned_ip_ndm_count${NO_STYLE}\n" 35 | else 36 | printf "Чтение списков NDMS:\t${RED_COLOR}отключено${NO_STYLE}\n" 37 | fi 38 | 39 | if [ "$USE_CUSTOM_EXCLUDE_LIST" == "1" ] || [ "$CUSTOM_LISTS_BLOCK_MODE" == "blacklist" ] || [ "$CUSTOM_LISTS_BLOCK_MODE" == "whitelist" ]; then 40 | if [ "$USE_CUSTOM_EXCLUDE_LIST" == "1" ]; then 41 | local excluded_count="$(ipset -q list ascn_custom_exclude | tail -n +8 | grep -c '^')" 42 | if [ "$excluded_count" -gt 0 ]; then 43 | printf "Список исключений:\t${BOLD_TEXT}$(get_ipset_member_text "$excluded_count")${NO_STYLE}\n" 44 | else 45 | printf "Список исключений:\t${RED_COLOR}не активен${NO_STYLE}\n" 46 | fi 47 | fi 48 | 49 | case "$CUSTOM_LISTS_BLOCK_MODE" in 50 | "blacklist" | "whitelist") 51 | local custom_set_name="ascn_custom_${CUSTOM_LISTS_BLOCK_MODE}" 52 | local custom_set_type="" 53 | [ "$CUSTOM_LISTS_BLOCK_MODE" == "blacklist" ] && custom_set_type="Черный список" || custom_set_type="Белый список" 54 | local custom_ip_count="$(ipset -q list $custom_set_name | tail -n +8 | grep -c '^')" 55 | if [ "$custom_ip_count" -gt 0 ]; then 56 | printf "${custom_set_type}:\t\t${BOLD_TEXT}$(get_ipset_member_text "$custom_ip_count")${NO_STYLE}\n" 57 | else 58 | printf "${custom_set_type}:\t\t${RED_COLOR}не активен${NO_STYLE}\n" 59 | fi 60 | ;; 61 | esac 62 | else 63 | printf "Пользовательские списки ${RED_COLOR}не активны${NO_STYLE}\n" 64 | fi 65 | 66 | printf "Режим геоблокировки:\t" 67 | case "$GEOBLOCK_MODE" in 68 | "blacklist" | "whitelist") 69 | local geoset_name="ascn_geo_${GEOBLOCK_MODE}" 70 | local geoset_type="" 71 | [ "$GEOBLOCK_MODE" == "blacklist" ] && geoset_type="черный список" || geoset_type="белый список" 72 | 73 | local geo_directory="$IPSETS_DIRECTORY/geo" 74 | local available_countries_list="" 75 | local countries_list="" 76 | if [ ! -d "$geo_directory" ]; then 77 | countries_list="${RED_COLOR}${GEOBLOCK_COUNTRIES}${NO_STYLE}" 78 | else 79 | for country in $GEOBLOCK_COUNTRIES; do 80 | local subnets_file="$geo_directory/$country.txt" 81 | if [ ! -s "$subnets_file" ]; then 82 | [ -z "$countries_list" ] && countries_list="${RED_COLOR}${country}${NO_STYLE}" || countries_list="${countries_list} ${RED_COLOR}${country}${NO_STYLE}" 83 | else 84 | [ -z "$available_countries_list" ] && available_countries_list="${country}" || available_countries_list="${available_countries_list} ${country}" 85 | [ -z "$countries_list" ] && countries_list="${BOLD_TEXT}${country}${NO_STYLE}" || countries_list="${countries_list} ${BOLD_TEXT}${country}${NO_STYLE}" 86 | fi 87 | done 88 | fi 89 | 90 | if [ -n "$(ipset -q -n list $geoset_name)" ] && [ -n "$available_countries_list" ]; then 91 | printf "${GREEN_COLOR}$geoset_type${NO_STYLE}\n" 92 | else 93 | printf "${RED_COLOR}не работает${NO_STYLE}\n" 94 | fi 95 | printf "Страны геоблокировки:\t${countries_list}\n" 96 | ;; 97 | *) 98 | printf "${RED_COLOR}отключена${NO_STYLE}\n" 99 | ;; 100 | esac 101 | 102 | printf "Исключения по странам:\t" 103 | if [ -n "$GEO_EXCLUDE_COUNTRIES" ]; then 104 | local geo_directory="$IPSETS_DIRECTORY/geo" 105 | local available_countries_list="" 106 | local countries_list="" 107 | if [ ! -d "$geo_directory" ]; then 108 | countries_list="${RED_COLOR}${GEO_EXCLUDE_COUNTRIES}${NO_STYLE}" 109 | else 110 | for country in $GEO_EXCLUDE_COUNTRIES; do 111 | local subnets_file="$geo_directory/$country.txt" 112 | if [ ! -s "$subnets_file" ]; then 113 | [ -z "$countries_list" ] && countries_list="${RED_COLOR}${country}${NO_STYLE}" || countries_list="${countries_list} ${RED_COLOR}${country}${NO_STYLE}" 114 | else 115 | [ -z "$available_countries_list" ] && available_countries_list="${country}" || available_countries_list="${available_countries_list} ${country}" 116 | [ -z "$countries_list" ] && countries_list="${BOLD_TEXT}${country}${NO_STYLE}" || countries_list="${countries_list} ${BOLD_TEXT}${country}${NO_STYLE}" 117 | fi 118 | done 119 | fi 120 | printf "${countries_list}\n" 121 | else 122 | printf "${RED_COLOR}отключены${NO_STYLE}\n" 123 | fi 124 | fi 125 | else 126 | printf "${RED_COLOR}не запущен${NO_STYLE}\n" 127 | fi 128 | } 129 | 130 | get_ipset_member_text() { 131 | local record="записей" 132 | case $1 in 133 | *1?) true ;; 134 | *[2-4]) record="записи" ;; 135 | *1) record="запись" ;; 136 | esac 137 | echo "$1 $record" 138 | } 139 | 140 | show_ipsets() { 141 | case "$1" in 142 | ips | subnets | ndm_lockout | honeypot) 143 | if ascn_is_running; then 144 | if config_is_reloading; then 145 | print_message "error" "Просмотр данных недоступен во время обновления конфигурации Antiscan" 146 | else 147 | local text="адреса" 148 | local text_1="адресов" 149 | if [ "$1" == "subnets" ]; then 150 | text="подсети" 151 | text_1="подсетей" 152 | fi 153 | local ipset_data="$(ipset -q list ascn_$1 -s | tail -n +8)" 154 | local banned_count=0 155 | [ -n "$ipset_data" ] && banned_count="$(echo "$ipset_data" | grep -c '^')" 156 | if [ "$banned_count" -eq 0 ]; then 157 | print_message "console" "Заблокированные ${text} отсутствуют" 158 | else 159 | print_message "console" "Заблокированные ${text}:" 160 | echo "$ipset_data" 161 | print_message "console" "Заблокировано ${text_1}: ${banned_count}" 162 | fi 163 | fi 164 | else 165 | print_message "error" "Antiscan не запущен" 166 | fi 167 | ;; 168 | *) 169 | print_message "console" "Использование: $0 list {ips|subnets|ndm_lockout|honeypot}" 170 | ;; 171 | esac 172 | } 173 | 174 | show_version() { 175 | if [ "$1" == "opkg" ]; then 176 | local ascn_opkg_version="$(opkg list-installed antiscan | awk '{print $3}')" 177 | if [ -z "$ascn_opkg_version" ]; then 178 | print_message "console" "Не удалось определить версию пакета Antiscan" 179 | else 180 | print_message "console" "Версия Antiscan (OPKG): $ascn_opkg_version" 181 | fi 182 | else 183 | print_message "console" "Версия Antiscan: $ASCN_VERSION" 184 | fi 185 | } 186 | -------------------------------------------------------------------------------- /etc/antiscan/scripts/config.sh: -------------------------------------------------------------------------------- 1 | CONFIG_FILE="$ANTISCAN_DIR/ascn.conf" 2 | CONFIG_FILE_TEMP="/tmp/ascn.conf.tmp" 3 | 4 | ASCN_LOCK_FILE="/tmp/ascn.lock" 5 | 6 | create_lock_file() { 7 | echo "1" >"$ASCN_LOCK_FILE" 8 | } 9 | 10 | remove_lock_file() { 11 | if config_is_reloading; then 12 | rm "$ASCN_LOCK_FILE" 13 | fi 14 | } 15 | 16 | read_config() { 17 | case "$1" in 18 | edit | config | conf | crontab | cron) 19 | : 20 | ;; 21 | *) 22 | source "$CONFIG_FILE" 23 | check_config 24 | if [ -f "$CONFIG_FILE_TEMP" ]; then 25 | source "$CONFIG_FILE_TEMP" 26 | fi 27 | ;; 28 | esac 29 | } 30 | 31 | check_config() { 32 | if [ -z "$ISP_INTERFACES" ]; then 33 | print_message "error" "В ascn.conf не указаны интерфейсы!" 34 | exit 3 35 | fi 36 | 37 | [ -z "$ENABLE_IPS_BAN" ] && ENABLE_IPS_BAN=1 38 | [ -z "$ENABLE_HONEYPOT" ] && ENABLE_HONEYPOT=0 39 | 40 | if [ -z "$PORTS" ] && [ -z "$PORTS_FORWARDED" ]; then 41 | print_message "error" "В ascn.conf не указаны порты!" 42 | exit 3 43 | else 44 | local ports_count=0 45 | local ports_forwarded_count=0 46 | local ports_honeypot_count=0 47 | local need_to_exit=0 48 | if [ -n "$PORTS" ]; then 49 | ports_count=$( 50 | set -- $(echo "$PORTS" | tr ',:' ' ') 51 | echo $# 52 | ) 53 | fi 54 | if [ -n "$PORTS_FORWARDED" ]; then 55 | ports_forwarded_count=$( 56 | set -- $(echo "$PORTS_FORWARDED" | tr ',:' ' ') 57 | echo $# 58 | ) 59 | fi 60 | if [ "$ENABLE_HONEYPOT" == "1" ] && [ -n "$HONEYPOT_PORTS" ]; then 61 | ports_honeypot_count=$( 62 | set -- $(echo "$HONEYPOT_PORTS" | tr ',:' ' ') 63 | echo $# 64 | ) 65 | fi 66 | if [ "$ports_count" -gt 15 ]; then 67 | print_message "error" "Количество указанных портов превышает 15" 68 | need_to_exit=1 69 | fi 70 | if [ "$ports_forwarded_count" -gt 15 ]; then 71 | print_message "error" "Количество указанных переадресованных портов превышает 15" 72 | need_to_exit=1 73 | fi 74 | if [ "$ports_honeypot_count" -gt 15 ]; then 75 | print_message "error" "Количество указанных портов для ловушки превышает 15" 76 | need_to_exit=1 77 | fi 78 | [ "$need_to_exit" -eq 1 ] && exit 4 79 | fi 80 | 81 | if [ "$ENABLE_IPS_BAN" == "1" ]; then 82 | if [ -z "$RECENT_CONNECTIONS_TIME" ] || [ -z "$RECENT_CONNECTIONS_HITCOUNT" ] || [ -z "$RECENT_CONNECTIONS_LIMIT" ] || 83 | [ -z "$DIFFERENT_IP_THRESHOLD" ] || [ -z "$RECENT_CONNECTIONS_BANTIME" ] || [ -z "$DIFFERENT_IP_CANDIDATES_STORAGETIME" ] || [ -z "$SUBNETS_BANTIME" ]; then 84 | print_message "error" "В ascn.conf не указаны параметры работы Antiscan!" 85 | exit 3 86 | fi 87 | [ -z "$RULES_MASK" ] && RULES_MASK="255.255.255.255" 88 | if [ "$RECENT_CONNECTIONS_BANTIME" -gt 2147483 ] || [ "$DIFFERENT_IP_CANDIDATES_STORAGETIME" -gt 2147483 ] || [ "$SUBNETS_BANTIME" -gt 2147483 ]; then 89 | print_message "error" "Срок хранения записей в списках не может превышать 2147483 секунды" 90 | exit 4 91 | fi 92 | fi 93 | 94 | [ -z "$SAVE_IPSETS" ] && SAVE_IPSETS=0 95 | [ -z "$USE_CUSTOM_EXCLUDE_LIST" ] && USE_CUSTOM_EXCLUDE_LIST=0 96 | [ -z "$READ_NDM_LOCKOUT_IPSETS" ] && READ_NDM_LOCKOUT_IPSETS=0 97 | [ -z "$LOCKOUT_IPSET_BANTIME" ] && LOCKOUT_IPSET_BANTIME=0 98 | [ -z "$HONEYPOT_BANTIME" ] && HONEYPOT_BANTIME=0 99 | 100 | if [ "$LOCKOUT_IPSET_BANTIME" -gt 2147483 ] || [[ "$ENABLE_HONEYPOT" == "1" && "$HONEYPOT_BANTIME" -gt 2147483 ]]; then 101 | print_message "error" "Срок хранения записей в списках не может превышать 2147483 секунды" 102 | exit 4 103 | fi 104 | 105 | if [ -z "$CUSTOM_LISTS_BLOCK_MODE" ]; then 106 | CUSTOM_LISTS_BLOCK_MODE=0 107 | else 108 | case "$CUSTOM_LISTS_BLOCK_MODE" in 109 | 0 | blacklist | whitelist) 110 | : 111 | ;; 112 | *) 113 | print_message "error" "Указан недопустимый режим блокировки по пользовательским спискам" 114 | exit 4 115 | ;; 116 | esac 117 | fi 118 | 119 | if [ -z "$GEOBLOCK_MODE" ]; then 120 | GEOBLOCK_MODE=0 121 | else 122 | case "$GEOBLOCK_MODE" in 123 | 0 | blacklist | whitelist) 124 | : 125 | ;; 126 | *) 127 | print_message "error" "Указан недопустимый режим геоблокировки" 128 | exit 4 129 | ;; 130 | esac 131 | fi 132 | 133 | if [ -z "$GEO_EXCLUDE_COUNTRIES" ]; then 134 | GEO_EXCLUDE_COUNTRIES="" 135 | else 136 | echo "$GEO_EXCLUDE_COUNTRIES" | grep -Eq '^([A-Z]{2})( +[A-Z]{2} {0,})*$' 137 | local validation_result=$? 138 | if [ "$validation_result" -eq 0 ]; then 139 | local count=$( 140 | set -- $GEO_EXCLUDE_COUNTRIES 141 | echo $# 142 | ) 143 | if [ "$count" -gt 8 ]; then 144 | print_message "error" "Количество указанных стран-исключений превышает 8" 145 | exit 4 146 | fi 147 | else 148 | print_message "error" "Список стран-исключений содержит недопустимые символы" 149 | exit 3 150 | fi 151 | fi 152 | 153 | if [ -z "$IPSETS_DIRECTORY" ] && [[ "$SAVE_IPSETS" == "1" || "$GEOBLOCK_MODE" != "0" || "$GEO_EXCLUDE_COUNTRIES" != "" ]]; then 154 | print_message "error" "В ascn.conf не указан путь для сохранения ipset!" 155 | exit 3 156 | else 157 | if [ "$GEOBLOCK_MODE" != "0" ]; then 158 | if [ -z "$GEOBLOCK_COUNTRIES" ]; then 159 | print_message "error" "В ascn.conf не указаны страны для геоблокировки!" 160 | exit 3 161 | else 162 | echo "$GEOBLOCK_COUNTRIES" | grep -Eq '^([A-Z]{2})( +[A-Z]{2} {0,})*$' 163 | local validation_result=$? 164 | if [ "$validation_result" -eq 0 ]; then 165 | local count=$( 166 | set -- $GEOBLOCK_COUNTRIES 167 | echo $# 168 | ) 169 | if [ "$count" -gt 8 ]; then 170 | print_message "error" "Количество указанных стран для геоблокировки превышает 8" 171 | exit 4 172 | fi 173 | else 174 | print_message "error" "Список стран геоблокировки содержит недопустимые символы" 175 | exit 3 176 | fi 177 | fi 178 | fi 179 | fi 180 | 181 | if [ -z "$SAVE_ON_EXIT" ]; then 182 | SAVE_ON_EXIT=0 183 | fi 184 | } 185 | 186 | write_temp_config() { 187 | echo "ISP_INTERFACES=\"$ISP_INTERFACES\"" >"$CONFIG_FILE_TEMP" 188 | echo "PORTS=\"$PORTS\"" >>"$CONFIG_FILE_TEMP" 189 | echo "PORTS_FORWARDED=\"$PORTS_FORWARDED\"" >>"$CONFIG_FILE_TEMP" 190 | echo "ENABLE_HONEYPOT=\"$ENABLE_HONEYPOT\"" >>"$CONFIG_FILE_TEMP" 191 | echo "HONEYPOT_PORTS=\"$HONEYPOT_PORTS\"" >>"$CONFIG_FILE_TEMP" 192 | echo "HONEYPOT_BANTIME=\"$HONEYPOT_BANTIME\"" >>"$CONFIG_FILE_TEMP" 193 | echo "ENABLE_IPS_BAN=\"$ENABLE_IPS_BAN\"" >>"$CONFIG_FILE_TEMP" 194 | echo "RECENT_CONNECTIONS_TIME=$RECENT_CONNECTIONS_TIME" >>"$CONFIG_FILE_TEMP" 195 | echo "RECENT_CONNECTIONS_HITCOUNT=$RECENT_CONNECTIONS_HITCOUNT" >>"$CONFIG_FILE_TEMP" 196 | echo "RECENT_CONNECTIONS_LIMIT=$RECENT_CONNECTIONS_LIMIT" >>"$CONFIG_FILE_TEMP" 197 | echo "RECENT_CONNECTIONS_BANTIME=$RECENT_CONNECTIONS_BANTIME" >>"$CONFIG_FILE_TEMP" 198 | echo "DIFFERENT_IP_CANDIDATES_STORAGETIME=$DIFFERENT_IP_CANDIDATES_STORAGETIME" >>"$CONFIG_FILE_TEMP" 199 | echo "DIFFERENT_IP_THRESHOLD=$DIFFERENT_IP_THRESHOLD" >>"$CONFIG_FILE_TEMP" 200 | echo "SUBNETS_BANTIME=$SUBNETS_BANTIME" >>"$CONFIG_FILE_TEMP" 201 | echo "RULES_MASK=\"$RULES_MASK\"" >>"$CONFIG_FILE_TEMP" 202 | echo "IPSETS_DIRECTORY=\"$IPSETS_DIRECTORY\"" >>"$CONFIG_FILE_TEMP" 203 | echo "SAVE_IPSETS=$SAVE_IPSETS" >>"$CONFIG_FILE_TEMP" 204 | echo "SAVE_ON_EXIT=$SAVE_ON_EXIT" >>"$CONFIG_FILE_TEMP" 205 | echo "USE_CUSTOM_EXCLUDE_LIST=$USE_CUSTOM_EXCLUDE_LIST" >>"$CONFIG_FILE_TEMP" 206 | echo "CUSTOM_LISTS_BLOCK_MODE=\"$CUSTOM_LISTS_BLOCK_MODE\"" >>"$CONFIG_FILE_TEMP" 207 | echo "GEOBLOCK_MODE=\"$GEOBLOCK_MODE\"" >>"$CONFIG_FILE_TEMP" 208 | echo "GEOBLOCK_COUNTRIES=\"$GEOBLOCK_COUNTRIES\"" >>"$CONFIG_FILE_TEMP" 209 | echo "GEO_EXCLUDE_COUNTRIES=\"$GEO_EXCLUDE_COUNTRIES\"" >>"$CONFIG_FILE_TEMP" 210 | echo "READ_NDM_LOCKOUT_IPSETS=$READ_NDM_LOCKOUT_IPSETS" >>"$CONFIG_FILE_TEMP" 211 | echo "LOCKOUT_IPSET_BANTIME=$LOCKOUT_IPSET_BANTIME" >>"$CONFIG_FILE_TEMP" 212 | } 213 | 214 | destroy_temp_config() { 215 | IPSETS_DIRECTORY="" 216 | SAVE_IPSETS=0 217 | SAVE_ON_EXIT=0 218 | RULES_MASK="255.255.255.255" 219 | CUSTOM_LISTS_BLOCK_MODE=0 220 | USE_CUSTOM_EXCLUDE_LIST=0 221 | GEOBLOCK_MODE=0 222 | GEOBLOCK_COUNTRIES="" 223 | GEO_EXCLUDE_COUNTRIES="" 224 | READ_NDM_LOCKOUT_IPSETS=0 225 | LOCKOUT_IPSET_BANTIME=0 226 | HONEYPOT_BANTIME=0 227 | ENABLE_HONEYPOT=0 228 | ENABLE_IPS_BAN=1 229 | rm -f "$CONFIG_FILE_TEMP" 230 | source "$CONFIG_FILE" 231 | } 232 | 233 | config_is_reloading() { 234 | if [ -f "$ASCN_LOCK_FILE" ]; then 235 | return 0 236 | else 237 | return 1 238 | fi 239 | } 240 | 241 | reload_config() { 242 | if ! ascn_is_running; then 243 | print_message "error" "Antiscan не запущен" 244 | exit 1 245 | else 246 | if config_is_reloading; then 247 | print_message "error" "Процесс обновления конфигурации Antiscan уже запущен" 248 | exit 2 249 | elif geo_is_loading; then 250 | print_message "error" "Обновление конфигурации невозможно, пока идет загрузка списков подсетей стран" 251 | exit 2 252 | else 253 | create_lock_file 254 | 255 | local enable_ips_ban_old=$ENABLE_IPS_BAN 256 | local ascn_old_timeout=$RECENT_CONNECTIONS_BANTIME 257 | local ascn_candidates_old_timeout=$DIFFERENT_IP_CANDIDATES_STORAGETIME 258 | local ascn_subnets_old_timeout=$SUBNETS_BANTIME 259 | local custom_lists_block_mode_old="$CUSTOM_LISTS_BLOCK_MODE" 260 | local use_custom_exclude_list_old=$USE_CUSTOM_EXCLUDE_LIST 261 | local geoblock_mode_old="$GEOBLOCK_MODE" 262 | local geo_countries_old="$GEOBLOCK_COUNTRIES" 263 | local geo_exclude_countries_old="$GEO_EXCLUDE_COUNTRIES" 264 | local read_ndm_lockout_old="$READ_NDM_LOCKOUT_IPSETS" 265 | local ndm_lockout_timeout_old="$LOCKOUT_IPSET_BANTIME" 266 | local enable_honeypot_old="$ENABLE_HONEYPOT" 267 | local honeypot_ports_old="$HONEYPOT_PORTS" 268 | local honeypot_timeout_old="$HONEYPOT_BANTIME" 269 | local ipsets_dir_old="$IPSETS_DIRECTORY" 270 | 271 | remove_rules 272 | destroy_temp_config 273 | read_config 274 | write_temp_config 275 | update_cron 276 | 277 | if [ "$enable_ips_ban_old" == "1" ] && [ "$ENABLE_IPS_BAN" == "1" ]; then 278 | update_ipset_timeout "ascn_candidates" "$ascn_candidates_old_timeout" "$DIFFERENT_IP_CANDIDATES_STORAGETIME" "" 1 279 | update_ipset_timeout "ascn_ips" "$ascn_old_timeout" "$RECENT_CONNECTIONS_BANTIME" "" 1 280 | update_ipset_timeout "ascn_subnets" "$ascn_subnets_old_timeout" "$SUBNETS_BANTIME" "" 1 281 | else 282 | if [ "$enable_ips_ban_old" == "0" ] && [ "$ENABLE_IPS_BAN" == "1" ]; then 283 | create_ips_ban_ipsets 284 | elif [ "$enable_ips_ban_old" == "1" ] && [ "$ENABLE_IPS_BAN" == "0" ]; then 285 | export_ipsets 1 286 | destroy_ipsets 1 287 | fi 288 | fi 289 | 290 | reload_lockout_ipset "$read_ndm_lockout_old" "$READ_NDM_LOCKOUT_IPSETS" "$ndm_lockout_timeout_old" "$LOCKOUT_IPSET_BANTIME" 291 | reload_custom_ipset "$custom_lists_block_mode_old" "$CUSTOM_LISTS_BLOCK_MODE" 292 | reload_custom_exclude_ipset "$use_custom_exclude_list_old" "$USE_CUSTOM_EXCLUDE_LIST" 293 | 294 | reload_geo_ipset "$geoblock_mode_old" "$GEOBLOCK_MODE" "$geo_countries_old" "$GEOBLOCK_COUNTRIES" 295 | reload_geo_exclude_ipset "$geo_exclude_countries_old" "$GEO_EXCLUDE_COUNTRIES" 296 | 297 | reload_honeypot_ipset "$enable_honeypot_old" "$ENABLE_HONEYPOT" "$honeypot_timeout_old" "$HONEYPOT_BANTIME" 298 | 299 | show_no_protection_warning 300 | 301 | if [ -n "$IPSETS_DIRECTORY" ] && [ "$ipsets_dir_old" != "$IPSETS_DIRECTORY" ]; then 302 | msg_to_print="Перезапустите Antiscan, чтобы начать работу с новым каталогом хранения списков." 303 | printf "${YELLOW_COLOR}${msg_to_print}${NO_STYLE}\n" 304 | print_message "warning" "${msg_to_print}" 305 | fi 306 | 307 | add_rules 308 | remove_lock_file 309 | fi 310 | fi 311 | } 312 | -------------------------------------------------------------------------------- /etc/antiscan/scripts/geo.sh: -------------------------------------------------------------------------------- 1 | ASCN_GEO_LOCK_FILE="/tmp/ascn_geo.lock" 2 | ASCN_GEO_LOAD_ERROR_FILE="/tmp/ascn_geo_load_error" 3 | 4 | download_geo_subnets() { 5 | local load_failed=0 6 | local unavailable_countries="" 7 | local geo_directory="$1" 8 | local is_geo_reloading="$2" 9 | local countries="$3" 10 | local all_countries_list="" 11 | 12 | local SUBNETS_MIRROR="https://antiscan.ru/data/geo" 13 | 14 | if [ "$GEOBLOCK_MODE" == "blacklist" ] || [ "$GEOBLOCK_MODE" == "whitelist" ]; then 15 | all_countries_list="${GEOBLOCK_COUNTRIES}" 16 | fi 17 | if [ -n "$GEO_EXCLUDE_COUNTRIES" ]; then 18 | [ -z "$all_countries_list" ] && all_countries_list="${GEO_EXCLUDE_COUNTRIES}" || all_countries_list="${all_countries_list} ${GEO_EXCLUDE_COUNTRIES}" 19 | fi 20 | 21 | if [ ! -d "$geo_directory" ]; then 22 | unavailable_countries="${countries}" 23 | if ! mkdir "$geo_directory"; then 24 | print_message "error" "Не удалось создать директорию ${geo_directory}" 25 | return 2 26 | fi 27 | else 28 | local exclude_countries="" 29 | for country in $all_countries_list; do 30 | exclude_countries="${exclude_countries}! -name ${country}.txt " 31 | done 32 | for country_na in $countries; do 33 | local subnets_file="$geo_directory/$country_na.txt" 34 | if [ ! -s "$subnets_file" ]; then 35 | unavailable_countries="${unavailable_countries} ${country_na}" 36 | fi 37 | done 38 | find "$geo_directory" -maxdepth 1 $exclude_countries -type f -delete 39 | fi 40 | 41 | [ "$is_geo_reloading" == "1" ] && unavailable_countries="${countries}" 42 | 43 | if [ -n "$unavailable_countries" ]; then 44 | local curl_temp_file_path="/tmp/curl_geo_response.txt" 45 | for country in $unavailable_countries; do 46 | local geo_subnets_file="$geo_directory/$country.txt" 47 | [ -f "$geo_subnets_file" ] && rm "$geo_subnets_file" 48 | printf "Загрузка списка подсетей для страны ${BOLD_TEXT}${country}${NO_STYLE}... " 49 | local log_message="Загрузка списка подсетей для страны ${country}" 50 | local load_result=0 51 | load_failed=0 52 | curl --connect-timeout 30 --retry 5 --retry-delay 10 -fsS "https://stat.ripe.net/data/country-resource-list/data.json?resource=${country}&v4_format=prefix" -o "$curl_temp_file_path" 2>/tmp/ascn_curl1_error 53 | local curl1_result=$? 54 | local curl2_result=254 55 | local curl1_error_text="" 56 | local curl2_error_text="" 57 | if [ "$curl1_result" -ne 0 ]; then 58 | print_message "warning" "${log_message} завершилась неудачно" 0 59 | printf "${RED_COLOR}неудачно${NO_STYLE}\n" 60 | if [ -s "/tmp/ascn_curl1_error" ]; then 61 | curl1_error_text="$(cat /tmp/ascn_curl1_error)" 62 | print_message "error" "${curl1_error_text}" 1 63 | printf "${RED_COLOR}${curl1_error_text}${NO_STYLE}\n" 64 | fi 65 | printf "${YELLOW_COLOR}Пробуем загрузить ${NO_STYLE}${BOLD_TEXT}${country}${NO_STYLE}${YELLOW_COLOR} с зеркала...${NO_STYLE} " 66 | print_message "warning" "Пробуем загрузить ${country} с зеркала..." 0 67 | log_message="Повторная загрузка списка подсетей для страны ${country}" 68 | curl --connect-timeout 30 --retry 5 --retry-delay 10 -fsS "${SUBNETS_MIRROR}/${country}.json" -o "$curl_temp_file_path" 2>/tmp/ascn_curl2_error 69 | curl2_result=$? 70 | if [ "$curl2_result" -ne 0 ]; then 71 | print_message "warning" "${log_message} завершилась неудачно" 0 72 | printf "${RED_COLOR}неудачно${NO_STYLE}\n" 73 | if [ -s "/tmp/ascn_curl2_error" ]; then 74 | curl2_error_text="$(cat /tmp/ascn_curl2_error)" 75 | print_message "error" "${curl2_error_text}" 1 76 | printf "${RED_COLOR}${curl2_error_text}${NO_STYLE}\n\n" 77 | fi 78 | fi 79 | fi 80 | [ -f "/tmp/ascn_curl1_error" ] && rm -f "/tmp/ascn_curl1_error" 81 | [ -f "/tmp/ascn_curl2_error" ] && rm -f "/tmp/ascn_curl2_error" 82 | if [ "$curl1_result" -eq 0 ] || [ "$curl2_result" -eq 0 ]; then 83 | jq -r '.data.resources.ipv4[]' "$curl_temp_file_path" 2>"/tmp/ascn_jq_error" >"$geo_subnets_file" 84 | local parse_result=$? 85 | if [ "$parse_result" -ne 0 ]; then 86 | print_message "warning" "${log_message} завершилась неудачно" 0 87 | printf "${RED_COLOR}неудачно${NO_STYLE}\n" 88 | if [ -s "/tmp/ascn_jq_error" ]; then 89 | jq_error_text="$(cat /tmp/ascn_jq_error)" 90 | print_message "error" "${jq_error_text}" 1 91 | printf "${RED_COLOR}${jq_error_text}${NO_STYLE}\n\n" 92 | fi 93 | load_result=1 94 | load_failed=1 95 | else 96 | load_result=0 97 | fi 98 | [ -f "/tmp/ascn_jq_error" ] && rm -f "/tmp/ascn_jq_error" 99 | else 100 | load_result=1 101 | load_failed=1 102 | fi 103 | 104 | if [ "$load_result" -eq 0 ]; then 105 | if [ -s "$geo_subnets_file" ]; then 106 | printf "${GREEN_COLOR}успешно${NO_STYLE}\n" 107 | print_message "notice" "${log_message} выполнена успешно" 1 108 | else 109 | printf "${RED_COLOR}неудачно${NO_STYLE}\n" 110 | print_message "warning" "${log_message} завершилась неудачно" 0 111 | print_message "warning" "Файл ${country}.txt не содержит подсетей" 1 112 | fi 113 | fi 114 | done 115 | [ -f "$curl_temp_file_path" ] && rm "$curl_temp_file_path" 116 | 117 | if [ "$load_failed" -eq 1 ]; then 118 | create_geo_error_task 119 | return 1 120 | else 121 | remove_geo_error_task 122 | return 0 123 | fi 124 | fi 125 | } 126 | 127 | load_geo_ipset() { 128 | local geo_ipset_type="$1" 129 | local is_geo_reloading="$2" 130 | local is_trying_load_geo="$3" 131 | local no_lock_file="$4" 132 | local no_download="$5" 133 | local geo_directory="$IPSETS_DIRECTORY/geo" 134 | local temp_geo_ipset_path="/tmp/temp_geo_ipset.txt" 135 | local load_country_failed=0 136 | local countries="" 137 | local countries_string="" 138 | 139 | if [ "$geo_ipset_type" == "exclude" ]; then 140 | countries="$GEO_EXCLUDE_COUNTRIES" 141 | countries_string="стран-исключений" 142 | else 143 | countries="$GEOBLOCK_COUNTRIES" 144 | countries_string="стран геоблокировки" 145 | fi 146 | 147 | if [ -z "$no_lock_file" ] && geo_is_loading; then 148 | print_message "error" "Обновление списков подсетей стран уже запущено" 149 | else 150 | [ -z "$no_lock_file" ] && create_geo_lock_file 151 | 152 | if [ -z "$no_download" ]; then 153 | download_geo_subnets "$geo_directory" "$is_geo_reloading" "$countries" 154 | local download_exitcode=$? 155 | if [ "$download_exitcode" -eq 1 ]; then 156 | load_country_failed=1 157 | elif [ "$download_exitcode" -eq 2 ]; then 158 | load_country_failed=2 159 | fi 160 | fi 161 | 162 | if [ "$is_trying_load_geo" == "1" ] && [ "$load_country_failed" -eq 1 ]; then 163 | : 164 | else 165 | if [ -d "$geo_directory" ]; then 166 | if [[ "$is_geo_reloading" != "1" && "$is_trying_load_geo" != "1" ]] || [ -z "$(ipset -q -n list ascn_geo_$geo_ipset_type)" ]; then 167 | echo "create ascn_geo_$geo_ipset_type hash:net family inet hashsize 1024 maxelem 1000000" >"$temp_geo_ipset_path" 168 | fi 169 | for country in $countries; do 170 | local subnets_file="$geo_directory/$country.txt" 171 | if [ -s "$subnets_file" ]; then 172 | sed "s/^/add ascn_geo_$geo_ipset_type /" "$subnets_file" >>"$temp_geo_ipset_path" 173 | fi 174 | done 175 | fi 176 | 177 | if [ -f "$temp_geo_ipset_path" ]; then 178 | local geo_subnets_count="$(grep -c '^' "$temp_geo_ipset_path")" 179 | if [ "$geo_subnets_count" -gt 1 ]; then 180 | if [ "$is_geo_reloading" == "1" ] || [ "$is_trying_load_geo" == "1" ]; then 181 | [ -n "$(ipset -q -n list ascn_geo_$geo_ipset_type)" ] && ipset flush ascn_geo_$geo_ipset_type 182 | fi 183 | 184 | if ! ipset -! restore <"$temp_geo_ipset_path"; then 185 | print_message "error" "Не удалось импортировать список ascn_geo_$geo_ipset_type!" 186 | fi 187 | else 188 | print_message "error" "Загруженный список подсетей ${countries_string} пуст" 189 | fi 190 | rm "$temp_geo_ipset_path" 191 | else 192 | if [ "$load_country_failed" -eq 2 ]; then 193 | print_message "error" "Загрузка списка подсетей ${countries_string} завершилась неудачно" 194 | else 195 | print_message "error" "Файл со списком подсетей ${countries_string} не найден" 196 | fi 197 | fi 198 | fi 199 | [ -z "$no_lock_file" ] && remove_geo_lock_file 200 | fi 201 | } 202 | 203 | create_geo_error_task() { 204 | if [ ! -f "$ASCN_GEO_LOAD_ERROR_FILE" ]; then 205 | echo "1" >"$ASCN_GEO_LOAD_ERROR_FILE" 206 | if [ -s "$CRONTAB_FILE" ]; then 207 | if ! grep -q 'S99ascn retry_load_geo' "$CRONTAB_FILE"; then 208 | print_message "notice" "Создаем задачу для повторного обновления списка подсетей..." 209 | sed -n -i '\:S99ascn:p; $a0 */1 * * * /opt/etc/init.d/S99ascn retry_load_geo &' "$CRONTAB_FILE" 210 | update_cron 211 | fi 212 | else 213 | print_message "error" "Не удалось создать задачу для повторного обновления списка подсетей" 214 | fi 215 | fi 216 | } 217 | 218 | remove_geo_error_task() { 219 | if [ -f "$ASCN_GEO_LOAD_ERROR_FILE" ]; then 220 | rm "$ASCN_GEO_LOAD_ERROR_FILE" 221 | fi 222 | if [ -s "$CRONTAB_FILE" ]; then 223 | if grep -q 'S99ascn retry_load_geo' "$CRONTAB_FILE"; then 224 | print_message "notice" "Удаляем задачу повторного обновления списка подсетей..." 225 | sed -i '/S99ascn retry_load_geo/d' "$CRONTAB_FILE" 226 | update_cron 227 | fi 228 | fi 229 | } 230 | 231 | geo_is_loading() { 232 | if [ -f "$ASCN_GEO_LOCK_FILE" ]; then 233 | return 0 234 | else 235 | return 1 236 | fi 237 | } 238 | 239 | create_geo_lock_file() { 240 | echo "1" >"$ASCN_GEO_LOCK_FILE" 241 | } 242 | 243 | remove_geo_lock_file() { 244 | if geo_is_loading; then 245 | rm "$ASCN_GEO_LOCK_FILE" 246 | fi 247 | } 248 | 249 | reload_geo_ipset() { 250 | local old_geo_mode="$1" 251 | local new_geo_mode="$2" 252 | local old_countries_list="$3" 253 | local new_countries_list="$4" 254 | 255 | if [ "$old_geo_mode" != "$new_geo_mode" ] || [ "$old_countries_list" != "$new_countries_list" ]; then 256 | if [ "$old_geo_mode" != "0" ]; then 257 | [ -n "$(ipset -q -n list ascn_geo_$old_geo_mode)" ] && ipset destroy ascn_geo_$old_geo_mode 258 | fi 259 | if [ "$new_geo_mode" != "0" ] && [[ "$new_geo_mode" == "blacklist" || "$new_geo_mode" == "whitelist" ]]; then 260 | load_geo_ipset "$new_geo_mode" 0 261 | fi 262 | fi 263 | } 264 | 265 | reload_geo_exclude_ipset() { 266 | local old_exclude_countries_list="$1" 267 | local new_exclude_countries_list="$2" 268 | if [ "$old_exclude_countries_list" != "$new_exclude_countries_list" ]; then 269 | if [ -n "$old_exclude_countries_list" ]; then 270 | [ -n "$(ipset -q -n list ascn_geo_exclude)" ] && ipset destroy ascn_geo_exclude 271 | fi 272 | if [ -n "$new_exclude_countries_list" ]; then 273 | load_geo_ipset "exclude" 0 274 | fi 275 | fi 276 | } 277 | 278 | force_reload_geo_ipsets() { 279 | if geo_is_loading; then 280 | print_message "error" "Обновление списков подсетей стран уже запущено" 281 | return 1 282 | else 283 | local geo_directory="$IPSETS_DIRECTORY/geo" 284 | local geoblock_download_failed=1 285 | local geoexclude_download_failed=1 286 | create_geo_lock_file 287 | if [ "$GEOBLOCK_MODE" == "blacklist" ] || [ "$GEOBLOCK_MODE" == "whitelist" ]; then 288 | download_geo_subnets "$geo_directory" 1 "$GEOBLOCK_COUNTRIES" && geoblock_download_failed=0 289 | fi 290 | if [ -n "$GEO_EXCLUDE_COUNTRIES" ]; then 291 | download_geo_subnets "$geo_directory" 1 "$GEO_EXCLUDE_COUNTRIES" && geoexclude_download_failed=0 292 | fi 293 | if [ "$geoblock_download_failed" -eq 0 ] || [ "$geoexclude_download_failed" -eq 0 ]; then 294 | remove_rules 295 | [ "$geoblock_download_failed" -eq 0 ] && load_geo_ipset "$GEOBLOCK_MODE" 0 1 1 1 296 | [ "$geoexclude_download_failed" -eq 0 ] && load_geo_ipset "exclude" 0 1 1 1 297 | add_rules 298 | remove_geo_lock_file 299 | return 0 300 | else 301 | remove_geo_lock_file 302 | return 1 303 | fi 304 | fi 305 | } 306 | 307 | retry_load_geo() { 308 | if ascn_is_running; then 309 | if config_is_reloading; then 310 | print_message "error" "Загрузка подсетей стран недоступна во время обновления конфигурации Antiscan" 311 | exit 2 312 | else 313 | if [ "$GEOBLOCK_MODE" == "blacklist" ] || [ "$GEOBLOCK_MODE" == "whitelist" ] || [ -n "$GEO_EXCLUDE_COUNTRIES" ]; then 314 | if [ -f "$ASCN_GEO_LOAD_ERROR_FILE" ]; then 315 | force_reload_geo_ipsets && remove_geo_error_task 316 | else 317 | remove_geo_error_task 318 | fi 319 | else 320 | remove_geo_error_task 321 | fi 322 | fi 323 | else 324 | exit 1 325 | fi 326 | } 327 | -------------------------------------------------------------------------------- /etc/antiscan/scripts/ipsets.sh: -------------------------------------------------------------------------------- 1 | create_ipsets() { 2 | create_ips_ban_ipsets 3 | 4 | if [ "$READ_NDM_LOCKOUT_IPSETS" == "1" ] && [ -z "$(ipset -q -n list ascn_ndm_lockout)" ]; then 5 | add_ipset "ascn_ndm_lockout" "hash:ip" $LOCKOUT_IPSET_BANTIME 6 | fi 7 | 8 | if [ "$ENABLE_HONEYPOT" == "1" ] && [ -z "$(ipset -q -n list ascn_honeypot)" ]; then 9 | add_ipset "ascn_honeypot" "hash:ip" $HONEYPOT_BANTIME 10 | fi 11 | 12 | if [ "$CUSTOM_LISTS_BLOCK_MODE" == "blacklist" ] || [ "$CUSTOM_LISTS_BLOCK_MODE" == "whitelist" ]; then 13 | local ipset_custom_name="ascn_custom_${CUSTOM_LISTS_BLOCK_MODE}" 14 | if [ -z "$(ipset -q -n list $ipset_custom_name)" ]; then 15 | load_custom_ipset "$ipset_custom_name" 16 | fi 17 | fi 18 | 19 | if [ "$USE_CUSTOM_EXCLUDE_LIST" == "1" ] && [ -z "$(ipset -q -n list ascn_custom_exclude)" ]; then 20 | load_custom_ipset "ascn_custom_exclude" 21 | fi 22 | 23 | if [ "$GEOBLOCK_MODE" == "blacklist" ] || [ "$GEOBLOCK_MODE" == "whitelist" ]; then 24 | local ipset_geo_name="ascn_geo_${GEOBLOCK_MODE}" 25 | if [ -z "$(ipset -q -n list $ipset_geo_name)" ]; then 26 | load_geo_ipset "$GEOBLOCK_MODE" 0 27 | fi 28 | fi 29 | 30 | if [ -n "$GEO_EXCLUDE_COUNTRIES" ]; then 31 | if [ -z "$(ipset -q -n list ascn_geo_exclude)" ]; then 32 | load_geo_ipset "exclude" 0 33 | fi 34 | fi 35 | } 36 | 37 | create_ips_ban_ipsets() { 38 | if [ "$ENABLE_IPS_BAN" == "1" ]; then 39 | if [ -z "$(ipset -q -n list ascn_candidates)" ]; then 40 | add_ipset "ascn_candidates" "hash:ip" $DIFFERENT_IP_CANDIDATES_STORAGETIME 41 | fi 42 | 43 | if [ -z "$(ipset -q -n list ascn_ips)" ]; then 44 | add_ipset "ascn_ips" "hash:ip" $RECENT_CONNECTIONS_BANTIME 45 | fi 46 | 47 | if [ -z "$(ipset -q -n list ascn_subnets)" ]; then 48 | add_ipset "ascn_subnets" "hash:net" $SUBNETS_BANTIME 49 | fi 50 | fi 51 | } 52 | 53 | add_ipset() { 54 | local ipset_name="$1" 55 | local ipset_type="$2" 56 | local ipset_timeout="$3" 57 | local ipset_timeout_string="" 58 | local ipset_file="$IPSETS_DIRECTORY/ipset_$ipset_name.txt" 59 | local should_add_ipset=1 60 | 61 | case $ipset_name in 62 | "ascn_candidates") 63 | ipset_timeout_string=$([ "$DIFFERENT_IP_CANDIDATES_STORAGETIME" -ne 0 ] && echo "timeout "$DIFFERENT_IP_CANDIDATES_STORAGETIME"") 64 | ;; 65 | "ascn_ips") 66 | ipset_timeout_string=$([ "$RECENT_CONNECTIONS_BANTIME" -ne 0 ] && echo "timeout "$RECENT_CONNECTIONS_BANTIME"") 67 | ;; 68 | "ascn_subnets") 69 | ipset_timeout_string=$([ "$SUBNETS_BANTIME" -ne 0 ] && echo "timeout "$SUBNETS_BANTIME"") 70 | ;; 71 | "ascn_ndm_lockout") 72 | ipset_timeout_string=$([ "$LOCKOUT_IPSET_BANTIME" -ne 0 ] && echo "timeout "$LOCKOUT_IPSET_BANTIME"") 73 | ;; 74 | "ascn_honeypot") 75 | ipset_timeout_string=$([ "$HONEYPOT_BANTIME" -ne 0 ] && echo "timeout "$HONEYPOT_BANTIME"") 76 | ;; 77 | esac 78 | 79 | if [ "$SAVE_IPSETS" == "1" ] && [ -s "$ipset_file" ]; then 80 | local ipset_old_timeout=$(grep -oP '^create.*timeout\s+\K\d+$' "$ipset_file") 81 | if [ -z "$ipset_old_timeout" ]; then 82 | ipset_old_timeout=0 83 | fi 84 | update_ipset_timeout "$ipset_name" "$ipset_old_timeout" "$ipset_timeout" "$ipset_file" 0 85 | if restore_ipset_from_file "$ipset_name" "$ipset_file"; then 86 | should_add_ipset=0 87 | fi 88 | fi 89 | 90 | if [ "$should_add_ipset" -eq 1 ]; then 91 | ipset create $ipset_name $ipset_type $ipset_timeout_string 92 | fi 93 | } 94 | 95 | destroy_ipsets() { 96 | local ipsets_list="" 97 | if [ -z "$1" ]; then 98 | ipsets_list="ascn_candidates ascn_ips ascn_subnets ascn_custom_exclude ascn_custom_blacklist ascn_custom_whitelist ascn_geo_blacklist ascn_geo_whitelist ascn_geo_exclude ascn_ndm_lockout ascn_honeypot" 99 | else 100 | ipsets_list="ascn_candidates ascn_ips ascn_subnets" 101 | fi 102 | for set in $ipsets_list; do 103 | if [ -n "$(ipset -q -n list $set)" ]; then 104 | ipset destroy $set 105 | fi 106 | done 107 | } 108 | 109 | restore_ipset_from_file() { 110 | if ! ipset restore <"$2"; then 111 | print_message "error" "Не удалось импортировать ipset $1!" 112 | return 1 113 | else 114 | return 0 115 | fi 116 | } 117 | 118 | load_custom_ipset() { 119 | local custom_ipset_tempfile="/tmp/ipset_custom.txt" 120 | local custom_ipset_filename="$ANTISCAN_DIR/$1.txt" 121 | if [ -f "$custom_ipset_filename" ]; then 122 | local custom_file_size="$(ls -l "$custom_ipset_filename" | awk '{print $5}')" 123 | if [ "$custom_file_size" -gt 4 ]; then 124 | echo "create $1 hash:net family inet hashsize 1024 maxelem 65536" >"$custom_ipset_tempfile" 125 | sed "s/^/add $1 /" "$custom_ipset_filename" >>"$custom_ipset_tempfile" 126 | if ! ipset -! restore <"$custom_ipset_tempfile"; then 127 | print_message "error" "Не удалось импортировать список $1!" 128 | fi 129 | rm "$custom_ipset_tempfile" 130 | else 131 | print_message "error" "В файле $1 отсутствуют IP-адреса." 132 | print_message "error" "Добавьте их и перезапустите Antiscan." 133 | fi 134 | else 135 | echo >"$custom_ipset_filename" 136 | print_message "warning" "Файл $1 отсутствовал и был создан автоматически." 1 137 | print_message "error" "Добавьте в него IP-адреса и перезапустите Antiscan." 138 | fi 139 | } 140 | 141 | export_ipsets() { 142 | if [ "$SAVE_IPSETS" == "1" ]; then 143 | if ascn_is_running; then 144 | if config_is_reloading && [ -z "$1" ]; then 145 | print_message "error" "Экспорт ipset в файл недоступен во время обновления конфигурации Antiscan" 146 | return 2 147 | else 148 | local ipsets_list="" 149 | [ -z "$1" ] && ipsets_list="ascn_candidates ascn_ips ascn_subnets ascn_ndm_lockout ascn_honeypot" || ipsets_list="ascn_candidates ascn_ips ascn_subnets" 150 | for set_name in $ipsets_list; do 151 | local ipset_filename="$IPSETS_DIRECTORY/ipset_$set_name.txt" 152 | local banned_count="$(ipset -q list $set_name | tail -n +8 | grep -c '^')" 153 | if [ "$banned_count" -ne 0 ]; then 154 | if ! ipset save "$set_name" >"$ipset_filename"; then 155 | print_message "error" "Не удалось экспортировать ipset $set_name!" 156 | fi 157 | fi 158 | done 159 | fi 160 | else 161 | return 1 162 | fi 163 | fi 164 | } 165 | 166 | update_ipset_timeout() { 167 | local set_name="$1" 168 | local old_timeout="$2" 169 | local new_timeout="$3" 170 | local ipset_file="$4" 171 | local is_reloading="$5" 172 | 173 | if [ "$old_timeout" -ne "$new_timeout" ]; then 174 | 175 | if [ "$is_reloading" -eq 1 ]; then 176 | ipset_file="/tmp/${set_name}.txt" 177 | ipset save "$set_name" >"$ipset_file" 178 | fi 179 | 180 | if [ "$new_timeout" -eq 0 ]; then 181 | sed -i "s/ timeout [0-9]\+//" "$ipset_file" && print_message "notice" "Для списка $set_name удалено время хранения записей" 182 | else 183 | if [ $old_timeout -eq 0 ]; then 184 | sed -i "s/maxelem 65536\$/maxelem 65536 timeout $new_timeout/" "$ipset_file" && print_message "notice" "Для списка $set_name установлено время хранения записей $new_timeout" 185 | else 186 | sed -i "s/ timeout [0-9]\+/ timeout $new_timeout/" "$ipset_file" && print_message "notice" "Для списка $set_name обновлено время хранения записей. Было $old_timeout, стало $new_timeout" 187 | fi 188 | fi 189 | 190 | if [ "$is_reloading" -eq 1 ]; then 191 | ipset destroy "$set_name" 192 | restore_ipset_from_file "$set_name" "$ipset_file" 193 | rm "$ipset_file" 194 | fi 195 | fi 196 | } 197 | 198 | reload_custom_ipset() { 199 | local old_custom_mode="$1" 200 | local new_custom_mode="$2" 201 | if [ "$old_custom_mode" != "$new_custom_mode" ]; then 202 | if [ "$old_custom_mode" != "0" ]; then 203 | [ -n "$(ipset -q -n list ascn_custom_$old_custom_mode)" ] && ipset destroy ascn_custom_$old_custom_mode 204 | fi 205 | if [ "$new_custom_mode" == "blacklist" ] || [ "$new_custom_mode" == "whitelist" ]; then 206 | local new_custom_ipset_name="ascn_custom_$new_custom_mode" 207 | load_custom_ipset "$new_custom_ipset_name" 208 | fi 209 | fi 210 | } 211 | 212 | reload_custom_exclude_ipset() { 213 | local old_exclude_status="$1" 214 | local new_exclude_status="$2" 215 | if [ "$old_exclude_status" != "$new_exclude_status" ]; then 216 | if [ "$old_exclude_status" != "0" ]; then 217 | [ -n "$(ipset -q -n list ascn_custom_exclude)" ] && ipset destroy ascn_custom_exclude 218 | fi 219 | if [ "$new_exclude_status" != "0" ]; then 220 | load_custom_ipset "ascn_custom_exclude" 221 | fi 222 | fi 223 | } 224 | 225 | reload_lockout_ipset() { 226 | local old_lockout_state="$1" 227 | local new_lockout_state="$2" 228 | local old_lockout_timeout="$3" 229 | local new_lockout_timeout="$4" 230 | 231 | if [ "$old_lockout_state" != "$new_lockout_state" ] || [ "$old_lockout_timeout" != "$new_lockout_timeout" ]; then 232 | if [ "$old_lockout_state" != "0" ]; then 233 | [ -n "$(ipset -q -n list ascn_ndm_lockout)" ] && ipset destroy ascn_ndm_lockout 234 | fi 235 | if [ "$new_lockout_state" != "0" ]; then 236 | add_ipset "ascn_ndm_lockout" "hash:ip" $LOCKOUT_IPSET_BANTIME 237 | fi 238 | fi 239 | } 240 | 241 | reload_honeypot_ipset() { 242 | local old_hp_state="$1" 243 | local new_hp_state="$2" 244 | local old_hp_timeout="$3" 245 | local new_hp_timeout="$4" 246 | 247 | if [ "$old_hp_state" != "$new_hp_state" ] || [ "$old_hp_timeout" != "$new_hp_timeout" ]; then 248 | if [ "$old_hp_state" != "0" ]; then 249 | [ -n "$(ipset -q -n list ascn_honeypot)" ] && ipset destroy ascn_honeypot 250 | fi 251 | if [ "$new_hp_state" != "0" ]; then 252 | add_ipset "ascn_honeypot" "hash:ip" $HONEYPOT_BANTIME 253 | fi 254 | fi 255 | } 256 | 257 | flush_ipsets() { 258 | case "$1" in 259 | "candidates" | "ips" | "subnets" | "custom_whitelist" | "custom_blacklist" | "custom_exclude" | "geo" | "ndm_lockout" | "honeypot" | "") 260 | if ascn_is_running; then 261 | if config_is_reloading; then 262 | print_message "error" "Очистка списков недоступна во время обновления конфигурации Antiscan" 263 | elif geo_is_loading; then 264 | print_message "error" "Очистка списков недоступна во время загрузки подсетей стран" 265 | else 266 | local ipset_to_clear="$1" 267 | local question_text="" 268 | if [ -z "$ipset_to_clear" ]; then 269 | ipset_to_clear="candidates ips subnets geo_whitelist geo_blacklist ndm_lockout honeypot" 270 | question_text="Очистить все списки адресов? (Y/N): " 271 | else 272 | ipset_readable_name="" 273 | [ "$ipset_to_clear" == "candidates" ] && ipset_readable_name="список адресов-кандидатов на блокировку" 274 | [ "$ipset_to_clear" == "ips" ] && ipset_readable_name="список заблокированных адресов" 275 | [ "$ipset_to_clear" == "subnets" ] && ipset_readable_name="список заблокированных подсетей" 276 | [ "$ipset_to_clear" == "custom_whitelist" ] && ipset_readable_name="пользовательский белый список адресов" 277 | [ "$ipset_to_clear" == "custom_blacklist" ] && ipset_readable_name="пользовательский черный список адресов" 278 | [ "$ipset_to_clear" == "custom_exclude" ] && ipset_readable_name="пользовательский список адресов-исключений" 279 | [ "$ipset_to_clear" == "geo" ] && ipset_to_clear="geo_whitelist geo_blacklist geo_exclude" && ipset_readable_name="список подсетей стран" 280 | [ "$ipset_to_clear" == "ndm_lockout" ] && ipset_readable_name="список заблокированных адресов NDMS" 281 | [ "$ipset_to_clear" == "honeypot" ] && ipset_readable_name="список заблокированных ловушкой адресов" 282 | question_text="Очистить ${ipset_readable_name}? (Y/N): " 283 | fi 284 | if read -p "$question_text" confirm && [[ $confirm == [yY] || $confirm == [yY][eE][sS] ]]; then 285 | local custom_cleared_list="" 286 | local lockout_cleared="0" 287 | local ndmset_has_ips="0" 288 | for set in $ipset_to_clear; do 289 | local name="ascn_$set" 290 | [ -n "$(ipset -q -n list $name)" ] && ipset flush $name 291 | case "$set" in 292 | "geo_whitelist" | "geo_blacklist" | "geo_exclude") 293 | geo_cleared="1" 294 | rm -f "$IPSETS_DIRECTORY/geo/"* 295 | ;; 296 | "custom_whitelist" | "custom_blacklist" | "custom_exclude") 297 | if [ "$set" == "custom_blacklist" ]; then 298 | custom_cleared_list="blacklist" 299 | elif [ "$set" == "custom_whitelist" ]; then 300 | custom_cleared_list="whitelist" 301 | fi 302 | local custom_set_filename="$ANTISCAN_DIR/$name.txt" 303 | [ -f "$custom_set_filename" ] && >"$custom_set_filename" 304 | ;; 305 | *) 306 | local set_filename="$IPSETS_DIRECTORY/ipset_$name.txt" 307 | [ -f "$set_filename" ] && rm "$set_filename" 308 | [ "$set" == "ndm_lockout" ] && lockout_cleared="1" 309 | ;; 310 | esac 311 | done 312 | if [ "$SAVE_IPSETS" == "1" ]; then 313 | if [ "$custom_cleared_list" == "$CUSTOM_LISTS_BLOCK_MODE" ]; then 314 | delete_ipset "custom" "$custom_cleared_list" 315 | local list_name="" 316 | [ "$custom_cleared_list" == "blacklist" ] && list_name="черному" || list_name="белому" 317 | msg_to_print="Блокировка по пользовательскому $list_name списку отключена. Внесите новые записи и перезапустите Antiscan." 318 | printf "${YELLOW_COLOR}${msg_to_print}${NO_STYLE}\n" 319 | print_message "warning" "${msg_to_print}" 320 | fi 321 | if [ "$geo_cleared" == "1" ] && [[ "$GEOBLOCK_MODE" == "blacklist" || "$GEOBLOCK_MODE" == "whitelist" || -n "$GEO_EXCLUDE_COUNTRIES" ]]; then 322 | delete_ipset "geo" "$GEOBLOCK_MODE" 323 | msg_to_print="Перезапустите Antiscan, чтобы повторно загрузить список подсетей стран и начать их использование." 324 | printf "${YELLOW_COLOR}${msg_to_print}${NO_STYLE}\n" 325 | print_message "warning" "${msg_to_print}" 326 | fi 327 | fi 328 | if [ "$lockout_cleared" == "1" ] && [ "$READ_NDM_LOCKOUT_IPSETS" == "1" ]; then 329 | local ndm_ipsets="$(ipset list -n | grep -E '^_NDM_BFD_.+4$')" 330 | for ndm_ipset in $ndm_ipsets; do 331 | local ndm_ipset_data="$(ipset list $ndm_ipset | tail -n +8)" 332 | [ -n "$ndm_ipset_data" ] && ndmset_has_ips=1 333 | done 334 | if [ "$ndmset_has_ips" == "1" ]; then 335 | msg_to_print="Блокировка будет снята, когда система очистит собственные списки ограничения доступа." 336 | printf "${YELLOW_COLOR}${msg_to_print}${NO_STYLE}\n" 337 | print_message "warning" "${msg_to_print}" 338 | fi 339 | fi 340 | fi 341 | fi 342 | else 343 | print_message "error" "Antiscan не запущен" 344 | fi 345 | ;; 346 | *) 347 | print_message "console" "Использование: $0 flush [candidates|ips|subnets|custom_whitelist|custom_blacklist|custom_exclude|geo|ndm_lockout|honeypot]" 348 | ;; 349 | esac 350 | } 351 | 352 | delete_ipset() { 353 | remove_rules 354 | local set="ascn_${1}_${2}" 355 | if [ -n "$(ipset -q -n list $set)" ]; then 356 | ipset destroy $set 357 | fi 358 | add_rules 359 | } 360 | 361 | update_ipsets() { 362 | case "$1" in 363 | "custom" | "geo") 364 | if ascn_is_running; then 365 | if config_is_reloading; then 366 | print_message "error" "Обновление ipset недоступно во время обновления конфигурации Antiscan" 367 | exit 2 368 | else 369 | if [ "$1" == "custom" ]; then 370 | if [ "$CUSTOM_LISTS_BLOCK_MODE" == "blacklist" ] || [ "$CUSTOM_LISTS_BLOCK_MODE" == "whitelist" ]; then 371 | local ipset_custom_name="ascn_custom_${CUSTOM_LISTS_BLOCK_MODE}" 372 | if [ -n "$(ipset -q -n list $ipset_custom_name)" ]; then 373 | ipset flush "$ipset_custom_name" 374 | load_custom_ipset "$ipset_custom_name" 375 | else 376 | remove_rules 377 | load_custom_ipset "$ipset_custom_name" 378 | add_rules 379 | fi 380 | fi 381 | if [ "$USE_CUSTOM_EXCLUDE_LIST" == "1" ]; then 382 | if [ -n "$(ipset -q -n list ascn_custom_exclude)" ]; then 383 | ipset flush ascn_custom_exclude 384 | load_custom_ipset "ascn_custom_exclude" 385 | else 386 | remove_rules 387 | load_custom_ipset "ascn_custom_exclude" 388 | add_rules 389 | fi 390 | fi 391 | else 392 | force_reload_geo_ipsets 393 | fi 394 | fi 395 | else 396 | exit 1 397 | fi 398 | ;; 399 | *) 400 | print_message "console" "Использование: $0 update_ipsets {custom|geo}" 401 | ;; 402 | esac 403 | } 404 | 405 | read_ip_candidates() { 406 | if ascn_is_running; then 407 | if [ "$ENABLE_IPS_BAN" == "1" ]; then 408 | if config_is_reloading; then 409 | print_message "error" "Работа с адресами-кандидатами невозможна, пока идёт обновление конфигурации Antiscan" 410 | exit 2 411 | else 412 | if [ -n "$(ipset -q -n list ascn_ips)" ] && [ -n "$(ipset -q -n list ascn_candidates)" ] && [ -n "$(ipset -q -n list ascn_subnets)" ]; then 413 | local ipset_candidates="$(ipset save ascn_candidates | tail -n +2)" 414 | local ipset_ips="$(ipset save ascn_ips | tail -n +2)" 415 | 416 | local ipset_honeypot_ips="" 417 | if [ -n "$(ipset -q -n list ascn_honeypot)" ]; then 418 | ipset_honeypot_ips="$(ipset save ascn_honeypot | tail -n +2)" 419 | fi 420 | 421 | local ipset_combined_sorted="$(printf "${ipset_candidates}\n${ipset_ips}\n${ipset_honeypot_ips}" | sort -u)" 422 | 423 | if [ -n "$ipset_combined_sorted" ]; then 424 | [ -f "$ASCN_REGEXP_FILE" ] && rm "$ASCN_REGEXP_FILE" 425 | 426 | local sorted_candidates="$(echo "$ipset_combined_sorted" | grep -oE '([0-9]{1,3}[\.]){3}' | uniq -c)" 427 | local regexp_variable="" 428 | local ipset_variable="" 429 | 430 | while read count subnet_number; do 431 | if [ "$count" -ge "$DIFFERENT_IP_THRESHOLD" ]; then 432 | regexp_variable="${regexp_variable}${subnet_number}[0-9]{1,3}|" 433 | ipset_variable="${ipset_variable}add ascn_subnets ${subnet_number}0/24\n" 434 | fi 435 | done <