NGINX -- нетривиальная защита админки WP / любой CMS -- делюсь

J
На сайте с 21.08.2011
Offline
78
11265

Предлагаю вашему вниманию своё решение защиты админки WP (или любой другой CMS -- не важно) для серверов, работающих на NGINX. Совсем нетривиальное, как мне кажется.

"Чё, изобретаешь велосипед?" -- спросите вы. :crazy:

Да, потому как все виденные мною решения (в том числе из этой темы), лично мне, совсем не понравились. Куки юзать? Не подходит хотя бы по одной простой причине -- я вообще не хочу, чтобы кто-то мог узнать/зайти по адресу wp-admin -- просто не хочу, чтобы кто-то знал, что мой сайт вообще работает на WP. И сайт сделан так, что только очень опытный юзер сможет распознать именно WP (да-да, вы нигде не увидите в сорсах wp-content или чего-то подобного). ;)

В общем, были поставлены вот такие задачи:

1. Отсечь ботов.

2. Снизить нагрузку на сервер -- отдавать 404 средствами NGINX, а не CMS, не пропуская к PHP.

3. Скрыть использование/админку WP и для обычных юзеров, а не только ботов.

4. Не модифицировать исходник WP (не переименовывать wp-login.php и прочее).

5. Возможность без проблем юзать свой сайт с динамического IP. Тупо "allow $myip" тут совсем не подходит.

6. Удобство.

7. Никаких плагинов WP -- смерть им всем, ибо жутко кривые часто и тормозят всю систему.

Ломал я свою голову над этим ТЗ целый вечер и ночь. :crazy: Ломал долго, потому как в серверных делах и в NGINX в частности я далеко не спец.:idea:

Что же получилось в итоге. Итак, мой "велосипед", который проверен на NGINX 1.4.4 + php5-fpm (php 5.5):

1. Создаём php файл в корне сайта и называем его как вашей душе угодно. Содержимое:

<?php
$ip = $_SERVER["REMOTE_ADDR"];
$msg = '404';
if ( !$ip || (strlen($ip) < 8) || (strlen($ip) > 16) ) { $ip = '127.0.0.0'; $msg = '2 x 404'; }
$openit = fopen('ips-alllowed/' . $ip, 'w');
fclose($openit);
echo "<p>$msg</p>";
http_response_code(404);

Думаю, тут всё понятно, но поясню для людей не в теме (пояснение по строчкам):

1. Выясняем IP обратившегося.

2. Дефолтный ответ, который вы увидете в браузере, если IP нормальный. Опционально.

3. Простая проверка IP на "нормальность" -- защита от "случайных случаев". :) Пропустит только похожее на IPv4. Если будет что-то не так -- пропишется IP локалхоста (127.0.0.0), а в браузере вы увидите ответ "2 х 404" (можете заменить на что угодно).

4. Открываем файл, который будет иметь название === IP. Если файла нет, то он будет создан. Замечание: не забудьте создать папку и выставить правильные права у "ips-allowed".

5. Закрываем файл, ничего в него не записывая, ибо нам не зачем.;)

6. Эхаем в браузер наш ответ. Опционально.

7. Отдаём 404-ый ответ любому обратившемуся к этому php файлу. Опционально. Гарантирует неиндексацию ботами и непонимание случайным юзерам. :D:

Обращение будете делать к ваш_сай/ваш_файл.php

На этом с php всё.

2. Редактируем конфиг сервера NGINX:

....

http {

...
$root_path = путь_к_корню_вашего_сайта
...

location ~ ^/(wp-admin|wp-login\.php) {
if (!-f $root_path/ips-allowed/$remote_addr) {
return 404;
# здесь можно отдавать любой ответ -- как пожелаете
}

# сюда идут все ваши настройки fast-cgi или proxyApache для передачи php

}
.....
}

3. Всё. :popcorn:

При каждом запросе к админке (или другому пути в location -- как пожелаете) идёт проверка наличия файла с именем равным вашему IP ($remote_addr -- переменная NGINX). Эта проверка -- единственное, что нагружает NGINX, но без неё никак. И, ИМХО, нагрузка тут будет не шибко большая -- любой нормальный сервер (VPS даже) выдержит 1000 запросов в минуту и не поперхнётся. Проверено на 5-баксовом Digitalocean. В дополнение ко всему не забывайте использовать limit_req.

С удовольствием выслушаю любую критику и/или предложения, вопросы.:popcorn:

Ещё раз повторяю: я в этих серверных делах не профи, но попробовал -- пашет хорошо (на первый взгляд).

п.с.: ах, да, забыл сказать, что же делать с накапливающимися файлами -- очистка папки по cron вам в помощь. ;)

S
На сайте с 09.10.2007
Offline
186
#1

а не проще просто allow/deny?

http://wiki.nginx.org/HttpAccessModule

Удобная панель для доменных имен (http://panel.started.ru/) с массовыми операциями. Индивидуальные цены по запросу.
J
На сайте с 21.08.2011
Offline
78
#2
simka:
а не проще просто allow/deny?
http://wiki.nginx.org/HttpAccessModule

Что именно?

У меня в NGINX в if (...) allow/deny выдавало ошибку конфига (нельзя там это использовать, видимо). return -- нет.

siv1987
На сайте с 02.04.2009
Offline
427
#3


location ~ ^/(wp-admin|wp-login\.php) {
allow 192.168.1.0/24;
deny all;
}
J
На сайте с 21.08.2011
Offline
78
#4

siv1987, вы вообще понимаете, зачем вся эта "пляска"?

Решение с одним IP -- никому не нужная ерунда. И даже с подсетями.

Весь кайф кода, что я привёл -- именно отвязка от IP. С любого IP можно зайти в админку просто посетив страницу одну до этого.

Прочитайте ещё раз.

Вот у меня динамический IP на ADSL (там, где живу, лучшего нет) и покупать статику я совсем не хочу по определённым причинам (+деньги, +не надо, +...).

Да плюс ко всему мне надо иметь возможность зайти с IP какого-нибудь оператора сотовой связи.

Или я отдыхаю в Эмиратах. Или у меня куча постеров/админов/модеров.

Для всех них писать и постоянно редактировать allow директиву? Смеётесь? :)

---------- Добавлено 17.02.2014 в 20:00 ----------

НЕБОЛЬШАЯ ПОПРАВКА!

Немного ошибся при описании $root_path в примере (написал как было бы в php :) ):

Вместо:

...
$root_path = путь_к_корню_вашего_сайта
...

Надо:

...
set $root_path путь_к_корню_вашего_сайта;
...
K5
На сайте с 21.07.2010
Offline
209
#5

т.е. в любом случае дополнительные манипуляции с обращением к скрытой странице?

тогда особо смысла и разницы с такой конструкцией нет (или другой вариант -получение спецкуки)

location ~* ^/(wp-admin|administrator|wp-login\.php|admin\.php) {
auth_basic "login and pass!!!";
auth_basic_user_file /etc/httpd/conf.d/.htpasswd;
location ~* ^/(wp-admin|administrator|wp-login\.php|admin\.php) {
proxy_pass http://$server_addr:81;
proxy_redirect http://$server_addr:81/ /;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
}
}

нагрузки нгиксу от выдачи окна авторизации (и как следствие 401 ошибки) 0 целых 0 десятых



---------- Добавлено 17.02.2014 в 21:55 ----------

кстати поделитесь секретом, как без модификации движка вы перекроили стандартные пути и папки ☝ ???

---------- Добавлено 17.02.2014 в 22:00 ----------

пока что выглядит именно как

велосипед
на свой манер 🤪

в чем "крутость" кода????

аська 45два48499два записки на работе (http://memoryhigh.ru) помогу с сайтом, удалю вирусы, настрою впс -> отзывы ТУТ (/ru/forum/836248) и ТАМ (http://www.maultalk.com/topic140187.html) !!!всегда проверяйте данные людей, которые сами пишут вам в аську или скайп!!!
J
На сайте с 21.08.2011
Offline
78
#6
kgtu5:
тогда особо смысла и разницы с такой конструкцией нет (или другой вариант -получение спецкуки)

Разницу с моим подходом смотри:

1. Нужно делать htpasswd.

2. Нужен лишний логин/пароль.

3. ЛЮБОЙ зайдёт в wp-admin и ему предоставят инфо, что "ДА, ЭТО WORDPRESS -- ДАЙ СВОЙ ЛОГИН/ПАРОЛЬ". Прямо-таки афиша с надписью: "(тр/x)а(х/к)ни меня!". :D

Это только на первый взгляд. ;)

---------- Добавлено 17.02.2014 в 22:10 ----------

kgtu5:
нагрузки нгиксу от выдачи окна авторизации (и как следствие 401 ошибки) 0 целых 0 десятых

Нагрузка от проверки наличия файла только для локации определёной также стремиться к нулю. И она меньше, чем авторизация с последующей проверкой. ;)

---------- Добавлено 17.02.2014 в 22:13 ----------

kgtu5:
кстати поделитесь секретом, как без модификации движка вы перекроили стандартные пути и папки ???

Зачем их перекраивать? ;) Чуток редиректов простейших и отказ от убогих плагинов. Относительные урлы.

Для относительного примера погуглите тему "WP Roots Theme". Идея оттуда взята.

---------- Добавлено 17.02.2014 в 22:13 ----------

kgtu5:
пока что выглядит именно как

Пока что не услышал в ответ ничего такого (с аргументами верными), чтобы это было именно так. ;)

Пока что выглядит именно как "я не понял чо это, но автор -- сами_знаете_кто". :)

Ничего, я не девочка и не малолетка -- всё понимаю. ;)

K5
На сайте с 21.07.2010
Offline
209
#7

1. ТС пока что твой вордпресс легко определим, даже не смотря на "невидимые" wp-admin и wp-login.php

Хочешь скажу как :) ?

2.

ЛЮБОЙ зайдёт в wp-admin

это каким же образом незнаючи логин и пароль ;)

3. локейшн в http и получаем

nginx: [emerg] "location" directive is not allowed here in

🙅

server наше все...

4.

Нагрузка от проверки наличия файла

тут можно поспорить, что больше нагрузит систему в целом - выдача запроса на авторизацию (уже загружено в оперативке и ждет выполнения) или создание новых файлов на жестком и обращение к ним, ибо брутфорсы не с одно ip идут ;) - вспомнить хотя бы августовский брут, когда хостеры банили по 10-30к ip

J
На сайте с 21.08.2011
Offline
78
#8
kgtu5:
1. ТС пока что твой вордпресс легко определим, даже не смотря на "невидимые" wp-admin и wp-login.php
Хочешь скажу как ?

Почитай выше внимательно, почему мой WP не так легко определим. ;)

Дело совсем не только в wp-admin/login.

kgtu5:
это каким же образом незнаючи логин и пароль

Я нигде не сказал, о том, что он пройдёт дальше авторизации. ;) Факт наличия этой самой авторизации даст понять, что перед нами WP.

kgtu5:
server наше все...

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

kgtu5:
тут можно поспорить, что больше нагрузит систему в целом - выдача запроса на авторизацию (уже загружено в оперативке и ждет выполнения) или создание новых файлов на жестком и обращение к ним, ибо брутфорсы не с одно ip идут - вспомнить хотя бы августовский брут, когда хостеры банили по 10-30к ip

Опять читаем через строчки и невнимательно? :)

Я, вот, старался, описывал, а вы даже прочитать внимательно один раз не можете. Обидно даже.

Таки ответьте мне, когда в моём примере (и сколько раз) создаются файлы с IP, и имеют ли к ним доступ и возможность создания сами боты? ;)

1к в минуту мой вариант отобьёт АБСОЛЮТНО легко и непринуждённо даже на VPS-ке за 5 баксов. И даже банить никого не надо. ;) Имитировал такую нагрузку на самом дешевом дроплете Digitalocean -- сайт вполне был отзывчив и работоспособен. 1к в минуту -- цифра немаленькая, не? :)

K5
На сайте с 21.07.2010
Offline
209
#9

потерто про жесткий

принципиального отличия от варианта с получением спецкуки нет...

Дело совсем не только в wp-admin/login.

Повторю: хочешь скажу как?

J
На сайте с 21.08.2011
Offline
78
#10
kgtu5:
принципиального отличия от варианта с получением спецкуки нет...

Да, конечно. Опять не читаем.

kgtu5:
Повторю: хочешь скажу как?

Давай-давай, конечно! К чему лишние вопросы?

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий