Перейти к содержанию

Защита от спама

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/:

scp -r user/plugins/forum-pro/sidecar/ server:
ssh server 'bash sidecar/install.sh'

Права 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     # вердикты ниже этой уверенности не применяются

Этот этап ловит хорошо написанный спам, который выглядит нормально для скоринга, но явно рекламный для читателя. Он выполняется в фоновом процессе, поэтому планировщик должен быть установлен.

Запустить проверку вручную для тестирования настроек можно так:

bin/plugin forum-pro ai-scan

Временные участники

Ограничения на уровне учётной записи. Новые учётные записи остаются временными, пока одновременно не выполнятся два условия: опубликовано заданное число сообщений и с момента регистрации прошёл заданный срок. Нужно преодолеть оба порога, поэтому спамер не сможет за девяносто секунд исчерпать лимит сообщений.

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-ценности.

Учётные записи сотрудников никогда не считаются временными.

Невидимая капча

auth:
  captcha: true

Прозрачная проверка proof-of-work при регистрации и входе, предоставляемая плагином Form. Она не требует никаких действий пользователя: ни изображений, в которые нужно всматриваться, ни галочек. Браузер выполняет небольшую работу в фоне — дешёвую один раз и дорогую в масштабе.

Советы по настройке

Начните со значений по умолчанию и неделю наблюдайте за очередью.

  • Задерживаются обычные сообщения? Повысьте pending_threshold или увеличьте spam.max_links, если сообщество часто делится ссылками.
  • Спам публикуется? Сначала снизьте spam_threshold. Если он начнёт ловить слишком много, подключите классификатор вместо дальнейшего снижения порогов.
  • Спам-аккаунты регистрируются массово? Включите auth.captcha и оставьте provisional.enabled с strip_links и block_messages.
  • Проходит хорошо написанная реклама? Для этого нужен ai_spam.

Ничего не удаляется автоматически до истечения срока хранения, поэтому слишком агрессивный этап стоит времени на проверку, а не контента.