ClamAV в mailcow блокирует чистые письма: сторонние базы, ложные срабатывания и как их снять
Сторонние базы SecuriteInfo резко повышают детект ClamAV в mailcow, но без правильной настройки оценок в Rspamd легитимные письма с вложениями начинают блокироваться наравне с реальными угрозами. Разбираю, как согласовать antivirus.conf и composites.conf, чем whitelist.ign2 отличается от allow-list по хешу и почему после исключения сигнатуры письмо всё равно может блокироваться из кэша.
Симптом: чистый PDF или обычная рассылка получают VIRUS_FOUND
Типичный сценарий, с которым ко мне обращаются после самостоятельной настройки антивируса для корпоративной почты на mailcow: администратор подключает дополнительные базы сигнатур SecuriteInfo к штатному ClamAV, чтобы ловить больше спама и вредоносных вложений — и почти сразу получает жалобы, что обычные счета в PDF, коммерческие предложения или рассылка с картинками начинают отклоняться с пометкой VIRUS_FOUND. Часто это происходит не из-за реальной угрозы, а из-за того, что новые сигнатуры не согласованы с системой оценок Rspamd, которая и принимает финальное решение — пропустить письмо, поместить в карантин или отклонить.
Второй, более узкий вариант той же проблемы — конкретный документ с активным содержимым (например, PDF со встроенным JavaScript для формы) стабильно ловится одной и той же сигнатурой, хотя вложение проверено вручную и опасности не несёт. Администратор добавляет сигнатуру в исключения, перезапускает ClamAV — а письмо с тем же вложением всё равно блокируется, потому что результат предыдущей проверки уже закэширован и переопределение сигнатуры на него не действует.
Как ClamAV и Rspamd вместе решают судьбу письма
В mailcow ClamAV не блокирует письма самостоятельно — он только сканирует вложения и передаёт название сработавшей сигнатуры в Rspamd, а окончательное решение принимает уже Rspamd на основе весов и композитных правил. Подключение SecuriteInfo штатно поддерживается начиная с mailcow версии 2023-07 и новее — именно тогда в composites.conf появились предопределённые оценки для его сигнатур. Без них (и без блока patterns) любое срабатывание SecuriteInfo Rspamd считает обычным вирусом: символ CLAM_VIRUS, вердикт VIRUS_FOUND с оценкой 2000 и отказ — как пишет документация, Rspamd «беспощадно помечает ВСЁ как VIRUS», хотя база ориентирована не только на вирусы, но и на маркетинговый спам.
Конфигурация делится на два файла, и это ключевая причина большинства проблем: правила сопоставления имени сигнатуры с типом (patterns { ... }) живут в data/conf/rspamd/local.d/antivirus.conf внутри секции clamav { ... }, а сами числовые оценки для этих типов — в data/conf/rspamd/local.d/composites.conf. Если добавить блок patterns не туда (например, вне секции clamav) — Rspamd в логе выдаёт ошибку unknown antivirus type: patterns, и правило просто не применяется, антивирус продолжает работать по дефолтным весам.
Если у вас DKIM/SPF/DMARC ещё не настроены или настроены частично, ложные блокировки ClamAV легко перепутать с проблемами доставки — оба симптома выглядят как «письмо не дошло». Прежде чем разбирать веса антивируса, стоит отдельно проверить базовую настройку DKIM, SPF и DMARC, чтобы не лечить не ту причину.
Как правильно подключить SecuriteInfo и не получить лавину ложных срабатываний
Рабочий блок patterns для SecuriteInfo выглядит так — вставляется внутрь секции clamav в antivirus.conf:
patterns {
CLAM_SECI_SPAM = "^SecuriteInfo\.com\.Spam.*";
CLAM_SECI_JPG = "^SecuriteInfo\.com\.JPG.*";
CLAM_SECI_PDF = "^SecuriteInfo\.com\.PDF.*";
CLAM_SECI_HTML = "^SecuriteInfo\.com\.HTML.*";
CLAM_SECI_JS = "^SecuriteInfo\.com\.JS.*";
}После правки обязательно docker compose restart rspamd-mailcow, иначе Rspamd продолжит работать со старым конфигом. Веса уже заданы в composites.conf mailcow композитами: CLAMD_SPAM_FOUND — 5, CLAMD_BAD_PDF, CLAMD_BAD_JPG, CLAMD_ASCII_MALWARE, CLAMD_HTML_MALWARE и CLAMD_JS_MALWARE — по 8; меняется параметр score нужного композита. И именно здесь стоит быть избирательным, а не копировать чужой готовый конфиг один в один: разные проекты выкладывают разные наборы весов, и то, что подошло чужой инсталляции с большим потоком спама, может оказаться избыточно строгим для небольшой компании с редкими вложениями.
Сами базы подключаются на стороне ClamAV строками DatabaseCustomURL с персональным идентификатором в data/conf/clamav/freshclam.conf. Для бесплатных баз SecuriteInfo скорость скачивания ограничена 300 кБ/с, поэтому документация советует поднять ReceiveTimeout с 20 до 90 секунд, а с полным набором баз ClamAV занимает около 1,3 ГБ ОЗУ — на маленьком VPS это надо учесть заранее. Отдельно документация mailcow прямо предупреждает про базу spam_marketing.ndb из состава SecuriteInfo: она классифицирует адреса как маркетинговые/спам-рассылки и известна значительным числом ложных срабатываний — подключать её стоит на свой риск и точно не с тем же весом, что реальные вирусные сигнатуры. У поставщика есть и обратная база — securiteinfo.ign2 — список собственных исключений SecuriteInfo, которую имеет смысл подключать параллельно с patterns, а не вместо него. И ещё один практический нюанс: оба файла, antivirus.conf и composites.conf, могут быть перезаписаны штатным обновлением mailcow — конфигурацию стоит держать в отдельном бэкапе или скрипте, который накатывает её заново после апдейта.
Whitelist.ign2: точечное исключение конкретной сигнатуры
Когда проблема не в лавине ложных срабатываний от новой базы, а в одной конкретной сигнатуре на конкретном типе документов — например, PUA.Pdf.Trojan.EmbeddedJavaScript-1 на формах с JavaScript, — документация mailcow предлагает точечный путь: добавить имя сигнатуры в data/conf/clamav/whitelist.ign2 и перезапустить контейнер: docker compose restart clamd-mailcow. Это глобальное исключение по имени сигнатуры — оно применяется ко всем письмам, где эта сигнатура сработала бы, вне зависимости от отправителя или конкретного файла.
Важно понимать разницу между этим механизмом и allow-list по хешу файла, который описан уже не в документации mailcow, а в общей документации ClamAV: .ign2/ignore-list исключает сигнатуру целиком — то есть любое письмо, где ClamAV распознает именно эту сигнатуру, перестанет блокироваться. А allow-list по хешу разрешает конкретный файл, не трогая саму сигнатуру: MD5-подпись кладётся в файл .fp, SHA1 или SHA256 — в .sfp (генерируется sigtool --sha256 файл) — остальные письма с той же сигнатурой продолжат блокироваться. Для разовой легитимной формы разумнее точечный allow-list по хешу, а не глобальное исключение сигнатуры — иначе вы теряете защиту от реальных вредоносных PDF с этой же сигнатурой у других отправителей. Нюанс mailcow: штатно из data/conf/clamav/ в базу копируется только whitelist.ign2 (это делает стартовый скрипт clamd-mailcow), а файл .sfp придётся положить прямо в каталог баз /var/lib/clamav внутри контейнера — он живёт в томе clamd-db-vol-1, и после крупных обновлений его наличие стоит проверять.
Почему письмо всё ещё блокируется после исключения — кэш Redis
Самая частая причина, по которой администратор добавляет сигнатуру в whitelist.ign2, перезапускает clamd-mailcow, а письмо с тем же вложением всё равно получает VIRUS_FOUND, — результат предыдущей проверки уже закэширован в Redis. mailcow кэширует результаты сканирования ClamAV, чтобы не гонять повторную проверку одного и того же вложения на каждый пересыл, и если файл уже был проверен и помечен как заражённый до правки whitelist, старый результат продолжает действовать, пока кэш не очищен.
Команда для очистки именно кэша ClamAV в Redis из документации mailcow: source mailcow.conf; docker compose exec redis-mailcow sh -c "redis-cli -a $REDISPASS KEYS 'rs_cl*' | xargs redis-cli -a $REDISPASS DEL". После этого стоит заново отправить проблемное письмо (или попросить отправителя переслать его) — только тогда ClamAV просканирует вложение заново уже с учётом нового whitelist.ign2, а не отдаст старый результат из кэша. Я всегда включаю этот шаг в чек-лист при разборе жалоб на ложные срабатывания — без него можно потратить час, меняя конфиг и не понимая, почему ничего не меняется.
Полезная привычка — держать под рукой короткую заметку с этой командой в документации инсталляции, а не искать её заново в панике каждый раз: разбор жалобы «я всё исправил, а не работает» без этого шага занимает вдвое больше времени, чем сама правка конфига.
Кейс «Аналитика спроса»: подключили SecuriteInfo — заблокировали собственную рассылку
У клиента — маркетингового агентства «Аналитика спроса», 26 рабочих мест — администратор подключил SecuriteInfo к ClamAV для усиления защиты от фишинговых вложений после серии подозрительных писем клиентам агентства. Блок patterns скопировали со стороннего форума и вставили в antivirus.conf, не проверив, в какую секцию он попал, и не заглянув в лог Rspamd после перезапуска. В первый же день собственная рассылка агентства с HTML-версией письма и вложенным PDF-брифом начала получать VIRUS_FOUND и блокироваться на исходящей стороне, хотя вложение было тем же файлом, что рассылался месяцами без проблем.
Разбор занял около полутора часов: в логе clamd-mailcow нашли срабатывание сигнатуры из семейства SecuriteInfo.com.HTML.* на HTML-версию письма с трекинг-пикселем и JS-счётчиком открытий, а в логе Rspamd — ту самую ошибку unknown antivirus type: patterns: блок с форума вставили после закрывающей скобки секции clamav. В итоге каждое срабатывание SecuriteInfo становилось CLAM_VIRUS с отказом. Перенесли patterns внутрь clamav { ... } и перезапустили rspamd-mailcow; дальше HTML-срабатывание получало уже 8 баллов композита CLAMD_HTML_MALWARE и вместе с «маркетинговыми» символами самой рассылки всё равно дотягивало до порога. Снизили score этого композита до 3, оставив CLAMD_JS_MALWARE и остальные на 8, и отключили базу spam_marketing.ndb, которую администратор подключил вместе с остальными «на всякий случай». Глобально исключать сигнатуру через whitelist.ign2 не стали: похожая сигнатура на чужих вложениях у клиентов агентства блокироваться по-прежнему должна была. После правки и очистки кэша Redis рассылка пошла без блокировок, а полноценные вредоносные вложения на тестовых письмах ClamAV продолжил ловить.
Отдельно проговорили с клиентом регламент на будущее: любую новую стороннюю базу сигнатур сначала подключать на тестовом ящике с пересылкой копии реальной рассылки агентства, и только после недели наблюдений без ложных срабатываний — переносить настройку на продакшен-домен. Похожий принцип поэтапного внедрения изменений антиспама я закладываю в регламент эксплуатации mailcow, по которому веду клиентские инсталляции: правки антивируса и антиспама — не то, что стоит выкатывать сразу на весь домен без проверки.
Чек-лист диагностики ложных срабатываний ClamAV
Когда приходит жалоба на блокировку легитимного письма, я прохожу по одному и тому же порядку. Сначала — найти в логах ClamAV (docker compose logs clamd-mailcow | grep FOUND) точное имя сработавшей сигнатуры, а не гадать по симптомам. Затем понять, массовая это проблема (новая сигнатура с неверным весом после подключения сторонней базы) или разовая (конкретный файл и конкретная сигнатура) — от этого зависит, что править: composites.conf целиком или whitelist.ign2/allow-list точечно.
Дальше — если решили менять оценку сигнатуры, править score композита в composites.conf, а не переписывать patterns; если решили точечно исключить документ — allow-list по хешу, а не широкий whitelist.ign2, если есть риск, что та же сигнатура пригодится на других отправителях. И в конце — обязательно очистить кэш Redis по ключам rs_cl* и попросить переслать письмо заново, иначе результат правки будет не виден и создастся ложное впечатление, что настройка не сработала. Отдельно держу в голове, что оба конфига могут слететь при обновлении mailcow — после крупного апдейта стоит свериться, что patterns и веса всё ещё на месте.
И последнее наблюдение из практики: если после всех правок ложные срабатывания продолжаются на новых, ещё не встречавшихся сигнатурах из той же сторонней базы, это сигнал не чинить каждую по отдельности бесконечно, а пересмотреть сам факт подключения этой базы — возможно, для конкретной компании выигрыш в детекте не окупает постоянной ручной разборки блокировок легитимной переписки.
Частые вопросы
Почему ClamAV в mailcow вообще не блокирует письма без сторонних баз?
Блокирует, но штатные сигнатуры ClamAV ориентированы в первую очередь на известные вредоносные файлы и покрывают меньше спам-паттернов. SecuriteInfo расширяет детект, но требует согласования весов через composites.conf — иначе легитимные письма попадают под те же жёсткие правила, что и реальные угрозы.
С какой версии mailcow можно подключать SecuriteInfo?
С 2023-07 и новее — именно тогда появились предопределённые оценки сигнатур SecuriteInfo в интеграции с Rspamd. На более старых версиях блок patterns можно добавить, но без готовых весов ложных срабатываний будет заметно больше.
В чём разница между whitelist.ign2 и allow-list по хешу?
whitelist.ign2 исключает сигнатуру целиком — все письма, где она сработала бы, перестают блокироваться. Allow-list по хешу разрешает конкретный файл (MD5 — в .fp, SHA1/SHA256 — в .sfp), не трогая сигнатуру для остальных писем. Для разового легитимного документа безопаснее allow-list по хешу.
Добавил сигнатуру в whitelist.ign2, перезапустил clamd-mailcow — письмо всё равно блокируется, почему?
Скорее всего, результат предыдущей проверки уже в кэше Redis. Нужно очистить ключи rs_cl* командой redis-cli -a $REDISPASS KEYS 'rs_cl*' | xargs redis-cli -a $REDISPASS DEL и заново прогнать письмо через антивирус.
Стоит ли подключать базу spam_marketing.ndb из SecuriteInfo?
Документация mailcow прямо предупреждает о значительном числе ложных срабатываний этой базы. Я подключаю её только с явно заниженным весом относительно вирусных сигнатур и только если у клиента реально высокий поток маркетингового спама, который не ловится стандартными правилами Rspamd.
Почему после обновления mailcow настройки антивируса снова стали давать ложные срабатывания?
antivirus.conf и composites.conf могут быть перезаписаны при обновлении mailcow — это отдельно указано в документации. Конфигурацию SecuriteInfo стоит хранить отдельно (скрипт, git, бэкап) и накатывать заново после каждого крупного апдейта.
Источники
- mailcow docs — Additional Databases for ClamAV — Требование mailcow ≥2023-07, пути antivirus.conf/composites.conf, пример блока patterns для SecuriteInfo, предупреждение про spam_marketing.ndb, база securiteinfo.ign2. https://docs.mailcow.email/manual-guides/ClamAV/u_e-clamav-additional_dbs/
- mailcow docs — ClamAV Whitelist — Путь data/conf/clamav/whitelist.ign2, команда docker compose restart clamd-mailcow, очистка кэша Redis по ключам rs_cl* через redis-cli -a $REDISPASS. https://docs.mailcow.email/manual-guides/ClamAV/u_e-clamav-whitelist/
- ClamAV docs — Allow Lists — Разница между ignore-list (исключение сигнатуры целиком) и allow-list по хешу файла (.fp/.sfp). https://docs.clamav.net/manual/Signatures/AllowLists.html
- SecuriteInfo — FAQ ClamAV and Unofficial Signatures — Описание неофициальных сигнатур SecuriteInfo, состав баз (Spam, JPG, PDF, HTML, JS), рекомендации по подключению. https://www.securiteinfo.com/clamav-antivirus/faq-clamav-unofficial-signatures_en.shtml
- mailcow community — Watchdog ALERT: clamd-mailcow (SecuriteInfo) — Практическое обсуждение настройки SecuriteInfo и типичных ошибок конфигурации antivirus.conf. https://community.mailcow.email/d/2744-watchdog-alert-clamd-mailcow



