# Защита хоста с помощью CrowdSec Вы наверняка использовали (или как минимум слышали) о Fail2Ban. Он очень широко распространён для защиты SSH на хостах, противодействия сканированию сайтов, легких DDoS-атак и "фонового bot-трафика". Fail2Ban существует с 2004 года и давно стал стандартом для защиты серверов. Но он слабо подходит для защиты кластеров Kubernetes, так поды обслуживающие внешний трафик (Ingress-контроллеры Traefik в случае k3s) могут находиться на разных узлах кластера. Если Fail2Ban заблокирует IP-адрес на одной ноде, то он не сможет защитить другие узлы кластера, так как они ничего не узнают о блокировках. Для защиты распределённых систем (в том числе кластеров Kubernetes) набирает популярность CrowdSec. Это проект с открытым исходным кодом, который, кроме обмена информацией об атаках между узлами (за периметром), использует и внешний краудсорсинг (Community Blocklist) для защиты от атак. Он собирает данные о блокировках и позволяет обмениваться этой информацией между всеми участниками сети (это отключаемая опция, и по умолчанию она отключена). Таким образом, CrowdSec может не только защитить все узлы кластера (благодаря обмену информацией за периметром), о блокировать IP-адреса, еще до их атаки на ваш сервер (если данные IP уже заблокированы другими участниками CrowdSec). А еще CrowdSec модульный, поддерживает сценарии (http-cms-scanning, sshd-bf и тому-подобное),в 60 раз быстрее Fail2Ban (он написан на Golang), работает с IPv6 и имеет интеграции с Traefik, Cloudflare, Nginx, k3s, Docker и другими инструментами. CrowdSec активно растёт в нише DevOps, облаков, контейнеров и кластеров Kubernetes. А еще он не требовательный по ресурсам (~100 МБ RAM) и подходит для Orange Pi. ---- ## Утановка CrowdSec В принципе, СrowdSec можно установить в кластер через Helm. Тогда он сам развернется на всех узлах кластера и это отличный вариант для защиты Traefik (HTTP-запросы, сценарии http-cms-scanning, http-probing) и контейнеризированных приложений (в моем случае [Gitea](../kubernetes/k3s-migrating-container-from-docker-to-kubernetes.md), [3x-ui](../kubernetes/k3s-3xui-pod.md) и тому подобного). Но мне нужно защитить еще и SSH самих узлов (узла) кластера. Поэтому план такой: * Хостовый CrowdSec (на одном или всех узлах кластера) использует тот же Local API (LAPI) через виртуальный IP (VIP) Keepalived для получения бан-листа и применяет его к SSH (через Firewall Bouncer) и через тот же LAPI сообщает о банах ssh-bt в CrowdSec Agent внутри k3s. * Кластерный CrowdSec Agent, внутри k3s, анализирует логи Traefik и создаёт решения (decisions) о бане IP. * Traefik Bouncer в k3s, также подключается к LAPI для защиты HTTP (для git.cube2.ru и других web-приложений). ---- ### CrowdSec на первом узле и защита SSH на хосте ---- #### Подготовка к установке CrowdSec Делаем обновляем список пактов и систему: ```shell sudo apt update sudo apt upgrade ``` Добавляем репозиторий CrowdSec и ключи репозитория: ```shell curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash ``` ---- #### Установка CrowdSec и проверка Устанавливаем CrowdSec: ```shell sudo apt install crowdsec ``` Увидим, в число прочего: ```text ... ... reating /etc/crowdsec/acquis.yaml INFO[2025-xx-xx xx:xx:xx] crowdsec_wizard: service 'ssh': /var/log/auth.log INFO[2025-xx-xx xx:xx:xx] crowdsec_wizard: using journald for 'smb' INFO[2025-xx-xx xx:xx:xx] crowdsec_wizard: service 'linux': /var/log/syslog /var/log/kern.log Machine 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' successfully added to the local API. API credentials written to '/etc/crowdsec/local_api_credentials.yaml'. Updating hub Downloading /etc/crowdsec/hub/.index.json Action plan: 🔄 check & update data files INFO[2025-05-17 17:56:45] crowdsec_wizard: Installing collection 'crowdsecurity/linux' downloading parsers:crowdsecurity/syslog-logs downloading parsers:crowdsecurity/geoip-enrich downloading https://hub-data.crowdsec.net/mmdb_update/GeoLite2-City.mmdb downloading https://hub-data.crowdsec.net/mmdb_update/GeoLite2-ASN.mmdb downloading parsers:crowdsecurity/dateparse-enrich downloading parsers:crowdsecurity/sshd-logs downloading scenarios:crowdsecurity/ssh-bf downloading scenarios:crowdsecurity/ssh-slow-bf downloading scenarios:crowdsecurity/ssh-cve-2024-6387 downloading scenarios:crowdsecurity/ssh-refused-conn downloading contexts:crowdsecurity/bf_base downloading collections:crowdsecurity/sshd downloading collections:crowdsecurity/linux enabling parsers:crowdsecurity/syslog-logs enabling parsers:crowdsecurity/geoip-enrich enabling parsers:crowdsecurity/dateparse-enrich enabling parsers:crowdsecurity/sshd-logs enabling scenarios:crowdsecurity/ssh-bf enabling scenarios:crowdsecurity/ssh-slow-bf enabling scenarios:crowdsecurity/ssh-cve-2024-6387 enabling scenarios:crowdsecurity/ssh-refused-conn enabling contexts:crowdsecurity/bf_base enabling collections:crowdsecurity/sshd enabling collections:crowdsecurity/linux ... ... ``` Как видим, CrowdSec сам определил, что у нас есть SSH и Linux (syslog и kern.log). Создан локальный API (LAPI) м логин/пароль для него записан в `/etc/crowdsec/local_api_credentials.yaml`. Далее CrowdSec загрузил парсеры, сценарии и коллекции для настройки защиты SSH и Linux. Проверим, что CrowdSec работает: ```shell sudo systemctl status crowdsec ``` Увидим что-то вроде: ```text ● crowdsec.service - Crowdsec agent Loaded: loaded (/lib/systemd/system/crowdsec.service; enabled; vendor preset: enabled) Active: active (running) since Sat xxxx-xx-xx xx:xx:xx XXX; 51min ago Main PID: 3357651 (crowdsec) Tasks: 14 (limit: 18978) Memory: 30.7M CPU: 18.233s CGroup: /system.slice/crowdsec.service ├─3357651 /usr/bin/crowdsec -c /etc/crowdsec/config.yaml └─3357715 journalctl --follow -n 0 _SYSTEMD_UNIT=smb.service Xxx xx xx:xx:xx xxxx systemd[1]: Starting Crowdsec agent... Xxx xx xx:xx:xx xxxx systemd[1]: Started Crowdsec agent. ``` Проверим версию CrowdSec: ```shell sudo cscli version ``` Увидим что-то вроде: ```text version: v1.6.8-debian-pragmatic-arm64-f209766e Codename: alphaga BuildDate: 2025-03-25_14:50:57 GoVersion: 1.24.1 Platform: linux libre2: C++ User-Agent: crowdsec/v1.6.8-debian-pragmatic-arm64-f209766e-linux ... ... ``` Проверим список установленных парсеров: ```shell sudo cscli parsers list ``` Увидим что-то вроде: ```text ────────────────────────────────────────────────────────────────────────────────────────────────────────────── PARSERS ────────────────────────────────────────────────────────────────────────────────────────────────────────────── Name 📦 Status Version Local Path ────────────────────────────────────────────────────────────────────────────────────────────────────────────── crowdsecurity/dateparse-enrich ✔️ enabled 0.2 /etc/crowdsec/parsers/s02-enrich/dateparse-enrich.yaml crowdsecurity/geoip-enrich ✔️ enabled 0.5 /etc/crowdsec/parsers/s02-enrich/geoip-enrich.yaml crowdsecurity/smb-logs ✔️ enabled 0.2 /etc/crowdsec/parsers/s01-parse/smb-logs.yaml crowdsecurity/sshd-logs ✔️ enabled 3.0 /etc/crowdsec/parsers/s01-parse/sshd-logs.yaml crowdsecurity/syslog-logs ✔️ enabled 0.8 /etc/crowdsec/parsers/s00-raw/syslog-logs.yaml crowdsecurity/whitelists ✔️ enabled 0.3 /etc/crowdsec/parsers/s02-enrich/whitelists.yaml ────────────────────────────────────────────────────────────────────────────────────────────────────────────── ``` Как видим `crowdsecurity/sshd-logs` доступны, а значит CrowdSec может парсить логи SSH. Проверим список установленных коллекций: ```shell sudo cscli collections list ``` Увидим что-то вроде: ```text ───────────────────────────────────────────────────────────────────────────────── COLLECTIONS ───────────────────────────────────────────────────────────────────────────────── Name 📦 Status Version Local Path ───────────────────────────────────────────────────────────────────────────────── crowdsecurity/linux ✔️ enabled 0.2 /etc/crowdsec/collections/linux.yaml crowdsecurity/smb ✔️ enabled 0.1 /etc/crowdsec/collections/smb.yaml crowdsecurity/sshd ✔️ enabled 0.6 /etc/crowdsec/collections/sshd.yaml ───────────────────────────────────────────────────────────────────────────────── ``` Видим, что `crowdsecurity/sshd` доступны. Проверим список установленных сценариев: ```shell sudo cscli scenarios list ``` Увидим что-то вроде: ```text SCENARIOS ─────────────────────────────────────────────────────────────────────────────────────────────────────── Name 📦 Status Version Local Path ─────────────────────────────────────────────────────────────────────────────────────────────────────── crowdsecurity/smb-bf ✔️ enabled 0.2 /etc/crowdsec/scenarios/smb-bf.yaml crowdsecurity/ssh-bf ✔️ enabled 0.3 /etc/crowdsec/scenarios/ssh-bf.yaml crowdsecurity/ssh-cve-2024-6387 ✔️ enabled 0.2 /etc/crowdsec/scenarios/ssh-cve-2024-6387.yaml crowdsecurity/ssh-refused-conn ✔️ enabled 0.1 /etc/crowdsec/scenarios/ssh-refused-conn.yaml crowdsecurity/ssh-slow-bf ✔️ enabled 0.4 /etc/crowdsec/scenarios/ssh-slow-bf.yaml ─────────────────────────────────────────────────────────────────────────────────────────────────────── ``` Сценарии `ssh-bf`, `crowdsecurity/ssh-slow-bf` (брутфорсинг и медленный брутфорсинг SSH), `crowdsecurity/ssh-cve-2024-6387` (защита от regreSSHion-атак на старые SSH-сервера) и crowdsecurity/ssh-refused-conn` (отказ соединения SSH) доступны. Кстати, обновлять все это богачество (парсеры, сценарии, коллекции и т.п.) можно командой: ```shell sudo cscli hub update ``` Проверим конфиги CrowdSec, и убедимся, что он анализирует логи SSH: ```shell sudo cat /etc/crowdsec/acquis.yaml ``` Должны увидеть вот такой блок: ```yaml filenames: - /var/log/auth.log labels: type: syslog --- ``` Если, вдруг, такого блока нет, добавьте его (лучше в начало) и перезапустим CrowdSec. Но обычно все уже настроено. Проверим, что CrowdSec анализирует логи SSH: ```shell sudo cscli metrics ``` Увидим что-то вроде: ```text ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ Acquisition Metrics │ ├────────────────────────┬────────────┬──────────────┬────────────────┬────────────────────────┬───────────────────┤ │ Source │ Lines read │ Lines parsed │ Lines unparsed │ Lines poured to bucket │ Lines whitelisted │ ├────────────────────────┼────────────┼──────────────┼────────────────┼────────────────────────┼───────────────────┤ │ file:/var/log/auth.log │ 628 │ - │ 628 │ - │ - │ │ file:/var/log/kern.log │ 2.78k │ - │ 2.78k │ - │ - │ │ file:/var/log/syslog │ 3.46k │ - │ 3.46k │ - │ - │ ╰────────────────────────┴────────────┴──────────────┴────────────────┴────────────────────────┴───────────────────╯ ... ... ``` Как видим, CrowdSec читает `/var/log/auth.log` (логи SSH). ---- #### Установка CrowdSec Firewall Bouncer -- блокировщик IP-адресов По мне, блокировки CrowdSec довольно беззубые. К счастью через "вышибалу" Firewall Bouncer можно блокировать IP-адреса по iptables (или nftables) и сделать CrowdSec злее fail2ban. Для этого нужно установить `crowdsec-firewall-bouncer-iptables`: ```shell sudo apt-get install crowdsec-firewall-bouncer-iptables ``` Проверим, что "вышибала" запустилась: ```shell sudo systemctl status crowdsec-firewall-bouncer ``` Увидим что-то вроде: ```text ● crowdsec-firewall-bouncer.service - The firewall bouncer for CrowdSec Loaded: loaded (/etc/systemd/system/crowdsec-firewall-bouncer.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2025-05-18 14:47:10 MSK; 723ms ago Process: 621537 ExecStartPre=/usr/bin/crowdsec-firewall-bouncer -c /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml -t (code=exited, status=0/SUCCESS) Process: 621674 ExecStartPost=/bin/sleep 0.1 (code=exited, status=0/SUCCESS) Main PID: 621622 (crowdsec-firewa) Tasks: 10 (limit: 18978) Memory: 7.4M CPU: 401ms CGroup: /system.slice/crowdsec-firewall-bouncer.service └─621622 /usr/bin/crowdsec-firewall-bouncer -c /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml May 18 14:47:04 opi5 systemd[1]: Starting The firewall bouncer for CrowdSec... May 18 14:47:10 opi5 systemd[1]: Started The firewall bouncer for CrowdSec. ``` Подключить его в CrowdSec: ```shell sudo cscli bouncers add firewall-bounce ``` Проверим, что "вышибала" добавлен: ```shell sudo cscli bouncers list ``` Увидим что-то вроде: ```text ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Name IP Address Valid Last API pull Type Version Auth Type ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── cs-firewall-bouncer-xxxx 127.0.0.1 ✔️ xxxx-xx-xxTxx:xx:xxZ crowdsec-firewall-bouncer v0.0.31-debian-pragmatic-xxxxxx... api-key firewall-bouncer ✔️ api-key ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ``` ---- #### Подключаем наш CrowdSec к обмену данными об атаках CrowdSec может обмениваться данными об атаках с другими участниками сети. Чтобы это сделать, нужно пойти [на сайт CrowdSec](https://crowdsec.net/) и зарегистрироваться. После подтверждения регистрации по email, в личном кабинете в самом низу, увидим строчку команды, типа: ```shell sudo cscli console enroll -e context хеш-идентификатор-вашего-аккаунта ``` Скопируем эту команду и выполняем в терминале. Увидим что-то вроде: ```text INFO manual set to true INFO context set to true INFO Enabled manual : Forward manual decisions to the console INFO Enabled tainted : Forward alerts from tainted scenarios to the console INFO Enabled context : Forward context with alerts to the console INFO Watcher successfully enrolled. Visit https://app.crowdsec.net to accept it. INFO Please restart crowdsec after accepting the enrollment. ``` Как видим, нужно перезапустить CrowdSec: ```shell sudo systemctl restart crowdsec ``` Теперь нужно снова зайти в личный кабинет CrowdSec и подтвердить подключение Security Engine. Все! Подключение локального CrowdSec к Community Blocklist завершено. В личном кабинете можно посмотреть статистику (по каждому Security Engine, ведь на один аккаунт можно подключить несколько хостов с CrowdSec) и даже управлять фильтрами и сценариями (это не точно). ![crowdsec--security-engine-registration.png](../images/crowdsec--security-engine-registration.png) Проверим, что CrowdSec получает блокировки через Community Blocklist API (CAPI): ```shell sudo cscli metrics ``` Увидим что-то типа: ```text ... ... ╭──────────────────────────────────────────╮ │ Local API Decisions │ ├────────────────┬────────┬────────┬───────┤ │ Reason │ Origin │ Action │ Count │ ├────────────────┼────────┼────────┼───────┤ │ generic:scan │ CAPI │ ban │ 3222 │ │ smb:bruteforce │ CAPI │ ban │ 427 │ │ ssh:bruteforce │ CAPI │ ban │ 10033 │ │ ssh:exploit │ CAPI │ ban │ 1315 │ ╰────────────────┴────────┴────────┴───────╯ ... ``` Как видим, CrowdSec получает блокировки. Если очень интересно, можно посмотреть, что именно и почему блокируется (например, `ssh:bruteforce`): ```shell sudo cscli decisions list --origin CAPI ``` Увидим длиннющий список, примерно такого содержания: ```text ╭───────┬────────┬────────────────────────────────────┬────────────────┬────────┬─────────┬────┬────────┬────────────┬──────────╮ │ ID │ Source │ Scope:Value │ Reason │ Action │ Country │ AS │ Events │ expiration │ Alert ID │ ├───────┼────────┼────────────────────────────────────┼────────────────┼────────┼─────────┼────┼────────┼────────────┼──────────┤ ..... .... ...................... .............. ... . ......... . │ ..... │ CAPI │ Ip:129.211.204.27 │ ssh:bruteforce │ ban │ │ │ 0 │ 79h15m46s │ 1 │ │ ..... │ CAPI │ Ip:128.199.124.27 │ ssh:bruteforce │ ban │ │ │ 0 │ -1h44m14s │ 1 │ │ ..... │ CAPI │ Ip:Ip:2602:80d:1006::76 │ ssh:bruteforce │ ban │ │ │ 0 │ 48h15m46s │ 1 │ │ ..... │ CAPI │ Ip:123.58.213.127 │ ssh:bruteforce │ ban │ │ │ 0 │ 160h15m46s │ 1 │ ╰───────┴────────┴────────────────────────────────────┴────────────────┴────────┴─────────┴────┴────────┴────────────┴──────────╯ ``` ---- #### Настройка Whitelist (белого списка) Чтобы не заблокировать себя (случайно) нужно создать в Whitelist (белый список). Например, сделаем `home_whitelist` (имя списка, таких списков может быть несколько, и ```shell sudo cscli allowlist create home_whitelist -d 'Мой домашний whitelist' ``` Теперь добавим в него свои домашнюю подсеть или IP-адрес (через пробел можно указать несколько адресов или подсетей): ```shell sudo cscli allowlist add home_whitelist 192.168.1.0/24 XXX.XXX.XXX.XXX ```` Проверим, что все добавилось: ```shell sudo cscli allowlist inspect home_whitelist ``` Увидим что-то вроде: ```text ────────────────────────────────────────────── Allowlist: home_whitelist ────────────────────────────────────────────── Name home_whitelist Description Мой домашний whitelist Created at 2025-05-17T21:00:13.042Z Updated at 2025-05-17T21:01:29.090Z Managed by Console no ────────────────────────────────────────────── ─────────────────────────────────────────────────────────────── Value Comment Expiration Created at ─────────────────────────────────────────────────────────────── 192.168.1.0/24 never 2025-05-17T21:00:13.042Z XXX.XXX.XXX.XXX never 2025-05-17T21:00:13.042Z XXX.XXX.XXX.XXX never 2025-05-17T21:00:13.042Z ... ... ─────────────────────────────────────────────────────────────── ``` Еще один способ отредактировать (создать) Whitelist-конфиг парсера, который мы получили командой `sudo cscli parsers list`. Конфиг `/etc/crowdsec/parsers/s02-enrich/whitelists.yaml` довольно простой, если его отредактировать (добавить нужные IP-адреса, подсети или даже доменные имена), а затем перезапустить CrowdSec -- получим тот же результат. Только управлять через списки (allowlist) удобнее. [См. документацию](https://doc.crowdsec.net/u/getting_started/post_installation/whitelists/). ---- #### Настройка Firewall Bouncer (блокировщик IP-адресов) ---- ##### Сценарии блокировок Когда мы проверяли установку CrowdSec, и проверим список сценариев `shell sudo cscli scenarios list`, то нам был показан список yaml-манифестов c конфигурациями сценариев блокировок. Эти **сценарии занимаются распознаванием атак**, в частности касающихся SSH: * `/etc/crowdsec/scenarios/ssh-bf.yaml` -- брутфорс SSH * `/etc/crowdsec/scenarios/ssh-slow-bf.yaml` -- медленный брутфорс SSH * `/etc/crowdsec/scenarios/ssh-cve-2024-6387.yaml` -- regreSSHion-атака (атаки уязвимости SSH-серверов старых версий) * `/etc/crowdsec/scenarios/ssh-refused-conn.yaml` -- отказ соединения SSH, защищает от сканеров, которые ищут открытые SSH-порты (на очень актуально, если у вас SSH открыт по стандартном 22-порту). В некоторых манифестах может быть несколько блоков конфигурации блокировок для разных сценариев атак "зловредов". Например, в `ssh-bf.yaml` есть блоки `crowdsecurity/ssh-bf` (для тупого брутфорса) и `crowdsecurity/ssh-bf_user-enum` (для перебора пользователей). Меняем "беззубые" параметры, на что-то более серьезное. Открываем на редактирование, например, `ssh-bf.yaml`: ```shell sudo nano /etc/crowdsec/scenarios/ssh-bf.yaml ``` Увидим что-то типа: ```yaml # ssh bruteforce type: leaky name: crowdsecurity/ssh-bf description: "Detect ssh bruteforce" filter: "evt.Meta.log_type == 'ssh_failed-auth'" leakspeed: "10s" references: - http://wikipedia.com/ssh-bf-is-bad capacity: 5 groupby: evt.Meta.source_ip blackhole: 1m reprocess: true labels: service: ssh confidence: 3 spoofable: 0 classification: - attack.T1110 label: "SSH Bruteforce" behavior: "ssh:bruteforce" remediation: true --- # ssh user-enum type: leaky name: crowdsecurity/ssh-bf_user-enum description: "Detect ssh user enum bruteforce" filter: evt.Meta.log_type == 'ssh_failed-auth' groupby: evt.Meta.source_ip distinct: evt.Meta.target_user leakspeed: 10s capacity: 5 blackhole: 1m labels: service: ssh remediation: true confidence: 3 spoofable: 0 classification: - attack.T1589 behavior: "ssh:bruteforce" label: "SSH User Enumeration" ``` Что тут происходит: * Сценарий `crowdsecurity/ssh-bf`: * Тип: `leaky` -- leaky bucket — алгоритм "дырявое ведро", считающий события в окне времени. Метафора "дырявого ведра" в том, что из дырок на дне идет утечка со скоростью одна попытка за `leakspeed`. Емкость ведра равна `capacity`. Когда "ведро" было пустм, в него можно было поместить `capacity` событий, и после по одому событию в `leakspeed`. Если ведро переполнено событиями, то включается `blackhole` (черная дыра) и события игнорируются в течении `blackhole` времени. * Фильтр: `evt.Meta.log_type == 'ssh_failed-auth'` -- ловит неудачные попытки входа по SSH из `/var/log/auth.log`. * Логика: * `groupby: evt.Meta.source_ip` -- группирует события по IP атакующего. * `leakspeed: 10s` -- "окно времени" — 10 секунд (каждые 10 сек разрешена одна попытка). * `capacity: 5` -- Бан после 5 неудачных попыток. * `blackhole: 1m` -- Бан на 1 минуту. * Сценарий `crowdsecurity/ssh-bf_user-enum`: * Тип тот же. * Фильтр тот же. * Логика: * `distinct: evt.Meta.target_user` -- считает попытки с разными пользователями (root, admin, pi, orangepi и т.д.). * `leakspeed: 10s` -- "окно времени" — 10 секунд. * `capacity: 5` -- Бан после 5 разных пользователей за 10 секунд. * `blackhole: 1m` -- Бан на 1 минуту. Как видим в обоих случаях бан срабатывает после пяти попыток за десять секунд, и блокировка всего на минуту. Конечно, брутфорсеры -- это быстрые атаки, но "быстрота" понятие относительное. Я выставляю: * `leakspeed: 10m` * `capacity: 2` * `blackhole: 1h` И считаю, что это довольно мягко. Но чтоб случайно не заблокировать себя, когда буду подключаться с внешнего IP не из белого списка (например, по мобильному интернету) -- это разумный компромисс. После редактирования файла, нужно перезапустить CrowdSec, чтоб он применил изменения: ```shell sudo systemctl restart crowdsec sudo systemctl restart crowdsec-firewall-bouncer ``` Другие сценарии можно настроить по аналогии. "Злость" управляется параметрами `leakspeed`, `capacity` и `blackhole`. Но имейте в виду: не стоит менять много параметров одновременно. Настройки разных сценариев могут конфликтовать друг другом, и тогда CrowdSec не запустится. После перезапуска CrowdSec: ```shell sudo systemctl restart crowdsec ``` И еще, экспериментально я обнаружил, что настройки дней, например `2d` недопустимы. Надо указывать `48h` (48 часов), и в целом не нужно сразу месть настройки сразу во всех сценариях. Они могут конфликтовать друг с другом, и CrowdSec не перезапуститься. Проверим, что CrowdSec начал банить на основании настроенных правил (особо ждать не придется, зловреды попадутся уже через пару минут): ```shell sudo cscli decisions list ``` Увидим что-то типа: ```text ╭───────┬──────────┬───────────────────┬────────────────────────────────┬─────┬────┬────────────────────────┬────────┬────────────┬──────────╮ │ ID │ Source │ Scope:Value │ Reason │ Act │ Co │ AS │ Events │ expiration │ Alert ID │ ├───────┼──────────┼───────────────────┼────────────────────────────────┼─────┼────┼────────────────────────┼────────┼────────────┼──────────┤ │ 30004 │ crowdsec │ Ip:39.98.38.186 │ crowdsecurity/ssh-slow-bf │ ban │ CN │ 37963 Hangzhou Alibaba │ 11 │ 3h54m49s │ 6 │ │ 30002 │ crowdsec │ Ip:165.246.104.64 │ crowdsecurity/ssh-bf │ ban │ KR │ 9317 INHA UNIVERSITY │ 3 │ 3h50m0s │ 4 │ │ 90210 │ crowdsec │ Ip:180.10.143.248 │ crowdsecurity/ssh-bf_user-enum │ ban │ CN │ 4134 Chinanet │ 3 │ 3h6m38s │ 216 │ ╰───────┴──────────┴───────────────────┴────────────────────────────────┴─────┴────┴────────────────────────┴────────┴────────────┴──────────╯ ``` ---- ##### Время блокировок Сценарии занимаются распознаванием угроз, но самими блокировками они не занимаются. Блокировки настроены по умолчанию на четыре часа, и это указано в профилях `/etc/crowdsec/profiles.yaml`. Чтобы изменить время, на которое "зловред" отправляется в бан, нужно отредактировать этот файл. По умолчанию он вот такой: ```yaml name: default_ip_remediation #debug: true filters: - Alert.Remediation == true && Alert.GetScope() == "Ip" decisions: - type: ban duration: 4h #duration_expr: Sprintf('%dh', (GetDecisionsCount(Alert.GetValue()) + 1) * 4) # notifications: # - slack_default # Set the webhook in /etc/crowdsec/notifications/slack.yaml before enabling this. # - splunk_default # Set the splunk url and token in /etc/crowdsec/notifications/splunk.yaml before enabling this. # - http_default # Set the required http parameters in /etc/crowdsec/notifications/http.yaml before enabling this. # - email_default # Set the required email parameters in /etc/crowdsec/notifications/email.yaml before enabling this. on_success: break --- name: default_range_remediation #debug: true filters: - Alert.Remediation == true && Alert.GetScope() == "Range" decisions: - type: ban duration: 4h #duration_expr: Sprintf('%dh', (GetDecisionsCount(Alert.GetValue()) + 1) * 4) # notifications: # - slack_default # Set the webhook in /etc/crowdsec/notifications/slack.yaml before enabling this. # - splunk_default # Set the splunk url and token in /etc/crowdsec/notifications/splunk.yaml before enabling this. # - http_default # Set the required http parameters in /etc/crowdsec/notifications/http.yaml before enabling this. # - email_default # Set the required email parameters in /etc/crowdsec/notifications/email.yaml before enabling this. on_success: break ``` Как видим, по умолчанию блокировка на 4 часа. Чтобы изменить время блокировок, нужно отредактировать `duration: 4h` на нужное. Но в конфигурации есть "заготовка" для динамического времени блокировок: `duration_expr: Sprintf('%dh', (GetDecisionsCount(Alert.GetValue()) + 1) * 4)` -- каждый раз, когда зловред попадает в бан, время блокировки увеличивается на 4 часа. То есть, если зловред попался в бан 5 раз, то его блокировка будет 20 часов. И так далее (формулу, при желании, можно изменить). Это то, что нам нужно. Имейте в виду, что подключение `duration_expr` исключает возможность указать `duration` (время блокировки) в секции `decisions`. Таким образом получаем вот такой конфиг: ```yaml name: default_ip_remediation #debug: true filters: - Alert.Remediation == true && Alert.GetScope() == "Ip" decisions: - type: ban # duration: 4h duration_expr: Sprintf('%dh', (GetDecisionsCount(Alert.GetValue()) + 1) * 4) on_success: break --- name: default_range_remediation #debug: true filters: - Alert.Remediation == true && Alert.GetScope() == "Range" decisions: - type: ban duration: 5h on_success: break ``` Можно добавлять и свои правила. Например, для более длительных блокировок медленных брутфорсов, добавим в конце: ```yaml --- name: ssh_slow_bf_remediation filters: - Alert.Remediation == true && Alert.Scenario == "crowdsecurity/ssh-slow-bf" decisions: - type: ban duration: 10h on_success: break ``` После сохранения конфига, перезапустим CrowdSec: ```shell sudo systemctl restart crowdsec ``` И убедимся, что время блокировки увеличилось: ```shell sudo cscli decisions list ``` ```text ╭────────┬──────────┬───────────────────┬──────────────────────┬────────┬─────────┬──────────────────────┬────────┬────────────┬──────────╮ │ ID │ Source │ Scope:Value │ Reason │ Action │ Country │ AS │ Events │ expiration │ Alert ID │ ├────────┼──────────┼───────────────────┼──────────────────────┼────────┼─────────┼──────────────────────┼────────┼────────────┼──────────┤ │ 165247 │ crowdsec │ Ip:165.246.104.64 │ crowdsecurity/ssh-bf │ ban │ KR │ 9317 INHA UNIVERSITY │ 3 │ 91h25m24s │ 258 │ ╰────────┴──────────┴───────────────────┴──────────────────────┴────────┴─────────┴──────────────────────┴────────┴────────────┴──────────╯ ``` ---- #### Web-панель Плюсом CrowdSec является то, что благодаря обмену информацией о блокировках, в личном кабинете на сайте CrowdSec можно посмотреть ваши локальные блокировки через веб-интерфейсе: ![crowdsec--security-panel.png](../images/crowdsec--security-panel.png) ---- #### Управление блокировками Можно добавить бан вручную (по умолчанию: `duration:4h` и `type:ban`): ```shell sudo cscli decisions add -i xxx.xxx.xxx.xxx sudo cscli decisions add --ip xxx.xxx.xxx.xxx --duration 24h --reason "любопытный безопасник" sudo cscli decisions add --ip xxx.xxx.xxx.xxx --reason "web bruteforce" --type captcha ``` Снять блокировку отдельного IP, подсети (диапазона) или вообще все: ```shell sudo cscli decisions delete --ip xxx.xxx.xxx.xxx sudo cscli decisions delete --range yyy.yyy.yyyy.yyy/24 sudo cscli decisions delete --all ``` #### Блокировки по GeoIP Проверим, что у нас есть парсер на основе GeoIP: ```shell sudo cscli parsers lis ``` Увидим в числе прочих: ```text PARSERS ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Name 📦 Status Version Local Path ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── crowdsecurity/geoip-enrich ✔️ enabled 0.5 /etc/crowdsec/parsers/s02-enrich/geoip-enrich.yaml ``` Он обогащает события (events) GeoIP-информацией: страна, город, ASN, континент и так далее, но сам ничего не блокирует — он просто добавляет поля к событиям. Но это делает возможным создание собственных фильтров и сценариев, завязанных на GeoIP. Используется двухбуквенный код страны (стандарт ISO-3166-1 alpha-2). У меня на хосте половина зловредов из Китая и Кореи. За ними, с большим отрывом, Индия и Индонезия. Вот честно, ничего против этих стран не имею, от из этих регионов 80% всех атак на мой SSH. Создаем свой сценарий: ```shell sudo nano /etc/crowdsec/scenarios/ban-cn--geoip.yaml ``` И вставим туда: ```yaml # /etc/crowdsec/scenarios/ban-cn--geoip.yaml # Бан по GeoIP для Китая и Кореи type: trigger name: local/ban-russian-ips description: "Ban any IP from China & Korea" filter: evt.Meta.geoip_country in ['CN', 'KR'] and evt.Meta.service == 'ssh' groupby: evt.Meta.source_ip labels: country_ban: CN remediation: true classification: - abuse behavior: "geoip:ban" confidence: 5 label: "GeoIP Country Ban" manual: true ``` Как видно, это `trigger`-сценарий, он срабатывает при одиночном совпадении, без необходимости "накопить события", как в `leaky`. И бан срабатывает если "зловред" лезет в сервис `ssh`. Перезапустим CrowdSec: ```shell sudo systemctl restart crowdsec ``` Теперь CrowdSec будет автоматически блокировать все новые IP из указанных стран при появлении их в логах. И если честно, можно вообще все страны забанить, кроме тех, где бываю в отпуске. Нечего им делать на моем сервере. :)