Nginx и ModSecurity
Date July 19th, 2013 Author Vitaly Agapov
Всем хорош Nginx, но у Apache всегда была целая россыпь козырей в рукаве, не позволявшая Nginx'у приблизиться к нему в его неимоверной крутости. Одним из таких козырей был плагин ModSecurity, про который я относительно недавно опять писал статейку. Каково же было моё удивление, тщательно перемешанное с радостью, когда я узнал, что ModSecurity теперь работает и с Nginx'ом и что этот плагин только-только вышел из беты. Радость была обоснована ещё и тем, что незадолго до того я искал какие-нибудь аналоги для использования. Тыкал палочкой Naxsi, но ничего под свои нужды так и не нашёл. А тут такой подарок.
Подарок оказался не без сюрпризов. Но обо всём по порядку.
Введение
Грубо говоря, запилили не столько модуль для Nginx, сколько standalone-реализацию самого ModSecurity, которую можно использовать практически с любым софтом, сделав небольшую прокладку-модуль. И как раз такую вот прокладку сделали для Nginx и для IIS.
Компиляция и установка
На момент написания сего текста самыми свежими версиями являются nginx-1.4.2 и modsecurity-2.7.4. Само собой надо проверить, не появилось ли что-нибудь поновее.
Для подготовки процесса надо поставить некоторые пакеты, которые нам понадобятся:
1.
apt-get
install
apache2-prefork-dev libxml2-dev libcurl4-openssl-dev
Для начала качаем и компилируем ModSecurity:
2.
tar
-xzvf modsecurity-apache_2.7.4.
tar
.gz
3.
cd
modsecurity-apache_2.7.4
4.
./configure --
enable
-standalone-module
5.
make
&&
make
install
Теперь качаем и компилируем Nginx:
1.
wget http://nginx.org/download/nginx-1.4.2.
tar
.gz
2.
tar
-xzvf nginx-1.4.2.
tar
.gz
3.
cd
nginx-1.4.2/
4.
./configure --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --sbin-path=/usr/sbin/nginx --error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --with-http_geoip_module --with-http_stub_status_module --with-http_ssl_module --with-ipv6 --with-http_perl_module --add-module=../modsecurity-apache_2.7.4/nginx/modsecurity/
5.
make
&&
make
install
Само собой, в ./configure надо вставлять нужные для каждого конкретного случая параметры, но главным в нашем повествовании является ключ –add-module=../modsecurity-apache_2.7.4/nginx/modsecurity/, указывающий на то место, где лежит ModSecurity для Nginx.
При старте Nginx должен будет в error.log выплёвывать несколько строк, которые укажут нам, что ModSecurity работает и на коне:
2013/07/19 10:23:28 [notice] 24221#0: ModSecurity for nginx (STABLE)/2.7.4 (http://www.modsecurity.org/) configured.
2013/07/19 10:23:28 [notice] 24221#0: ModSecurity: APR compiled version="1.4.6"; loaded version="1.4.6"
2013/07/19 10:23:28 [notice] 24221#0: ModSecurity: PCRE compiled version="8.12 "; loaded version="8.12 2011-01-15"
2013/07/19 10:23:28 [notice] 24221#0: ModSecurity: LIBXML compiled version="2.7.8"
Настройка
Допустим мы хотим использовать уже готовый конфиг для ModSecurity, который у нас отлично работает на Apache. Что ж, это вполне возможно. Пусть в /etc/modsecurity/login.conf лужит набор директив, которые я разбирал в вышеупомянутой статье. Прежде всего надо добавить в каждый SecRule в список действий идентификатор правила вида id:<уникальное число>, так как он стал обязателен в новой версии ModSecurity. Например:
SecRule REQUEST_BASENAME "login.htm" "id:100,phase:1,nolog,pass,initcol:ip=%{REMOTE_ADDR},setvar:ip.requests=+1,expirevar:ip.requests=2"
Затем для их подключения надо в общем конфиге виртуал хоста или в нужном нам location'е добавить две строки:
1.
ModSecurityEnabled on;
2.
ModSecurityConfig /etc/modsecurity/login.conf;
Например:
1.
location @backend{
2.
ModSecurityEnabled on;
3.
ModSecurityConfig /etc/modsecurity/login.conf;
4.
proxy_set_header X-Forwarded-Proto $scheme;
5.
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
6.
proxy_pass http://127.0.0.1:8080;
7.
proxy_redirect off;
8.
}
Кажись, на этом всё. Nginx можно рестартовать и наслаждаться жизнью. Но…
Segfault при попытке сделать reload
Да, при наличии в конфигурации ModSecurity директив SecRule процесс Nginx сегфолтится при попытке сделать релоад. При этом рестарт проходит отлично. Проблема касается только версии 2.7.4. Если в вашем будущем версия 2.7.5 уже зарелизилась, то проблема скорее всего уже отсутствует.
При релоаде в dmesg сваливаются ошибки вида:
nginx[25847]: segfault at 70 ip 00007ffe25a7eddc sp 00007fff895c8c00 error 4 in libapr-1.so.0.4.6[7ffe25a60000+38000]
При этом страницы не отдаются, а в логе Nginx'а валится:
[client 10.0.0.1] ModSecurity: Rule processing failed. [uri "/home.htm"]
С проблемой можно либо смириться и делать всегда рестарт, либо решить её следующим образом. Дело в том, что фикс этой проблемы уже есть в транке на GitHub'е. Вот соответствующий коммит: https://github.com/chaizhenhua/ModSecurity/commit/4ffdf9bf6d343e9146de360183629e0e0bc59add
Мы просто качаем файл https://raw.github.com/chaizhenhua/ModSecurity/4ffdf9bf6d343e9146de360183629e0e0bc59add/nginx/modsecurity/ngx_http_modsecurity.c и заменяем им тот, который лежит в modsecurity-apache_2.7.4/nginx/modsecurity/. После чего проворачиваем всю компиляцию заново. У меня сработало.
Tags: ModSecurity, Nginx
Category:
Nginx |
No comments »