Два уровня защиты: встроенные лимиты Xray и системный Fail2ban с банами через UFW. Разбираем, как это работает и как настроить.
Прокси-сервер, доступный из интернета, постоянно подвергается сканированию и попыткам подбора. Даже если сам протокол устойчив к атакам, тысячи неудачных подключений создают шум и нагрузку. Fail2ban автоматически банит IP-адреса, которые превышают порог неудачных попыток, на уровне фаервола — до того, как они дойдут до Xray.
В 3x-ui есть два независимых механизма: встроенный (на уровне Xray) и системный (Fail2ban + UFW). Они дополняют друг друга.
В настройках клиента можно задать limitIp — максимальное число одновременных IP. Если клиент подключается с большего числа адресов, Xray временно блокирует новые соединения. Это не бан на уровне фаервола, а ограничение внутри самого прокси.
Преимущество: работает без внешних зависимостей. Ограничение: защищает только от «расшаривания» аккаунта, но не от сканеров, которые стучатся на порт без валидных учётных данных.
3x-ui пишет попытки подключения в /var/log/x-ui/3xipl.log. Формат строк пригоден для разбора фильтром Fail2ban.
Fail2ban читает лог 3x-ui и при превышении порога вызывает действие — обычно бан через UFW или iptables. В отличие от встроенного лимита, здесь IP блокируется на уровне фаервола: пакеты отбрасываются ещё до Xray.
[3x-ipl]
enabled = true
filter = 3x-ipl
action = 3x-ipl
logpath = /var/log/x-ui/3xipl.log
maxretry = 1
findtime = 32
bantime = 30m
maxretry = 1 означает, что достаточно одной неудачной попытки для бана (если фильтр ловит именно «неудачную попытку»). findtime = 32 — окно в секундах.
Если перед панелью стоит Nginx, имеет смысл добавить джейл для сканеров веб-уязвимостей. Он читает /var/log/nginx/access.log и банит IP, которые запрашивают типичные сканерские пути (/.env, /wp-login.php, //xmlrpc.php и т.д.) с кодами 301/302/400/401/403/404.
Recidive — «джейл для джейлов». Он читает /var/log/fail2ban.log и банит IP, которые уже были забанены несколько раз в течение длительного периода (например, 30 дней). Это отсекает «настойчивых» нарушителей, которые возвращаются после разбана.
По умолчанию Fail2ban использует iptables. Если на сервере уже есть UFW (что типично для Ubuntu), лучше перенаправить баны туда, чтобы не дублировать правила и видеть всё в одном месте.
[DEFAULT]
banaction = ufw
banaction_allports = ufw
В Debian/Ubuntu есть готовый action.d/ufw.conf, который выполняет ufw insert 1 reject from <ip>. Проверить, что бан попал в UFW: ufw status | grep <ip> — должно быть REJECT.
fail2ban-regex /path/to/log /etc/fail2ban/filter.d/name.conf, чтобы убедиться, что regex ловит строки.Использование VPN в России разрешено, но не является желательным. Fail2ban — стандартная практика администрирования, не связанная с правовым статусом прокси. Защита сервера от несанкционированного доступа не является чем-то специфическим для VPN.