Основы PHP
  Что такое PHP?
  Возможности PHP
  Преимущества PHP
  История развития
  Что нового в PHP5?
  «Движок» PHP
  Переход на PHP 5.3
New Переход на PHP 5.6
  Введение в PHP
  Изучение PHP
  Основы CGI
  Синтаксис PHP
  Типы данных PHP
  Переменные в PHP
  Константы PHP
  Выражения PHP
  Операторы PHP
  Конструкции PHP
  Ссылки в PHP
  PHP и ООП
  Безопасность
  Функции PHP
  Функции по категориям
  Функции по алфавиту
  Стандартные функции
  Пользовательские
  PHP и HTTP
  Работа с формами
  PHP и Upload
  PHP и Cookies
  PHP и базы данных
  PHP и MySQL
  Документация MySQL
  Учебники
  Учебники по PHP
  Учебники по MySQL
  Другие учебники
  Уроки PHP
  Введение
  Самые основы
  Управление
  Функции
  Документация
  Математика
  Файлы
  Основы SQL
  Дата и время
  CURL
  Изображения
  Стили
  Безопасность
  Установка
  Проектирование БД
  Регулярные выражения
  Подготовка к работе
  Быстрый старт
  Установка PHP
  Установка MySQL
  Конфигурация PHP
  Download / Скачать
  Скачать Apache
  Скачать PHP
  Скачать PECL
  Скачать PEAR
  Скачать MySQL
  Редакторы PHP
  Полезные утилиты
  Документация
  PHP скрипты
  Скачать скрипты
  Инструменты
  PHP в примерах
  Новости портала
 Главная   »  Сборник статей
 
 

Защита от спама на сайте

Автор: Дмитрий Лебедев

Источник: phpclub.ru

Рассуждения о том, как убрать все почтовые адреса и оставить вместо них на сайте лишь формоотправитель.

Введение в проблему

Все мы знаем, что такое спам, потому что либо сталкивались с этим, либо читали об этом. Все мы знаем, как спамеры собирают адреса для рассылок. Так же не секрет, что спам невозможно победить полностью. Проблема состоит в том, как максимально защитить пользователей, оставляющих свои контанктные координаты на вашем сайте, минимальными усилиями.

Ранее испытанные способы защиты

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

<?php
$text
= preg_replace("~(<a[^>]+href=)([\"']?)mailto:([\\w_\\.\\-]+)([\\w_\\.\\-])@". <br>"([\\w_\\.\\-])([\\w_\\.\\-]+\\.[a-z]{2,4})\\2([ >])~i", "\\1\"mailto:spamux@nospam.ru\" <br>onMouseover=\"this.href='mai' + 'lto:\\3' + '\\4' + '%40' + '\\5' + '\\6';\"\\7", $text);
?>

К сожалению, она не сработает, если у вас большой сайт. Скажем, spectator.ru, автор которого одним из первых стал использовать этот метод. Будь я спамером, я бы залез в персональные настройки, поставил галочки "не показывать ушки", 1000 отзывов на странице, и отловил куки Proxomitron'ом. Потом качалкой или php-скриптом выкачал бы страницы с комментариями (подставив куки с настройками) и при помощи регулярного выражения выловил адреса. Получил бы небольшую базу для рекламной рассылки.

Была ещё пара способов защиты, в которых ссылка mailto: автоматически заменяется на кукую-либо другую, но эффект оставался прежний — при нажатии на неё системный клиент создавал бы письмо по нужному адресу. Оба они не выдержали критики.

Знакомьтесь: ежовые рукавицы

Очевидно, сложно придумать другой способ защиты кроме уже испытанного — предоставления формы на сайте для отправки сообщения. Займёмся её проектированием. Достоинства способа очевидны: никто уже не сможет достать из вашего сайта адреса для своей спамерской базы данных. Отсылать сообщения, спрятав свой адрес, как это делают спамеры, не получится — веб-сервер зафиксирует его IP-адрес. Списки публичных анонимных прокси-серверов регулярно обновляются, и заблокировать доступ с них легко.

Формоотправитель

Начнём именно с него, потому что это самая сложная часть.

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

Во-первых, защитимся от глупых двойных нажатий и отправки множества одинаковых запросов. Идея такова: сообщение не будет отправлено, если перед этим пользователь не открыл страницу с формой, а, открыв страницу с формой, можно отправить сообщение только один раз. Сделать это можно при помощи встроенных в PHP сессий. При открытии страницы с формой мы запустим сессию, в которую сохраним переменную, скажем $flag. Идентификатор сессии выведем как спрятанный элемент в самом конце формы. Пользователь вводит сообщение и отправляет форму. Получая форму, скрипт запускает сессию и проверяет наличие и значение переменной $flag. Если переменная не существует, значит это повторное нажатие, письмо не отсылается и выдаётся сообщение об ошибке. Если переменная есть, и данные формы нас устроили (заполнены нужные поля), скрипт отсылает письмо и удаляет сессию.

Во-вторых, защитимся от умных хулиганов, записывая логи сообщений. Если пользователь отправлят правильно заполненную форму, скрипт будет смотреть в логи и проверять, что там. Так, нужно запретить

  • отправлять сообщения по одному и тому же адресу чаще определенного периода
  • отправлять один и тот же текст по разным адресам
  • и просто слишком часто пользоваться формоотправителем — скажем, не более 10 сообщений в сутки на одного пользователя

ID сессии выводим в самом конце формы, чтобы хакеру требовалось скачивать всю форму и разбирать её, что сложнее, чем просто отправлять HTTP-запросы. Естественно, формоотправитель будет выдавать сообщения об ошибках в написании сообщения, требование указать обратный адрес и т.п.

Получившийся код формоотправителя оказался слишком большим, чтобы приводить его в тексте. Он помещён в архив на сайте. Вроде бы, скрипт работает и отправляет сообщения.

Замена адресов в тексте

Теперь формоотправитель готов, и нужно заменить все email`ы на ссылки на него. Конечно же, вручную делать этого не стоит. Для себя я написал скрипт, автоматически заменяющий адреса на ссылки к формоотправителю.

Учет ссылок / битые ссылки. Часто приходится ссылаться на одно и то же, также часто ссылки устаревают и «ломаются». Идея: хранить все ссылки в одном месте, нумировать их, и ссылаться на них в виде <a href=link.php3?id=10>.

...Минусы: большее время на расстановку ссылок (компенсирующееся каталогом ссылок), пользователь, наводя курсор на ссылку, не видит, по какому адресу он попадет. (Дмитрий Смирнов, "Идеальный авторский проект, гипертекстуальность")

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

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

Итак, что делает заменитель адресов. Он ищет в тексте ссылки "mailto:", выбирает из них адреса, отправляет запрос в базу, чтобы подсчитать (count(*)), сколько адресов из тех, что на странице, есть в специальной таблице. Если на странице новые адреса, то их число будет больше, чем результат запроса. В таком случае делается запрос, в котором выбираются значения адресов, и уже существующие в таблице исключаются из списка. Оставшийся список отправляется в таблицу INSERT-запросом.

Что касается ID адресов, то, на мой взгляд, лучше использовать что-то, что посетитель сайта не мог бы подобрать. Представляете, на формоотправитель ведёт ссылка /email.php?id=10 ? Какой соблазн подставить туда 11, 12 и т.д. и попробовать отправить им всем сообщение. Поэтому в качестве идентификаторов я решил использовать md5-хэш от адресов. Подбирать хэш вряд ли кто возьмётся. В случае с каталогом ссылок можно обойтись и ID, но тогда придётся выбирать из базы все значения, а для замены адресов на их хэши всё гораздо проще.

Выполняется команда вида

<?php
$text
= preg_replace("~(<a[^>]+href=)". "(['\"]?)mailto:([\\w_\\.\\-]+@[\\w_\\.\\-]+". "\\.[a-z]{2,4})\\2(.*?>)~ie", "'\\1\\2\"/email.php?email='. urlencode(md5('\\3')). '\"\\4'", $text);
?>

...которая заменяет адреса на их хэши. Остальные адреса, находящиеся в тексте, я не решился заменять на ссылки, а сделал простую замену на адреса типа vasya_at_pupkin_dot_ru. Код автозаменителя так же есть в архиве.

Итог

Прятать почтовые адреса от посетителей довольно просто. Механизм автозамены не требует дополнительных усилий, и вы можете писать страницы сайта дальше, как будто бы ничего не произошло. Сложности возникают при защите формоотправителя от веб-хулиганов. Эта защита требует больших усилий и сложного кода, поэтому пока что я не стал использовать на сайте написанный код. Вы можете скачать архив с заменителем адресов и формоотправителем, только очень прошу: не ставьте его на свой сайт в том виде, в котором скачали, я сам не знаю, насколько надёжно он работает.

Впрочем, возможно, я слишком жестко стараюсь защититсья от флуда. Ведь одно дело слать спам, используя ошибки почтовых серверов и пряча свой адрес, а другое - заходить по на веб-сервер, который записывает всё, что ты делал. Доступ с анонимных прокси к формоотправителю, естественно, следует закрывать.

 
 » Обсудить эту статью на форуме

 
 Сборник статей 
 Содержание раздела 
Есть еще вопросы или что-то непонятно - добро пожаловать на наш  форум портала PHP.SU 
 

 
Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS