Налаштування антиспам-захисту форм 1С-Бітрікс
Спам у формах — проблема не лише дратівлива, а й технічно затратна: засмічує CRM сміттєвими лідами, перевантажує email-черги, створює хибні спрацьовування в аналітиці. Стандартна CAPTCHA від Бітрікс (bitrix:main.captcha) — зображення з символами — з 2020 року практично не працює: сучасні боти розпізнають її з точністю 95%+. Потрібен багаторівневий підхід.
Рівні захисту
Ефективний антиспам-захист — це кілька незалежних рівнів, кожен із яких відсіює свій тип атаки:
- Honeypot — приховане поле, яке заповнюють лише боти
- Таймінг — форма, надіслана швидше ніж за 3 секунди після завантаження — бот
- Rate limiting — обмеження кількості відправок з однієї IP-адреси
- reCAPTCHA v3 / Turnstile — JS-перевірка без CAPTCHA-зображень
- Перевірка email — MX-запит, одноразові email-домени
- Перевірка телефону — валідний формат, не в чорному списку
Honeypot: найпростіший і найефективніший метод
// У шаблоні форми — приховане поле, невидиме через CSS (не display:none — це підозріло для деяких ботів)
?>
<div style="position:absolute;left:-9999px;top:-9999px;opacity:0;height:0;overflow:hidden">
<label for="email_confirm">Leave empty</label>
<input type="text"
id="email_confirm"
name="email_confirm"
tabindex="-1"
autocomplete="off"
value="">
</div>
<?php
Серверна перевірка:
// Якщо поле заповнено — це бот
if (!empty($data['email_confirm'])) {
// Тихо ігноруємо, не показуємо помилку боту
echo json_encode(['success' => true]);
exit;
}
Таймінг: форма не може бути надіслана миттєво
// При рендері форми записуємо timestamp у приховане поле
$formToken = base64_encode(json_encode([
'ts' => time(),
'sessid' => bitrix_sessid(),
]));
<input type="hidden" name="form_token" value="<?= htmlspecialchars($formToken) ?>">
Серверна перевірка:
$token = json_decode(base64_decode($data['form_token'] ?? ''), true);
$timeElapsed = time() - (int)($token['ts'] ?? 0);
if ($timeElapsed < 3) {
// Надто швидко — ознака бота
$this->markSpam('timing', $timeElapsed);
exit(json_encode(['success' => true])); // тихий успіх для бота
}
if ($timeElapsed > 3600) {
// Форма застаріла — помилка для користувача
exit(json_encode(['success' => false, 'error' => 'Сесія закінчилася. Оновіть сторінку.']));
}
Rate Limiter через Redis / Кеш Бітрікс
namespace Local\AntiSpam;
class RateLimiter
{
private const LIMITS = [
'ip' => ['max' => 5, 'window' => 3600], // 5 форм з IP за годину
'email' => ['max' => 3, 'window' => 86400], // 3 заявки з email за день
'phone' => ['max' => 2, 'window' => 86400], // 2 заявки з телефону за день
];
public function check(string $type, string $identifier): bool
{
$limit = self::LIMITS[$type] ?? ['max' => 3, 'window' => 3600];
$key = 'spam_rl_' . $type . '_' . md5($identifier);
$cache = \Bitrix\Main\Application::getInstance()->getManagedCache();
$count = (int)$cache->get($key);
if ($count >= $limit['max']) {
$this->logAttempt($type, $identifier, 'rate_limit');
return false;
}
$cache->set($key, $count + 1, $limit['window']);
return true;
}
private function logAttempt(string $type, string $identifier, string $reason): void
{
\CEventLog::Add([
'SEVERITY' => 'WARNING',
'AUDIT_TYPE_ID' => 'SPAM_BLOCKED',
'MODULE_ID' => 'local.antispam',
'DESCRIPTION' => "Blocked: type={$type}, id={$identifier}, reason={$reason}",
'REMOTE_ADDR' => $_SERVER['REMOTE_ADDR'],
]);
}
}
reCAPTCHA v3: скорингова перевірка без переривання UX
Google reCAPTCHA v3 не показує CAPTCHA користувачу — вона працює у фоні та повертає score від 0 до 1 (0 = бот, 1 = людина).
Інтеграція у форму:
// Підключаємо reCAPTCHA v3
// <script src="https://www.google.com/recaptcha/api.js?render=YOUR_SITE_KEY"></script>
async function submitForm(formData) {
const token = await grecaptcha.execute('YOUR_SITE_KEY', { action: 'callback_form' });
formData.recaptcha_token = token;
formData.recaptcha_action = 'callback_form';
// відправка...
}
Серверна верифікація:
namespace Local\AntiSpam;
class RecaptchaV3Verifier
{
private string $secretKey;
private float $minScore;
public function __construct(float $minScore = 0.5)
{
$this->secretKey = \Bitrix\Main\Config\Option::get('local.antispam', 'recaptcha_secret');
$this->minScore = $minScore;
}
public function verify(string $token, string $expectedAction = ''): bool
{
$ch = curl_init('https://www.google.com/recaptcha/api/siteverify');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'secret' => $this->secretKey,
'response' => $token,
'remoteip' => $_SERVER['REMOTE_ADDR'],
]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if (!($response['success'] ?? false)) {
return false;
}
// Перевіряємо action
if ($expectedAction && ($response['action'] ?? '') !== $expectedAction) {
return false;
}
return ($response['score'] ?? 0) >= $this->minScore;
}
}
Для аудиторії, де Google reCAPTCHA може блокуватися, альтернативами є Cloudflare Turnstile (без VPN-проблем) або Yandex SmartCaptcha.
Yandex SmartCaptcha: альтернативний варіант
// Підключення
// <script src="https://captcha-api.yandex.ru/captcha.js" defer></script>
// Відображення віджета
const captchaId = window.smartCaptcha.render('captcha-container', {
sitekey : 'YOUR_SITE_KEY',
callback : (token) => { document.getElementById('smart-token').value = token; },
});
Серверна перевірка:
function verifyYandexCaptcha(string $token): bool
{
$secretKey = \Bitrix\Main\Config\Option::get('local.antispam', 'yandex_captcha_secret');
$ch = curl_init('https://smartcaptcha.yandexcloud.net/validate');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'secret' => $secretKey,
'token' => $token,
'ip' => $_SERVER['REMOTE_ADDR'],
]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
return ($result['status'] ?? '') === 'ok';
}
Перевірка одноразових email-адрес
Тимчасові email-адреси (mailinator.com, guerrillamail.com тощо) — ознака спаму:
class EmailValidator
{
private const DISPOSABLE_DOMAINS_URL =
'https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/master/disposable_email_blocklist.conf';
public function isDisposable(string $email): bool
{
$domain = strtolower(substr(strrchr($email, '@'), 1));
// Кешуємо список на 24 години
$cache = \Bitrix\Main\Data\Cache::createInstance();
if (!$cache->initCache(86400, 'disposable_domains', '/antispam/')) {
$cache->startDataCache();
$list = file(self::DISPOSABLE_DOMAINS_URL, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$cache->endDataCache($list);
} else {
$list = $cache->getVars();
}
return in_array($domain, $list ?? [], true);
}
}
Склад робіт
- Реалізація honeypot у всіх формах сайту
- Таймінг-перевірка через прихований timestamp-токен
- Rate limiter за IP, email, телефоном
- Інтеграція reCAPTCHA v3 або Yandex SmartCaptcha
- Перевірка одноразових email при реєстрації та підписці
- Логування заблокованих спроб у
CEventLog - Дашборд статистики: кількість заблокованих за типом за період
Терміни: базовий набір (honeypot + таймінг + rate limit) — 3–5 днів. Повний стек зі SmartCaptcha та моніторингом — 1–2 тижні.







