Спамозащита в MediaWiki + nginx. Часть 1.
Mar. 7th, 2013 04:00 pmУ меня есть wiki на не самом плохом, с точки зрения SEOшников домене. И в какой-то момент туда полез спам. Крайне активно. При этом начало этого процесса я проворонил, и уж не знаю обмениваются ли спамеры между собой базами, или каждый нарывает свою, но попал я во многие базы, это точно.
С этим надо было что-то делать. И вот что я сделал
1. Знать что происходит. В LocalSettings.php добавляем настройку, которая будет оповещать Вас о любом изменении сделанном в вики:
Nataraj -- в данном случае имя пользователя, на чей адрес приходят оповещения. More Info
2 Знать откуда происходит. Если ваша вики стоит за проксирующим фронтендом, не плохо бы сделать так, чтобы в веб-логи и в базу MediaWiki попадали реальные IP адреса запросов, а не адрес фронтенда. Для этого в конфиге nginx'а добавляем
где 111.222.33.44 -- адрес вашего фронтенда. Тогда в логи будут попадать IP адреса из заголовка X-Forwarded-For More Info
и в LocalSettings.php добавляем
И тогда сама MediaWiki для запросов пришедших с 111.222.33.44 будет запоминать не этот адрес, а адрес из X-Forwarded-For. More info
3. Капча на все случаи жизни. В любом случае на сайте следует поставить каптчу. Я предпочитаю FancyCaptcha, поскольку она адекватно работает в случае включенного JavaScript'а. Она входит в дистрибутив, ее надо только включить, и сгенерить ей картинки, так как это рекомендовано в руководстве.
3.1. Если у вас мало изменяемая вики, или вики которую с среднем правят узкая группа людей, то каптчу следует поставить на все изменения, которые происходят, добавив всех кого надо в список привелегированных пользователей.
3.2. Вы наверное могли заметить, что на в мануале FancyCaptcha относится к числу не рекомендованных. И правда, если сгенерировать каптчи ровно по инструкции, то получатся картинки "как у всех", которые спамеры хорошо научились распознавать... Поэтому рекомендую простыми методами сделать не как у всех. Используя либо ImageMagic, либо пакетную обработку фотошопа, докорёжте картинки так, чтобы сделать ее неподходящей для робота распознавателя, настроенного на картинки "как у всех". Как именно это сделать -- советовать не буду, каждый должен избрать свой путь. Иначе мы получим новую "как у всех"
4. Черный Список. Есть замечательный ресурс http://www.stopforumspam.com, собирающий данные о спамерской активности на форумах и сайтах. Они ежечасно обновляют список опасных IP адресов, и для этих адресов можно либо закрыть доступ, либо сделать для них специальную Read Only версию сайта, чтобы живые пользователи не страдали если что. На сайте MediaWiki предлагается вот такое-вот php-only решение Я его пробовал применить на практике, но при нынешних объемах черного списка и объеме идущего спама, оно безбожно ело процессор. Поэтому я решил перевести процесс блокировки на уровень веб сервера. Перевод делается в несколько шагов.
4.1. Изготовление read-only копии сайта. Следующий скрипт делает при помощи символических ссылок полную копию сайта, за исключением файла конфигурации LocalSettings.php, сам файл конфигурации копируется штатными средствами, и в него добавляются настройки выключающие возможность редактирования
В хостнейме для r/o копии www. заменяется на ro. или в случае если www. не было ro. просто добавляется. Это знание понадобится потом, когда будем писать новый nginx конфиг.
4.2. Создаем список запрещенных IP адресов в nginx. Для того чтобы в конфиге разнести отдачу для белого и для черного списка, мы воспользуемся модулем geo. И для этого нужно сконвертировать csv который дает нам stopforumspam в geo'вский список IP'шников.
Для этого я написал следующий скрипт:
И добавляем запуск этого скрипта в /etc/rc.local
4.5. Тестируем Проверяем, все запуская все скрипты руками, а так же руками вписываем свой текущий IP'шник в /etc/nginx/sites-enabled/bad_ip_list.conf перезапускаем сервер и убеждаемся что теперь нас не пускают редактировать собственное wiki. Bingo! Еще полезно вписать MAILTO=my-email@example.com в /etc/crontab и получать письма, если что-то в работе скриптов пошло не так.
5. Если вы дочитали до этого места и вам понравилось... 41001103370866 - яндекс деньги
5.1. Вопросы, комментарии и критика -- принимаются...
См. также часть 2.
С этим надо было что-то делать. И вот что я сделал
1. Знать что происходит. В LocalSettings.php добавляем настройку, которая будет оповещать Вас о любом изменении сделанном в вики:
$wgUsersNotifiedOnAllChanges = array( 'Nataraj' );
Nataraj -- в данном случае имя пользователя, на чей адрес приходят оповещения. More Info
2 Знать откуда происходит. Если ваша вики стоит за проксирующим фронтендом, не плохо бы сделать так, чтобы в веб-логи и в базу MediaWiki попадали реальные IP адреса запросов, а не адрес фронтенда. Для этого в конфиге nginx'а добавляем
set_real_ip_from 111.222.33.44;
real_ip_header X-Forwarded-For;где 111.222.33.44 -- адрес вашего фронтенда. Тогда в логи будут попадать IP адреса из заголовка X-Forwarded-For More Info
и в LocalSettings.php добавляем
$wgUsePrivateIPs = true; $wgSquidServersNoPurge = array( '111.222.33.44' );
И тогда сама MediaWiki для запросов пришедших с 111.222.33.44 будет запоминать не этот адрес, а адрес из X-Forwarded-For. More info
3. Капча на все случаи жизни. В любом случае на сайте следует поставить каптчу. Я предпочитаю FancyCaptcha, поскольку она адекватно работает в случае включенного JavaScript'а. Она входит в дистрибутив, ее надо только включить, и сгенерить ей картинки, так как это рекомендовано в руководстве.
3.1. Если у вас мало изменяемая вики, или вики которую с среднем правят узкая группа людей, то каптчу следует поставить на все изменения, которые происходят, добавив всех кого надо в список привелегированных пользователей.
$wgCaptchaTriggers['edit'] = true; $wgCaptchaTriggers['create'] = true;
3.2. Вы наверное могли заметить, что на в мануале FancyCaptcha относится к числу не рекомендованных. И правда, если сгенерировать каптчи ровно по инструкции, то получатся картинки "как у всех", которые спамеры хорошо научились распознавать... Поэтому рекомендую простыми методами сделать не как у всех. Используя либо ImageMagic, либо пакетную обработку фотошопа, докорёжте картинки так, чтобы сделать ее неподходящей для робота распознавателя, настроенного на картинки "как у всех". Как именно это сделать -- советовать не буду, каждый должен избрать свой путь. Иначе мы получим новую "как у всех"
4. Черный Список. Есть замечательный ресурс http://www.stopforumspam.com, собирающий данные о спамерской активности на форумах и сайтах. Они ежечасно обновляют список опасных IP адресов, и для этих адресов можно либо закрыть доступ, либо сделать для них специальную Read Only версию сайта, чтобы живые пользователи не страдали если что. На сайте MediaWiki предлагается вот такое-вот php-only решение Я его пробовал применить на практике, но при нынешних объемах черного списка и объеме идущего спама, оно безбожно ело процессор. Поэтому я решил перевести процесс блокировки на уровень веб сервера. Перевод делается в несколько шагов.
4.1. Изготовление read-only копии сайта. Следующий скрипт делает при помощи символических ссылок полную копию сайта, за исключением файла конфигурации LocalSettings.php, сам файл конфигурации копируется штатными средствами, и в него добавляются настройки выключающие возможность редактирования
#!/usr/bin/perl
use strict;
use File::Path qw(remove_tree);
my $orig_path = '/var/www/';
my $ro_path = $orig_path."-ro";
my $ro_hostname_prefix = "ro.";
remove_tree($ro_path);
mkdir ($ro_path);
opendir(my $dh, $orig_path);
my $file;
while ($file= readdir $dh)
{
if (! ($file ~~ ['.','..','LocalSettings.php']))
{
print $file,"\n";
`ln -s "$orig_path/$file" "$ro_path/$file"`;
}
}
closedir($dh);
open F, "$orig_path/LocalSettings.php";
open F2, ">", "$ro_path/LocalSettings.php";
while (my $s = )
{
$s=~s{(\$wgSitename\s*=\s*".*)(";)} {$1 - Read only version for known SPAM bots$2};
$s=~s{(\$wgServer\s*=\s*"http://)(?:www\.)?(.*";)}{$1$ro_hostname_prefix$2};
print F2 $s;
}
print F2 "\n\$wgReadOnly = 'SPAM alert. Your IP is tainted';\n";
close F;
close F2;
В хостнейме для r/o копии www. заменяется на ro. или в случае если www. не было ro. просто добавляется. Это знание понадобится потом, когда будем писать новый nginx конфиг.
4.2. Создаем список запрещенных IP адресов в nginx. Для того чтобы в конфиге разнести отдачу для белого и для черного списка, мы воспользуемся модулем geo. И для этого нужно сконвертировать csv который дает нам stopforumspam в geo'вский список IP'шников.
Для этого я написал следующий скрипт:
#!/usr/bin/perl
use strict;
# http://www.mediawiki.org/wiki/Manual:Combating_spam#IP_address_blacklists
my $cache_dir = '/var/cache';
my $config_file = '/etc/nginx/sites-enabled/bad_ip_list.conf';
my $log = "";
if ('daily' ~~ \@ARGV || ! -e "$cache_dir/bannedips.zip")
{
# print "Ежедневный запуск\n";
$log.=`rm -f $cache_dir/bannedips.zip`;
$log.=`cd $cache_dir ; wget http://www.stopforumspam.com/downloads/bannedips.zip 2>&1`;
my_die("bannedips.zip failed to download") unless -e "$cache_dir/bannedips.zip";
$log.=`rm -f $cache_dir/bannedips.csv`;
$log.=`cd $cache_dir ; unzip bannedips.zip`;
}
if (! ('daily' ~~ \@ARGV) || ! -e "$cache_dir/listed_ip_1.zip")
{
# print "Ежечасный запуск\n";
$log.=`rm -f $cache_dir/listed_ip_1.zip`;
$log.=`cd $cache_dir ; wget http://www.stopforumspam.com/downloads/listed_ip_1.zip 2>&1`;
my_die("listed_ip_1.zip failed to download") unless -e "$cache_dir/listed_ip_1.zip";
$log.=`rm -f $cache_dir/listed_ip_1.txt`;
$log.=`cd $cache_dir ; unzip listed_ip_1.zip`;
}
open F2 ,">", "$config_file.new" or die;
print F2 "geo \$bad_ip {\n";
print F2 " default 0;\n";
my %known_addresses = ();
open F, "$cache_dir/listed_ip_1.txt" or die;
while (my $ip = )
{
$ip =~ s/\n\z// or die;
my_die("$ip is not IP address") unless is_ip($ip);
print F2 " $ip 1;\n";
$known_addresses{$ip} = 1;
}
close F;
open F, "$cache_dir/bannedips.csv" or die "Error opening 'bannedips.csv': \$!";
{
local $/ = ',';
while (my $ip = )
{
$ip =~ s/\,\z// or die;
my_die("$ip is not IP address") unless is_ip($ip);
print F2 " $ip 1;\n" unless $known_addresses{$ip};
}
}
close F;
print F2 "}\n";
close F2;
`mv $config_file $config_file.old`;
`mv $config_file.new $config_file`;
`rm $config_file.old`;
sub is_ip
{
my $ip = shift;
$ip =~ /^(\d)+\.(\d+)\.(\d+)\.(\d+)\z/ or return 0;
return 0 if $1<0 || $1>255;
return 0 if $2<0 || $2>255;
return 0 if $3<0 || $3>255;
return 0 if $4<0 || $4>255;
return 1;
}
sub my_die
{
print $log;
die @_;
} И добавляем запуск этого скрипта в /etc/rc.local
/usr/local/bin/nginx-watchdog.pl &
4.5. Тестируем Проверяем, все запуская все скрипты руками, а так же руками вписываем свой текущий IP'шник в /etc/nginx/sites-enabled/bad_ip_list.conf перезапускаем сервер и убеждаемся что теперь нас не пускают редактировать собственное wiki. Bingo! Еще полезно вписать MAILTO=my-email@example.com в /etc/crontab и получать письма, если что-то в работе скриптов пошло не так.
5. Если вы дочитали до этого места и вам понравилось... 41001103370866 - яндекс деньги
5.1. Вопросы, комментарии и критика -- принимаются...
См. также часть 2.