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. Само собой надо проверить, не появилось ли что-нибудь поновее.
Для подготовки процесса надо поставить некоторые пакеты, которые нам понадобятся:
apt-get install apache2-prefork-dev libxml2-dev libcurl4-openssl-dev
Для начала качаем и компилируем ModSecurity:
wget https://www.modsecurity.org/tarball/2.7.4/modsecurity-apache_2.7.4.tar.gz tar -xzvf modsecurity-apache_2.7.4.tar.gz cd modsecurity-apache_2.7.4 ./configure --enable-standalone-module make && make install
Теперь качаем и компилируем Nginx:
wget http://nginx.org/download/nginx-1.4.2.tar.gz tar -xzvf nginx-1.4.2.tar.gz cd nginx-1.4.2/ ./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/ 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'е добавить две строки:
ModSecurityEnabled on; ModSecurityConfig /etc/modsecurity/login.conf;
Например:
location @backend{ ModSecurityEnabled on; ModSecurityConfig /etc/modsecurity/login.conf; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:8080; proxy_redirect off; }
Кажись, на этом всё. 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 »