Защищаемся от спама по добавлению ip в чёрный список

Иногда боты достают конкретно, можно банить их по ip.

Для этого имеем в виду то, что ip в таблице со счётчиком num==0 нормален, а всё что выше – нет, и мы его откидываем.

Итак, строим такую таблицу:

CREATE TABLE `ips_blocked` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `dtm` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `ip` varchar(44) NOT NULL COMMENT 'ip адрес',
  `ua` tinytext NOT NULL COMMENT 'User agent',
  `num` int(11) NOT NULL DEFAULT '0' COMMENT 'кол-во попаданий',
  `rem` tinytext NOT NULL COMMENT 'примечание',
  PRIMARY KEY (`id`),
  UNIQUE KEY `ip` (`ip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

ip туда добавляем вручную, т.к. этот процесс редкий, если нет – пишите скрипт для добавления туда ip.

По умолчанию num равен 0.

Итак, перед записью заявки проверяем ip по этой таблице, и если он есть и его номер num больше 0, откидываем заявку:

$ip = empty($_SERVER['REMOTE_ADDR']) ? '' : htmlspecialchars($_SERVER['REMOTE_ADDR']);
 
if(DB::columnIntPrepared('SELECT 1 FROM ips_blocked WHERE ip=? AND num>0', array($ip))) {
	DB::execute("UPDATE ips_blocked SET num=num+1 WHERE ip=?", array($ip));
	report('Ваш ip находится в чёрном списке. Пришлите вашу заявку нам на email.');
}

Таким образом мы можем пропустить первое случайное попадание в чёрный список по ip, а если оно повторится – всё, заявки с данного ip больше не принимаем совсем.

Таким образом, если мы опять обнаружили спамерский ip, ставим его номер 1 в таблице ips_blocked.

На этом всё, до свидания!

P.S. Для ip версии 4 (IPv4) наиболее эффективно наверное использовать тип INT(11),
и при этом каждый раз при добавлении/выборке его в/из таблицы надо использовать соотв. функции, например так:

Добавление: INSERT INTO ips_blocked VALUES (…, INET_ATON(?), …)
Выборка: SELECT INET_NTOA(ip) AS ip

Здесь вместо знака вопроса при добавлении вставляем ip в подготовленное SQL-выражение.

Но я не стал этого делать, а сделал тип поля VARCHAR и длину поля вообще 44, чтобы при случае иметь возможность добавлять IPv6, не знаю уже, когда этот момент настанет. ))))