Тонке налаштування greylisting: зупиняємо ботів, не гальмуючи легітимну пошту
Дефолтний postgrey з delay=300 і матчингом по повному IP у 2026 ловить хіба залишки старих ботнетів, зате стабільно затримує листи з Gmail і Microsoft на 20-40 хвилин. Розбираємо, чому так, і як зробити greylisting тонким шаром усередині postscreen — без затримок для довіреної пошти.
EvilMail Team15 липня 2026 р.11 хв читання
Чому дефолтний greylisting сьогодні шкодить більше, ніж допомагає
Типова заявка в підтримку: «Ваш сервер не приймає пошту. Лист-підтвердження зі Stripe прийшов через 35 хвилин, код 2FA з Google — через 22. Клієнти скаржаться». Ви дивитесь у /var/log/mail.log і бачите чистий 450 4.2.0 ... Greylisted. Сервер працює правильно. Проблема в тому, що «правильно» тут означає дефолтний postgrey з delay=300.
Механізм простий. Greylisting будує триплет — (client IP, envelope sender, envelope recipient) — і на першу зустріч цього триплета відповідає тимчасовою відмовою 450. Ідея з 2003 року: справжній MTA потримає лист у черзі й повторить спробу за кілька хвилин, а дешевий спам-бот, який вистрілив і забув, більше не повернеться. За другої спроби триплет уже відомий — лист проходить.
Ця логіка розсипається об ротацію вихідних пулів великих провайдерів. Google, Microsoft 365, Amazon SES віддають вихідну пошту з десятків різних /24. Перша спроба приходить з 209.85.220.41, повторна — з 209.85.208.198. Для postgrey, який матчить повний /32, це два різні триплети. Другий теж отримує 450. І третій. Лист висить, доки на боці відправника не збіжаться зірки й той самий IP не повторить спробу у вікні — звідси ваші 35 хвилин.
Теза цієї статті одна: greylisting у 2026 корисний лише як тонко налаштований шар усередині postscreen + reputation, а не як самостійний бар'єр. Не вимикайте його бездумно, але й не вірте, що він вас рятує.
Анатомія триплета і де саме він розсипається
Триплет живе в базі зі станом: коли вперше побачений, коли «дозріє» (мине delay), до якого моменту вважається валідним (max-age). Уся ефективність упирається в один параметр — гранулярність IP.
postgrey нормалізує клієнта по повному IP. Опція --privacy лише хешує адресу перед записом, гранулярність лишається /32. Subnet-матчингу немає взагалі.
SQLgrey з optmethod = smart за замовчуванням матчить перші три октети — фактично /24. 209.85.220.41 і 209.85.208.198 — це 209.85.220.x проти 209.85.208.x, тобто різні /24, і smart тут не врятує сам по собі. Але для пулів, де ретрай приходить у межах одного /24 (а таких більшість), матчинг по підмережі знімає до 80% фальшивих повторних грейлистів. Для решти лишається whitelist за rDNS/SPF.
Друга половина проблеми — вікна ретраю легітимних MTA проти вашого delay.
Ключове число: у Postfix minimal_backoff_time за замовчуванням 300 секунд, тобто перший ретрай — рівно через 5 хвилин. Exim повторює приблизно через 15 хвилин. Хмарні транзакційні сервіси (SendGrid, Mailgun, Stripe, Twilio) ретраять від кількох секунд до 1-2 хвилин. А от погано налаштовані корпоративні MTA можуть повторити лише за годину. Звідси висновок: delay більший за 300 секунд небезпечний — ви ризикуєте, що частина легітимних відправників упреться в max-age швидше, ніж повторить спробу. Оптимум для транзакційної пошти — delay = 60.
Postgrey: як довести його до пуття, якщо вже стоїть
Дефолт із коробки задається у /etc/default/postgrey через POSTGREY_OPTS. Приведіть його до бойового вигляду:
--delay=60 замість 300, --retry-window=8 (годин) дає повільним MTA шанс, --auto-whitelist-clients=5 — після 5 успішних проходів клієнт більше не грейлиститься. Інтеграція в main.cf:
Порядок критичний — про це нижче окремо. Whitelist-файли /etc/postgrey/whitelist_clients і /etc/postgrey/whitelist_recipients приймають домени й regex; сюди вручну додають критичних відправників (google.com, .amazonses.com, платіжні шлюзи). Проблема postgrey в тому, що робити це доводиться руками, бо нормального subnet-матчингу немає, а вбудований AWL примітивний. Саме це — головна причина мігрувати.
SQLgrey: чому в 2026 він практичніший
SQLgrey зберігає стан у MySQL/PostgreSQL і має дві речі, яких бракує postgrey: subnet-матчинг відправника й повноцінний auto-whitelist. Робочий /etc/sqlgrey/sqlgrey.conf:
optmethod = smart # subnet-матчинг клієнта (перші 3 октети)
reconnect_delay = 5 # хвилин — мінімальна пауза перед валідним ретраєм
max_connect_age = 24 # годин життя незавершеного триплета
awl_age = 32 # днів у auto-whitelist після першого успіху
group_domain_level = 2
SQLgrey слухає inet:127.0.0.1:2501 — підставляєте цей сокет у check_policy_service замість postgrey. Найважливіший параметр — awl_age = 32. Після першого успішного проходу пара «відправник → одержувач» потрапляє в from_awl, і наступні 32 дні вона взагалі не бачить грейлиста. Затримка стає одноразовою для пари, а не постійним податком на кожен лист.
Структура таблиць: connect тримає активні триплети, from_awl — whitelist за конкретним envelope sender + клієнтською підмережею, domain_awl — агрегований whitelist на рівні домену відправника. domain_awl спрацьовує швидше для великих провайдерів: як тільки будь-який відправник з @gmail.com пройшов з певної підмережі Google, увесь домен з цієї підмережі отримує bypass. Це і є та штука, що вбиває проблему ротації пулів без ручних whitelist-файлів.
Обхід грейлиста для довіреної пошти
Це серцевина «без затримок». Greylisting має бачити лише сіру зону — те, що не чорне, але й не очевидно біле. Усе довірене повинно виходити з ланцюга ДО check_policy_service. Вирішує саме порядок у smtpd_recipient_restrictions.
Порядок ланцюга робить усю роботу:
permit_mynetworks і permit_sasl_authenticated стоять першими — власну й автентифіковану пошту не грейлистимо ніколи.
SPF-pass bypass реалізується через postfix-policyd-spf-python, що слухає inet:127.0.0.1:10025 і ставиться ПЕРЕД грейлистом. На Received-SPF: Pass він додає заголовок або повертає dunno, і ви за цим сигналом пускаєте лист повз policy service. Логіка проста: якщо домен офіційно дозволив цьому IP відправляти від свого імені, це не бот-однострільник.
TLS як м'який сигнал: з'єднання по TLS з валідним сертифікатом — ще один маркер легітимності для «сірої зони».
Помилка №1, яку я бачу в чужих конфігах, — check_policy_service стоїть перед permit_sasl_authenticated. Результат: ваші власні користувачі, що шлють з телефона через submission, огрібають грейлист. Порядок вирішує все.
У 2026 більшість роботи, заради якої колись ставили greylisting, дешевше й без затримок робить postscreen. Він працює на рівні :25 до того, як передасть з'єднання smtpd, і відсіює ботів за поведінкою протоколу:
postscreen_greet_action = enforce ловить pregreet — бота, що починає слати команди, не дочекавшись банера. Дешеві ботнети роблять саме так і відвалюються миттєво, без жодної затримки для легітимних. DNSBL зі зваженим scoring (*2 для надійних списків, поріг 2) прибирає відомі джерела. Те, що переживе postscreen, — це вже або чистий MTA, або «сіра зона», і саме її має розглядати грейлист.
Моя позиція жорстка: greylisting — доповнення, не фундамент. Сучасний snowshoe-спам іде через справжні MTA з коректним retry, тому проходить будь-який грейлист. Його реальна цінність сьогодні — відсів дешевих ботнетів, і postscreen робить це без затримки. Якщо у вас увімкнений postscreen з pregreet і DNSBL, greylisting — це вже тонкий фінішний фільтр, а не передова.
Вимірюйте, кого ви насправді гальмуєте
Не тюньте наосліп. Витягніть із логів співвідношення delayed → passed проти delayed → ніколи-не-повторили:
bash
# скільки листів затримано і скільки зрештою пройшло (postgrey)
grep -c 'action=greylist' /var/log/mail.log
grep -c 'action=pass' /var/log/mail.log
# топ доменів-відправників, що застрягли в грейлисті (кандидати у whitelist)
awk '/action=greylist/ {for(i=1;i<=NF;i++) if($i ~ /^sender=/) print $i}' \
/var/log/mail.log | sort | uniq -c | sort -rn | head -20
# агрегація по дню
pflogsumm -d today /var/log/mail.log | less
Читання результату:
delayed без наступного passed ≈ спам-бот — він не вміє тримати чергу. Це добре, грейлист працює за призначенням.
Але якщо частка «delayed і ніколи не повторили» аномально висока серед відомих доменів (gmail.com, outlook.com, ваш платіжний шлюз) — це червоний прапор: ваш delay задовгий або max-age закороткий, і легітимні MTA впираються в стелю раніше, ніж повторюють спробу. Ви гальмуєте своїх, а не ботів.
Формула проста: ефективність = (bad_delayed_never_retried) / (total_delayed). Якщо в знаменнику багато відомих провайдерів — розширюйте whitelist і зменшуйте delay, а не радійте «високому відсотку відсіву».
Чеклист бойового налаштування
permit_mynetworks і permit_sasl_authenticated — передcheck_policy_service, завжди.
SPF = PASS → bypass через postfix-policyd-spf-python перед грейлистом.
postscreen попереду з pregreet + зваженим DNSBL — він знімає з грейлиста основне навантаження.
Щотижневий розбір mail.log на delayed → passed і моніторинг черги deferred.
Whitelist за rDNS/SPF для Google (include:_spf.google.com, PTR *.google.com) і Microsoft.
І окремо про контекст evilmail.pro: для тимчасової пошти greylisting контрпродуктивний. Користувач створив одноразову адресу, щоб отримати код підтвердження тут і зараз — затримувати перший лист на хвилину означає зламати весь сценарій. На вхідних temp-email грейлист вимикають повністю, а весь цей тюнінг актуальний там, де він доречний: на транзакційній і бізнес-пошті, де ціна фальшивого спрацювання — не зіпсований UX, а втрачений платіж.