Защита от спама¶
Forum Pro добавляет три независимых этапа обнаружения поверх ограничений на уровне учётной записи. Все этапы, кроме первого, необязательны, каждый при сбое пропускает сообщения дальше, а всё, что они обнаруживают, попадает в очередь проверки, а не удаляется сразу.
Этап 1: эвристики¶
Мгновенно, всегда включено, без зависимостей. Каждое сообщение оценивается при отправке по следующим признакам:
- Поле-ловушка (honeypot)
- Скорость отправки (форма заполнена быстрее, чем человек успел бы напечатать)
- Количество ссылок
- Чёрные списки
- Вес для новых участников
- Обнаружение всплесков и дублей (один и тот же номер телефона или почти одинаковый текст в недавних сообщениях)
- Ограничения частоты для сообщений в минуту, тем в час и жалоб в час
spam:
enabled: true
pending_threshold: 30 # оценка, при которой контент требует одобрения
spam_threshold: 60 # оценка, при которой контент попадает в очередь спама
min_submit_seconds: 3 # быстрее этого выглядит как автоматическая отправка
max_links: 2 # ссылки сверх этого повышают оценку
new_member_post_count: 3 # участники ниже этого числа сообщений считаются новыми
duplicate_window_minutes: 60 # окно проверки всплесков и дублей
max_posts_per_minute: 6 # 0 отключает
max_topics_per_hour: 12 # 0 отключает
max_flags_per_hour: 10 # 0 отключает
Главные параметры — два порога. Сообщение с оценкой от 30 до 59 задерживается на одобрение, а с оценкой 60 и выше сразу попадает в очередь спама. Снижайте оба порога, если спам проходит, и повышайте, если задерживаются сообщения обычных участников.
Этап 2: ML-классификатор¶
Мгновенно, необязательно, работает на вашем сервере. Сообщения участников с низким доверием оценивает квантованная модель DistilRoBERTa для обнаружения спама (~82 млн параметров, ~85 МБ после квантования в int8), которую обслуживает небольшой сайдкар на Python и ONNX. Примерно 200 мс на сообщение на двух потоках CPU, без GPU.
Вероятность спама от классификатора умножается на weight и прибавляется к оценке эвристик, поэтому уверенного вердикта достаточно, чтобы отправить сообщение в очередь спама, а умеренного — чтобы перевести его в ожидающие одобрения.
spam:
classifier:
enabled: true
url: http://127.0.0.1:8787/classify
timeout_ms: 800 # публикация никогда не ждёт дольше
min_probability: 0.6 # вердикты ниже этого ничего не добавляют
weight: 60 # добавляемая оценка = вероятность x weight
trust_post_count: 20 # участники с большим числом сообщений пропускают классификатор
Примечание
Клиент работает по принципу fail-open: если сайдкар медленный, недоступный или остановлен, публикация продолжается только на эвристиках. Сломанный классификатор никогда не заблокирует участникам возможность писать.
Установка сайдкара¶
В плагине есть установщик в папке sidecar/:
Права root не нужны. Скрипт устанавливает uv, создаёт виртуальное окружение Python 3.12 (системный Python не затрагивается и может быть любой версии), экспортирует и квантует модель в int8 во временном окружении, устанавливает пользовательский модуль systemd forum-spam-classifier.service и проверяет его запуск.
Если для loginctl enable-linger на вашей машине нужны права root, скрипт переключается на cron-сторож, который поддерживает сервис запущенным. Попросите администратора один раз выполнить loginctl enable-linger <user>, после чего строку cron можно удалить.
В рабочем состоянии процесс занимает примерно 300 МБ RSS и слушает только 127.0.0.1:8787. Укажите его адрес в spam.classifier.url — и всё готово.
Этап 3: ежечасная проверка ИИ¶
Необязательный этап, требует плагин AI Pro. Раз в час LLM просматривает недавние сообщения новых участников с полным контекстом темы и отправляет уверенно определённый спам модераторам, записывая обоснование каждого решения.
ai_spam:
enabled: true
provider: "" # имя провайдера ai-pro ('' = провайдер по умолчанию)
model: "" # переопределение модели ('' = модель провайдера по умолчанию)
lookback_hours: 24 # проверяются только сообщения новее этого срока
max_posts: 50 # сообщений за один запуск
trust_post_count: 20 # участники с большим числом сообщений не проверяются
min_confidence: 0.85 # вердикты ниже этой уверенности не применяются
Этот этап ловит хорошо написанный спам, который выглядит нормально для скоринга, но явно рекламный для читателя. Он выполняется в фоновом процессе, поэтому планировщик должен быть установлен.
Запустить проверку вручную для тестирования настроек можно так:
Временные участники¶
Ограничения на уровне учётной записи. Новые учётные записи остаются временными, пока одновременно не выполнятся два условия: опубликовано заданное число сообщений и с момента регистрации прошёл заданный срок. Нужно преодолеть оба порога, поэтому спамер не сможет за девяносто секунд исчерпать лимит сообщений.
provisional:
enabled: true
post_threshold: 5 # оставаться временным, пока опубликовано меньше сообщений
min_age_hours: 24 # ...и пока учётной записи не исполнится столько часов (0 отключает проверку возраста)
strip_links: true # убирать URL из сообщений (остаются обычным текстом)
hide_profile: true # скрывать сайт, ссылки на соцсети, подпись и звание
noindex_profile: true # помечать профиль как noindex
newbie_badge: true # показывать значок «Новый» в сообщениях и профиле
block_attachments: true # блокировать загрузку файлов и изображений
block_messages: true # запрещать начинать личные беседы
Каждое ограничение — независимый переключатель, поэтому можно настроить такую строгость, какая нужна сообществу. Один strip_links убирает большую часть мотивации спамить форум: сообщение всё равно появляется, но URL становится инертным текстом без SEO-ценности.
Учётные записи сотрудников никогда не считаются временными.
Невидимая капча¶
Прозрачная проверка proof-of-work при регистрации и входе, предоставляемая плагином Form. Она не требует никаких действий пользователя: ни изображений, в которые нужно всматриваться, ни галочек. Браузер выполняет небольшую работу в фоне — дешёвую один раз и дорогую в масштабе.
Советы по настройке¶
Начните со значений по умолчанию и неделю наблюдайте за очередью.
- Задерживаются обычные сообщения? Повысьте
pending_thresholdили увеличьтеspam.max_links, если сообщество часто делится ссылками. - Спам публикуется? Сначала снизьте
spam_threshold. Если он начнёт ловить слишком много, подключите классификатор вместо дальнейшего снижения порогов. - Спам-аккаунты регистрируются массово? Включите
auth.captchaи оставьтеprovisional.enabledсstrip_linksиblock_messages. - Проходит хорошо написанная реклама? Для этого нужен
ai_spam.
Ничего не удаляется автоматически до истечения срока хранения, поэтому слишком агрессивный этап стоит времени на проверку, а не контента.