├── 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 <