Как настроить смартфоны и ПК. Информационный портал

Веб сервер nginx что. Nginx: настройка и установка

Сегодня рассмотрим настройку виртуального хоста, обслуживающего сайт со статическим контентом. То бишь, никаких CGI, Perl, PHP и еже с ними. Все примеры, упоминающиеся в статье, относятся и проверялись на Debian Linux 5.0 Lenny . Владельцев других систем это никак не должно смущать, поскольку меняться могут только пути к файлам конфигурации, в то время как их содержимое применимо к любой системе, на которой работает Nginx.

Способ хранения файлов конфигурации

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

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

Include /etc/nginx/sites-enabled/*;

То есть, из каталога /etc/nginx/sites-enabled считывается содержимое всех файлов и применяется к текущей конфигурации сервера. Заглянув в упомянутый каталог, вы увидите там один файл default , являющийся символической ссылкой на файл /etc/nginx/sites-available/default . Тоже очень удобный подход: вам вдруг понадобилось отключить какой-то виртуальный хост, вы просто удаляете символическую ссылку, а на заморачиваетесь с перемещением файла туда-сюда.

Создание виртуального сервера

Для «чистоты эксперимента» предлагаю удалить поставляемую с дистрибутивом символическую ссылку /etc/nginx/sites-enabled/default и начать, так сказать, с чистого листа.

Создайте файл /etc/nginx/sites-available/myvhost со следующим содержимым:

Server { listen 80; server_name myvhost; access_log /var/log/nginx/myvhost.log; location / { root /var/www/myvhost/; index index.htm index.html; autoindex on; } }

Это и есть сама простая конфигурация виртуального сервера в Nginx. Теперь об используемых параметрах по порядку.

Первая опция server , за которой следует фигурная скобка, начинает новую секцию. Именно в секциях server и описываются конфигурации всех виртуальных серверов в Nginx.

Опцией listen мы сообщаем Nginx номер порта, на котором наш виртуальный сервер должен ожидать соединений. По умолчанию значение этой опции равно 80 , и в приведённом примере значение определено лишь для наглядности. Также при помощи этой опции можно указать не только номер порта, но и адрес сетевого интерфейса, к которому нужно «прицепить» данный сервер. Например следующие два примера «вешают» сервер на все доступные в системе TCP/IP-интерфейсы, на порт 8080:

Listen 8080 listen *:8080

Следующий пример связывает виртуальный сервер с определённым сетевым интерфейсом с IP-адресом 192.168.0.1, ожидая входящих соединений на порту 8080:

Listen 192.168.0.1:8080

Опция server_name определяет имя виртуального сервера, которое используется при анализе веб-сервером HTTP-заголовка Host , приходящего от клиента. Именно эта опция и реализует настройку виртуальных хостов, базирующихся на имени. Например, вот так будет выглядеть фрагмент конфигурации двух виртуальных хостов на одном сервере:

Server { ... listen 80; server_name example-1.com ... } server { ... listen 80; server_name example-2.com ... }

Параметров у опции server_name может быть более одного, таким образом вы можете определить псевдонимы вашего сервера, например:

Server_name example-1.com www.example-1.com www1.example-1.com

Также, можно использовать символ звёздочки, заменяющий любую последовательность символов в имени сервера:

Server_name example-1.com *.example-1.com

С параметром access_log мы знакомились в . Значение этого параметра определяет месторасположение и формат лог-файла доступа к контенту сервера.

Опция location заслуживает рассмотрения в отдельной заметке, поэтому в данной статье мы коснёмся её значения и возможностей лишь слегка, в объёме достаточном для конфигурирования статического веб-сервера. Использование опции location позволяет вам настраивать поведение сервера в зависимости от значения URI, полученного от клиента. Таким образом, секция server может содержать несколько вложенных секций location, описывающих конфигурацию на основе части URI. В примере, приведённом в начале статьи определён всего один location, которому будет соответствовать любой URI, полученный от клиента, поскольку любой URI содержит символ прямого слэша.

Например, если вам необходимо, чтобы при обнаружении в URI подстроки /images/ , Nginx не обращался в корневой каталог сервера, а искал файлы в каталоге /mnt/server2/var/www/images/ , можно определить следующие два location:

Location / { root /var/www/myvhost/; } location /images/ { root /mnt/server2/var/www/; }

В приведённых выше примерах использования location используется поиск подстроки в строке URI. То есть, подстрока /images/ будет найдена как в http://server/images /, так и http://server/my/images /. Если вам необходимо, чтобы Nginx выполнял поиск точного соответствия, для этого можно воспользоваться символом "=" , который и заставляет сервер вести поиск таким образом:

Location = /images/ { root /mnt/server2/var/www/; }

Также вы можете определить подстроку, с которой должен начинаться URI. Для этого используется конструкция из двух символов "^~" :

Location ^~ /images/ { ... }

Ну и регулярные выражения, само-собой, поддерживаются и дают большую гибкость при описании location. Следующий location будет соответствовать всем URI, содержащим в конце имена графических файлов (без учёта регистра):

Location ~* \.(gif|jpg|jpeg)$ { ... }

То же самое, но с учётом регистра:

Location ~ \.(gif|jpg|jpeg)$ { ... }

И немного о порядке очереди обработки опций location в Nginx. Вопреки тому, что многим кажется на первый взгляд, совершенно не имеет значения (кроме регулярных выражений, само-собой) в каком порядке определены location в конфигурационном файле. Как ни меняйте их местами, результат будет один и тот же. При поиске нужного локейшена, Nginx следует следующему алгоритму:

  1. Выполняется поиск правила, начинающегося с "=" . Как только такое правило будет найдено, дальнейший поиск будет прекращён.
  2. Выполняется поиск «обычных» правил, т. е. не регулярных выражений. Если среди них будет найдено правило, начинающееся с "^~" , дальнейший поиск будет прекращён.
  3. Обрабатываются регулярные выражения в том порядке, в котором они встречаются в файле конфигурации.
  4. Если будет найдено соответствие по п. 3, то будет использоваться именно этот location, в противном случае будет использоваться location, найденный в п. 2.

Опция root своим значением определяет путь к корню документов виртуального сервера на файловой системе.

При помощи опции index вы можете определить имена файлов индексных документов, которые будет «отдавать» клиентам Nginx, если был запрошен доступ к каталогу. Если в каталоге такого файла не окажется и для данного location отключена опция autoindex , то клиент в ответ получит HTTP-код 403 , говорящий о том, что доступ запрещён.

Опция autoindex настраивает поведение Nginx в случае, если в каталоге не найден запрашиваемый индексный файл. Если значением опции autoindex, как примере выше, является "on" , то сервер вернёт клиенту содержимое каталога в виде HTML-списка файлов. По умолчанию autoindex отключён, и будьте осторожны с ней, чтобы ненароком не вывесить на всеобщее обозрение критически-важную информацию.

Перезапуск сервера

Теперь, когда конфигурационный файл готов, необходимо сделать на него символическую ссылку из каталога /etc/nginx/sites-enabled/ , чтобы при перезапуске Nginx подключил его содержимое в свою конфигурацию:

# ln -s /etc/nginx/sites-available/myvhost /etc/nginx/sites-enabled/myvhost

# mkdir /var/www/myvhost

Осталось перезапустить сервер:

# /etc/init.d/nginx restart

И, если все настройки были выполнены без ошибок, вы сможете подключиться к вашему первому виртуальному серверу Nginx при помощи веб-браузера и увидеть пустой индекс файлов корневого каталога сервера. Попробуйте разместить пару статических html-файлов в каталоге /var/www/myshost и затем получить доступ к ним из вашего браузера.

В следующей статье мы рассмотрим конфигурацию SSL-сервера в Nginx.

Веб-сервер Nginx - это один из самых популярных веб-серверов с очень высокой производительностью и быстрой обработкой статических запросов от пользователей. При правильной настройке можно добиться очень высокой производительности от этого веб-сервера. Nginx очень быстро справляется со статическими файлами, будь то html страницы или другие виды ресурсов.

В одной из предыдущих статей мы уже рассматривали и настройку его основных параметров, в этой же статье я хочу больше остановиться на производительности и подготовке веб-сервера к использованию в боевых условиях. Что касается дистрибутива Linux, то сегодня мы будем рассматривать CentOS, эта система часто используется на серверах и с настройкой Nginx тут могут возникнуть некоторые сложности. Дальше будет рассмотрена настройка Nginx CentOS, поговорим как включить полную поддержку http2, google pagespeed, и настроить основной конфигурационный файл.

В официальных репозиториях CentOS есть Nginx и он, скорее всего, уже установлен в вашей системе. Но мы хотим чтобы сайт работал по протоколу http2, который позволяет передавать все данные одним подключением, а это увеличивает производительность. Для работы по http2 вам понадобиться настроить SSL сертификат, но об этом уже написано в статье получение сертификата Lets Encrypt Nginx. Но это еще не все. для переключения с обычного SSL на HTTP2.0 в большинстве браузеров сейчас используется протокол ALPN, а он поддерживается начиная с OpenSSL 1.02. В то время, как в репозиториях есть только OpenSSL 1.01. Поэтому нам нужно установить версию Nginx, собранную с OpenSSL 1.02. Для этого можно использовать Broken Repo:

sudo yum -y install yum-utils
# sudo yum-config-manager --add-repo https://brouken.com/brouken.repo

Если вы используете репозиторий EPEL, то нужно указать что не надо из него брать Nginx:

sudo yum-config-manager --save --setopt=epel.exclude=nginx*;

Теперь для установки правильной версии Nginx достаточно набрать:

sudo yum install nginx

Будет установлена самая последняя версия Nginx 1.13.2, с полной поддержкой ALPN. Дальше перейдем к настройке.

2. Настройка Nginx

Первым делом следует рассмотреть структуру конфигурационного файла. На первый взгляд, тут все может показаться очень запутанным, но там все достаточно логично:

глобальные опции
events {}
http{
server {
location{}
}
server {}
}

Сначала идут глобальные опции, которые задают основные параметры программы, например, от какого пользователя она будет запущена и количество процессов. Дальше есть секция events , в которой описано как Nginx будет реагировать на входящие подключения, затем идет секция http , которая объединяет все настройки касаемо работы протокола http. В ней находится секция server , каждая такая секция отвечает за отдельный домен, в секции server размещаются секции location , каждая из которых отвечает за определенный URL запроса, обратите внимание, что не файл на сервере, как в Apache, а именно URL запроса.

Основные глобальные настройки мы будем делать в файле /etc/nginx/nginx.conf. Дальше рассмотрим что именно будем менять и какие значения желательно установить. Начнем с глобальных опций:

  • user - пользователь, от имени которого будет запущен сервер, должен быть владельцем каталога с файлами сайта, и от имени его же нужно запускать php-fpm;
  • worker_processes - количество процессов Nginx, которые будут запущены, нужно установить ровно столько, сколько у вас есть ядер, например, у меня - 4;
  • worker_cpu_affinity - этот параметр позволяет закрепить каждый процесс за отдельным ядром процессора, установите значение auto, чтобы программа сама выбрала что и к чему крепить;
  • worker_rlimit_nofile - максимальное количество файлов, которые может открыть программа, на каждое соединение нужно как минимум два файла и каждый процесс будет иметь указанное вами количество соединений, поэтому формула такая: worker_processes * worker_connections* 2, параметр worker_connections разберем чуть ниже;
  • pcre_jit - включите этот параметр для ускорения обработки регулярных выражений с помощью JIT компиляции;

В секции events стоит настроить два параметра:

  • worker_connections - количество соединений для одного процесса, должно быть достаточным для обработки входящих соединений. Сначала нам нужно знать сколько этих входящих соединений есть, для этого смотрим статистику по адресу ip_сервера/nginx_status. Как включить рассмотрим ниже. В строке Active Connections видим количество активных соединений с сервером, также нужно учесть что соединения с php-fpm тоже считаются. Дальше обратите внимание на поля accepted и handled, первое отображает обработанных подключений, второе - количество принятых. Из значения должны быть одинаковыми. Если отличаются значит соединений не хватает. Смотрите примеры, первый снимок проблема, второй - порядок. Для моей конфигурации оптимальной может быть цифра в 200 соединений (всего 800, учитывая 4 процесса):

  • multi_accept - позволяет программе принимать несколько соединений одновременно, тоже ускоряет работу, при большом количестве соединений;
  • accept_mutex - установите значение этого параметра в off, чтобы сразу все процессы получали уведомление про новые соединения;

Также в секции events рекомендуется использовать директиву use epoll, так как этот самый эффективный метод обработки входящих соединений для Linux, но этот метод применяется по умолчанию, поэтому не вижу смысла добавлять его вручную. Рассмотрим еще несколько параметров из секции http:

  • sendfile - использовать метод отправки данных sendfile. Самый эффективный метод для Linux.
  • tcp_nodelay, tcp_nopush - отправляет заголовки и тело запроса одним пакетом, работает немного быстрее;
  • keepalive_timeout - таймаут поддержания соединения с клиентом, если у вас нет очень медленных скриптов, то будет достаточно будет 10 секунд, устанавливаем значение сколько нужно чтобы пользователь мог быть подключен к серверу;
  • reset_timedout_connection - разрывать соединения после таймаута.
  • open_file_cache - кэшировать информацию об открытых файлах. Например, open_file_cache max=200000 inactive=120s; max - максимальное количество файлов в кэше, время кэширования.
  • open_file_cache_valid - когда нужно проверить актуальность файлов. Например: open_file_cache_valid 120s;
  • open_file_cache_min_uses - кэшировать только файлы, которые были открыты указанное количество раз;
  • open_file_cache_errors - запоминать ошибки открытия файлов.
  • if_modified_since - устанавливает каким образом будут обрабатываться заголовки if-modified-since. С помощью этого заголовка браузер может получить ответ 304 если страница не изменилась с момента последнего просмотра. Возможны варианты - не отправлять - off, отправлять при точном совпадении времени - exact, отправлять если время совпадает точно или больше - before;

Вот как-то так будет выглядеть настройка nginx conf:

user nginx;
worker_processes 4;
worker_cpu_affinity auto;
worker_rlimit_nofile 10000;
pcre_jit on;

error_log /var/log/nginx/error.log warn;
load_module "modules/ngx_pagespeed.so";

events {
multi_accept on;
accept_mutex off;
worker_connections 1024;
}

sendfile on;
tcp_nopush on;
tcp_nodelay on;

open_file_cache max=200000 inactive=20s;
open_file_cache_valid 120s;
open_file_cache_errors on;

reset_timedout_connection on;
client_body_timeout 10;
keepalive_timeout 65;

include /etc/nginx/sites-enabled.*.conf

3. Настройка http2

Я не буду подробно описывать настройку секции server, потому что делал это уже в статье установка Nginx в Ubuntu и здесь мне нечего добавить, настройка SSL это достаточно обширная тема и тоже будет рассмотрена в отдельной статье. Но чтобы настроить http2 вам нужно иметь уже SSL. Далее, просто подправьте директиву listen в вашей секции server:

listen 194.67.215.125:443 default_server;

listen 194.67.215.125:443 http2 default_server;

Вот таким простым способом можно включить http2 если перед этим была установлена правильная версия Nginx.

4. Настройка PageSpeed

Google Pagespeed - это модуль Nginx, который выполняет различные оптимизации для того, чтобы страницы грузились быстрее, веб-сервер работал эффективнее, а пользователи не чувствовали дискомфорта. Сюда входит кэширование, оптимизация html кода, оптимизация картинок, объединение javascript и css кода и многое другое. Все это выполняется на уровне Nginx, поэтому эффективнее, чем если бы вы это делали в php. Но тут есть один недостаток, модуль удаляет заголовок Last Modified.

Дело в том, что PageSpeed устанавливает очень долгий строк кэширования для всех файлов, а в имя файла добавляет его хэш. Так скорость загрузки ресурсов выходит намного выше, поскольку браузер будет запрашивать файлы только с новым хэшем, а LastModified удаляется чтобы пользователи смогли увидеть изменения в случае если какой-либо файл будет изменен. А теперь рассмотрим как установить модуль. Нам придется собрать его из исходных кодов.

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

yum install wget gcc cmake unzip gcc-c++ pcre-devel zlib-devel

Скачайте и распакуйте исходники Nginx для вашей версии, например, 1.13.3:

wget -c https://nginx.org/download/nginx-1.13.3.tar.gz
# tar -xzvf nginx-1.13.3.tar.gz

Настройка сервера nginx не включает пере сборку и замену программы из репозитория, мы просто используем эти исходники для сборки модуля. Скачайте и распакуйте исходники PageSpeed:

wget -c https://github.com/pagespeed/ngx_pagespeed/archive/v1.12.34.2-stable.zip
# unzip v1.12.34.2-stable.zip

Скачайте и распакуйте библиотеку оптимизации PageSpeed в папку с исходниками модуля:

cd ngx_pagespeed-1.12.34.2-stable/
# wget -c https://dl.google.com/dl/page-speed/psol/1.12.34.2-x64.tar.gz
# tar -xvzf 1.12.34.2-x64.tar.gz

Скачайте и распакуйте исходники OpenSSL 1.02:

wget -c https://www.openssl.org/source/openssl-1.0.2k.tar.gz -O /opt/lib/$OPENSSL.tar.gz
# tar xvpzf openssl-1.0.2k.tar.gz

Теперь нам нужно собрать модуль. Сначала смотрим опции, с которыми собран текущий Nginx:

А теперь переходим в папку с Nginx, подставляем все полученные опции, опцию --add-dynamic-module для PageSpeed, OpenSSL и пробуем собрать:

cd nginx-1.13.3
# ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt="-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic" --with-ld-opt= --with-openssl=$HOME/openssl-1.0.2k --add-dynamic-module=$HOME/ngx_pagespeed-1.12.34.2-stable ${PS_NGX_EXTRA_FLAGS}
# make

Если все было сделано правильно, то на выходе вы получите модуль ngx_pagespeed.so в папке obj, его нужно скопировать в папку /etc/nginx/modules:

cp ngx_pagespeed.so /etc/nginx/modules/ngx_pagespeed.so

Создаем папку для кэша:

mkdir -p /var/ngx_pagespeed_cache
# chown -R nginx:nginx /var/ngx_pagespeed_cache

Теперь добавьте такую строчку для включения модуля в /etc/nginx/nginx.conf:

load_module "modules/ngx_pagespeed.so";

И другие). Текущая версия, 0.6.x, рассматривается как стабильная с точки зрения надежности, а релизы из ветки 0.7 считаются нестабильными. При этом важно заметить, что функциональность некоторых модулей будет меняться, вследствие чего могут меняться и директивы, поэтому обратной совместимости в nginx до версии 1.0.0 не гарантируется.

Чем же nginx так хорош и почему его так любят администраторы высоконагруженных проектов? Почему бы просто не использовать Apache?

Почему Apache - плохо?

Для начала нужно объяснить, как вообще работают сетевые серверы. Те, кто знаком с сетевым программированием, знают, что по сути существуют три модели работы сервера:

  1. Последовательная. Сервер открывает слушающий сокет и ждет, когда появится соединение (во время ожидания он находится в заблокированном состоянии). Когда приходит соединение, сервер обрабатывает его в том же контексте, закрывает соединение и снова ждет соединения. Очевидно, это далеко не самый лучший способ, особенно когда работа с клиентом ведется достаточно долго и подключений много. Кроме того, у последовательной модели есть еще много недостатков (например, невозможность использования нескольких процессоров), и в реальных условиях она практически не используется.
  2. Многопроцессная (многопоточная). Сервер открывает слушающий сокет. Когда приходит соединение, он принимает его, после чего создает (или берет из пула заранее созданных) новый процесс или поток, который может сколь угодно долго работать с соединением, а по окончании работы завершиться или вернуться в пул. Главный поток тем временем готов принять новое соединение. Это наиболее популярная модель, потому что она относительно просто реализуется, позволяет выполнять сложные и долгие вычисления для каждого клиента и использовать все доступные процессоры. Пример ее использования - Web-сервер Apache. Однако у этого подхода есть и недостатки: при большом количестве одновременных подключений создается очень много потоков (или, что еще хуже, процессов), и операционная система тратит много ресурсов на переключения контекста. Особенно плохо, когда клиенты очень медленно принимают контент. Получаются сотни потоков или процессов, занятых только отправкой данных медленным клиентам, что создает дополнительную нагрузку на планировщик ОС, увеличивает число прерываний и потребляет достаточно много памяти.
  3. Неблокируемые сокеты/конечный автомат. Сервер работает в рамках одного потока, но использует неблокируемые сокеты и механизм поллинга. Т.е. сервер на каждой итерации бесконечного цикла выбирает из всех сокетов тот, что готов для приема/отправки данных с помощью вызова select(). После того, как сокет выбран, сервер отправляет на него данные или читает их, но не ждет подтверждения, а переходит в начальное состояние и ждет события на другом сокете или же обрабатывает следующий, в котором событие произошло во время обработки предыдущего. Данная модель очень эффективно использует процессор и память, но достаточно сложна в реализации. Кроме того, в рамках этой модели обработка события на сокете должна происходить очень быстро - иначе в очереди будет скапливаться много событий, и в конце концов она переполнится. Именно по такой модели работает nginx. Кроме того, он позволяет запускать несколько рабочих процессов (так называемых workers), т.е. может использовать несколько процессоров.

Итак, представим следующую ситуацию: на HTTP-сервер с каналом в 1 Гбит/с подключается 200 клиентов с каналом по 256 Кбит/с:

Что происходит в случае Apache? Создается 200 потоков/процессов, которые относительно быстро генерируют контент (это могут быть как динамические страницы, так и статические файлы, читаемые с диска), но медленно отдают его клиентам. Операционная система вынуждена справляться с кучей потоков и блокировок ввода/вывода.

Nginx в такой ситуации затрачивает на каждый коннект на порядок меньше ресурсов ОС и памяти. Однако тут выявляется ограничение сетевой модели nginx: он не может генерировать динамический контент внутри себя, т.к. это приведет к блокировкам внутри nginx. Естественно, решение есть: nginx умеет проксировать такие запросы (на генерирование контента) на любой другой веб-сервер (например, все тот же Apache) или на FastCGI-сервер.

Рассмотрим механизм работы связки nginx в качестве «главного» сервера и Apache в качестве сервера для генерации динамического контента:

Nginx принимает соединение от клиента и читает от него весь запрос. Тут следует отметить, что пока nginx не прочитал весь запрос, он не отдает его на «обработку». Из-за этого обычно «ломаются» практически все индикаторы прогресса закачки файлов - впрочем, существует возможность починить их с помощью стороннего модуля upload_progress (это потребует модификации приложения).

После того, как nginx прочитал весь ответ, он открывает соединение к Apache. Последний выполняет свою работу (генерирует динамический контент), после чего отдает свой ответ nginx, который его буферизует в памяти или временном файле. Тем временем, Apache освобождает ресурсы. Далее nginx медленно отдает контент клиенту, тратя при этом на порядки меньше ресурсов, чем Apache.

Такая схема называется фронтэнд + бэкенд (frontend + backend) и применяется очень часто.

Установка

Т.к. nginx только начинает завоевывать популярность, имеются некоторые проблемы с бинарными пакетами, так что будьте готовы к тому, что его придется компилировать самостоятельно. С этим обычно не возникает проблем, надо лишь внимательно прочитать вывод команды./configure —help и выбрать необходимые вам опции компиляции, например такие:

./configure \
—prefix=/opt/nginx-0.6.x \ # префикс установки
—conf-path=/etc/nginx/nginx.conf \ # расположение конфигурационного файла
—pid-path=/var/run/nginx.pid \ # … и pid-файла
—user=nginx \ # имя пользователя под которым будет запускаться nginx
—with-http_ssl_module —with-http_gzip_static_module —with-http_stub_status_module \ # список нужных
—without-http_ssi_module —without-http_userid_module —without-http_autoindex_module —without-http_geo_module —without-http_referer_module —without-http_memcached_module —without-http_limit_zone_module # … и не нужных модулей

После конфигурирования стоит запустить стандартный make && make install, после чего можно пользоваться nginx.

Кроме того в Gentoo вы можете воспользоваться ebuild’ом из стандартного дерева портов; в RHEL/CentOS репозиторием epel (в нем расположени nginx 0.6.x) или srpm для версии 0.7, который можно скачать отсюда: http://blogs.mail.ru/community/nginx ; в Debian можно воспользоваться пакетом nginx из ветки unstable.

Конфигурационный файл

Конфигурационный файл nginx очень удобен и интуитивно понятен. Называется он обычно nginx.conf и распологается в $prefix/conf/ если расположение не было переопределено при компиляции. Я люблю класть его в /etc/nginx/, также делают и разработчики всех пакетов упомянутых выше.

Структура конфигурационного файла такова:

user nginx; # имя пользователя, с правами которого будет запускаться nginx
worker_processes 1; # количество рабочих процессов
events {
<…> # в этом блоке указывается механизм поллинга который будет использоваться (см. ниже) и максимальное количество возможных подключений
}

Http {
<глобальные директивы http-сервера, например настройки таймаутов и т.п.>;
<почти все из них можно переопределить для отдельного виртуального хоста или локейшена>;

# описание серверов (это то что в apache называется VirtualHost)
server {
# адрес и имя сервера
listen *:80;
server_name aaa.bbb;

<Директивы сервера. Здесь обычно указывают расположение докуменов (root), редиректы и переопределяют глобальные настройки>;

# а вот так можно определить location, для которого можно также переопределить практически все директивы указаные на более глобальных уровнях
location /abcd/ {
<директивы>;
}
# Кроме того, можно сделать location по регулярному выражению, например так:
location ~ \.php$ {
<директивы>;
}
}

# другой сервер
server {
listen *:80;
server_name ccc.bbb;

<директивы>
}
}

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

Итак, выше мы рассмотрели преимущества схемы frontend + backend, разобрались с установкой, структурой и синтаксисом конфигурационного файла, рассмотрим тепеть как реализовать обратное проксирование в nginx.

А очень просто! Например так:

location / {
proxy_pass http://1.2.3.4:8080;
}

В этом примере все запросы попадающие в location / будут проксироваться на сервер 1.2.3.4 порт 8080. Это может быть как apache, так и любой другой http-сервер.

Однако тут есть несколько тонкостей, связанных с тем, что приложение будет считать, что, во-первых, все запросы приходят к нему с одного IP-адреса (что может быть расценено, например, как попытка DDoS-атаки или подбора пароля), а во-вторых, считать, что оно запущено на хосте 1.2.3.4 и порту 8080 (соответственно, генерировать неправильные редиректы и абсолютные ссылки). Чтобы избежать этих проблем без необходимости переписывания приложения, мне кажется удобной следующая конфигурация:
Nginx слушает внешний интерфейс на порту 80.

Если бэкенд (допустим, Apache) расположен на том же хосте, что и nginx, то он «слушает» порт 80 на 127.0.0.1 или другом внутреннем IP-адресе.

Конфигурация nginx в таком случае выглядит следующим образом:

server {
listen 4.3.2.1:80;
# устанавливаем заголовок Host и X-Real-IP: к каждому запросу отправляемому на backend
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host:$proxy_port;
# или «proxy_set_header Host $host;», если приложение будет дописывать:80 ко всем ссылкам
}

Для того, чтобы приложение различало IP-адреса посетителей, нужно либо поставить модуль mod_extract_forwarded (если оно исполняется сервером Apache), либо модифицировать приложение так, чтобы оно брало информацию о IP-адресе пользователя из HTTP-заголовка X-Real-IP.

Другой вариант бэкенд - это использование FastCGI . В этом случае конфигурация nginx будет выглядеть примерно так:

server {
<…>

# location, в который будут попадать запросы на php-скрипты
location ~ .php$ {
fastcgi_pass 127.0.0.1:8888; # определяем адрес и порт fastcgi-сервера,
fastcgi_index index.php; # …индексный файл

# и некоторые параметры, которые нужно передать серверу fastcgi, чтобы он понял какой скрипт и с какими параметрами выполнять:
fastcgi_param SCRIPT_FILENAME /usr/www/html$fastcgi_script_name; # имя скрипта
fastcgi_param QUERY_STRING $query_string; # строка запроса
# и параметры запроса:
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
}

# благодяря тому что локейшены с регулярными выражениями обладают большим «приоритетом», сюда будут попадать все не-php запросы.

location / {
root /var/www/html/
}

Статика

Для того, чтобы меньше нагружать бэкенд, статические файлы лучше отдавать только через nginx - он, с этой задачей справляется лучше, т.к. на каждый запрос он тратит существенно меньше ресурсов (не надо порождать новый процесс, да процесс nginx’а как правило потребляет меньше памяти, а обслуживать может множество соединений).

В конфигурационном файле это выглядит примерно так:

server {
listen *:80;
server_name myserver.com;

Location / {
proxy_pass


«>http://127.0.0.1:80;

}

# предположим что все статичные файлы лежат в /files
location /files/ {
root /var/www/html/; # указываем путь на фс
expires 14d; # добавляем заголовок Expires:
error_page 404 = @back; # а если файл не найден, отправляем его в именованный локейшн @back
}

# запросы из /files, для которых не было найдено файла отправляем на backend, а он может либо сгенерировать нужный файл, либо показать красивое сообщение об ошибке
location @back {
proxy_pass
» title=»http://127.0.0.1:80;

«>http://127.0.0.1:80;

}

Если вся статика не помещена в какой-то определенный каталог, то воспользоваться регулярным выражением:

location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|wav|bmp|rtf|js)$ {
# аналогично тому что выше, только в этот location будут попадать все запросы оканчивающиеся на одно из указаных суффиксов
root /var/www/html/;
error_page 404 = @back;
}

К сожалению, в nginx не реализована асинхронная работа с файлами. Иными словами, nginx worker блокируется на операциях ввода-вывода. Так что если у вас очень много статических файлов и, в особенности, если они читаются с разных дисков, лучше увеличивать количество рабочих процессов (до числа, которое в 2-3 раза больше, чем суммарное число головок на диске). Это, конечно, ведет к увеличению нагрузки на ОС, но в целом производительность увеличивается. Для работы с типичным количеством статики (не очень большое количество сравнительно небольших файлов: CSS, JavaScript, изображения) вполне хватает одного-двух рабочих процессов.

To be continued

Ссылки

Тут можно найти дополнительноую информацию о nginx:

Один из самых популярных веб-серверов

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

Иерархия каталогов

Все конфигурационные файлы сервера располагаются в каталоге /etc/nginx. Кроме того, внутри директории расположены еще несколько папок, а также модульные конфигурационные файлы.

cd /etc/nginx
ls -F
conf.d/ koi-win naxsi.rules scgi_params uwsgi_params
fastcgi_params mime.types nginx.conf sites-available/ win-utf
koi-utf naxsi_core.rules proxy_params sites-enabled/

Если вы пользовались Apache, то должны быть знакомы с каталогами sites-enabled и sites-available. Они и определяют конфигурацию сайтов. Созданные файлы хранятся в последнем каталоге. Папка sites-enabled нужна для хранения конфигураций только активированных страниц. Чтобы их связать, нужна символическая ссылка между папками. Конфигурации можно также хранить в каталоге conf.d. При этом, во время запуска Nginx каждый файл с расширением.conf будет читаться по новой. При написании конфигурационных файлов, набирайте код без ошибок и соблюдайте синтаксис. Все остальные файлы располагаются в /etc/nginx. Конфигуратор содержит сведения о конкретных процессах, а также дополнительных компонентах.

Главный конфигурационный файл Nginx - это nginx.conf.

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

sudo nano /etc/nginx/nginx.conf

На экране появятся вот такие строки:

user www-data;
worker_processes 4;
pid /var/run/nginx.pid;
events {
worker_connections 768;
# multi_accept on;
}
http {
. . .

Первая - это общие сведения о Nginx. Фраза user www-data указывает на пользователя, который запускает сервер. Директива pid показывает, где располагаются PID-процессы, предназначенные для внутреннего использования. Строчка worker_processes показывает сколько процессов может одновременно запускать Nginx. Кроме того, здесь можно указать логи (например, лог ошибок определяется за счет директивы error_log). Ниже располагается раздел events. Он нужен для обработки соединений сервера. После него располагается блок http.

Структура конфигурационного файла Nginx

Понимание структуры форматирования файла поможет вам лучше разобраться с конфигурацией веб-сервера. Она делится на структурные блоки. Детали конфигурации блока http разделены на уровни посредством закрытых блоков. Они наследуют свойства из родительского, т.е. того, в котором располагаются. Данный блок хранит большую часть конфигураций сервера. Они делятся на блоки server, внутри которых расположены location.

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

gzip on;
gzip_disable "msie6";

Имейте ввиду, что один и тот же параметр может принимать разные значения в различных блоках. Сначала задайте его вверху, в потом переопределите параметр на нужном уровне. Если последнее действие не выполнить, программа задаст значения в автоматическом режиме.

Последними строками файла nginx.conf выступают:

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

Они свидетельствуют о том, что блоки location и server хранятся вне данного файла. Они определяют настройки url-адресов и конкретных файлов. Такая структура необходима для поддерживания модульной структуры конфигураций. Внутри нее получится создавать новые директории, файлы для различный сайтов. Кроме того, похожие файлы вы сможете сгруппировать. После рассмотрения вы можете закрывать файл nginx.conf.

Виртуальные блоки

Они являются аналогами виртуальных хостов в Apache. Блоки раздела server включают в себя характеристики отдельных сайтов, которые располагаются на сервере. В папке sites-available вы найдете файл блока server, который применяется по умолчанию. Внутри него можно найти вне нужные данные, которые могут потребоваться при обслуживании сайтов.

cd sites-available
sudo nano default
server {
root /usr/share/nginx/www;
index index.html index.htm;
server_name localhost;
location / {
try_files $uri $uri/ /index.html;
}
location /doc/ {
alias /usr/share/doc/;
autoindex on;
allow 127.0.0.1;
deny all;
}
}

В вышеуказанном примере было намеренно убрано комментирование. Это было сделано для удобства восприятия. Внутри блоки server располагаются настройки, заключенные в фигурные скобки:

Этот блок размещается с помощью директивы include в конце http, прописанном в файле nginx.conf. Посредством директивы root определяется каталог, где будет располагаться контент сайта. В нем программа и будет искать файлы, которые пользователь будет запрашивать. Путь такой по умолчанию: /usr/share/nginx/www. Nginx отделяет строчки или директивы одна от другой посредством точки с запятой. Если знак препинания не проставить, несколько строчек прочтуться как одна. Чтобы прописать правила, которые будут использоваться в качестве индекса, воспользуйтесь директивой index. Сервер проверит их в порядке перечисления. Если ни одна из имеющихся страничек не была запрошена пользователем, вернется index.html. Если его не будет, то сервер будет искать index.htm.

Правило server_name

Она включает в себя список доменных имен, которые должен будет обработать блок server. Их можно прописать любое количество, разделяя пробелами. Если поставить * в конце или начале домена, удастся задать имя с маской. Звездочка соответствует части имени. Если прописать *.com.ua, то сюда будут относиться все адреса указанной доменной зоны. Если адрес подходит под описание нескольких директив, то он ответит той, которой подходит полностью. При отсутствии совпадений ответ будет на самое длинное имя, у которого есть маска. В противном случае будет выполнено соответствие регулярным выражениям. Имена сервера, которые используют регулярные выражения, начинаются с тильды (~).

Location-блоки

Следующий на очереди у нас будет блок location. Он нужен для определения способа обработки определенных запросов. Если ресурсы не соответствуют никаким иным блокам location, то к ним будут применяться директивы, указанные в скобках. Эти блоки могут включать путь вроде /doc/. Для установления полного соответствия между uri и location, применяется знак =. Применяя тильду, получится задать соответствие регулярным выражениям. Вы также можете установить чувствительность к регистру, поставив ~. Если добавить звездочку, регистр не будет играть никакой роли.

Имейте ввиду: когда запрос будет полностью соответствовать блоку location, он будет использован, а поиск остановится. Когда совпадение неполное, URI будет сравниваться с параметрами директив location. Используется блок с сочетанием ^~, совпадающий с URI для выбора блока. Если данную опцию не задействовать, сервер выбирает оптимальное совпадение, а также произведет поиск с использованием регулярных выражений. Это необходимо для подбора одного из подходящих шаблонов. Если подходящее выражение будет найдено, оно будет использовано. В противном случае, применится предыдущее совпадение с URI. Однако имейте ввиду, что Nginx больше любит полные соответствия. Если их нет, начнется поиск регулярных выражений, а потом по URI. Паритетность поиска задается комбинацией символов ^~.

Правило try_files

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

try_files $uri $uri/ /index.html;

Что же она означает? Если поступает запрос, который обслуживается блоком location, сервер сначала попытается обработать uri как файл. Это обеспечивает переменная $uri. Когда соответствий ей не будет, uri будет обработан как каталог. Можно проверить его существование, задав слеш в конце: $uri/. Бывают ситуации, когда ни файл, ни каталог не будет найден. В таком случае загрузится файл по умолчанию - index.html. Правило try_files применяет последний параметр как запасной вариант. Именно поэтому данный файл должен быть в системе. Однако, если совпадений вообще не найдено, Nginx вернет страничку ошибки. Чтобы ее задать, пропишите = и код ошибки:

Дополнительные опции

Если применить правило alias, получится обслужить страницы блока location вне каталога root, например. Когда нужны файлы из doc, они будут запрошены из /usr/share/doc/. Кроме того, правило autoindеx on запускает листинг директорий сервера, для указанной директивы location. Если прописать строки deny и allow, получится изменить доступ к каталогам.

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

Выделенный Web-сервер на основе nginx – отличный способ повышения производительности Web-сайтов. В скорости обработки статического контента ему просто нет равных: он легко выдерживает несколько тысяч одновременных соединений и может быть легко оптимизирован и подогнан под любую конфигурацию. Однако? выступая в качестве фронт-энда для Apache, nginx оказывается наиболее уязвимым местом всей Web-инфраструктуры, поэтому безопасности nginx необходимо уделить особое внимание.

Эта статья – своего рода ликбез, или, если хочешь, резюме всех техник повышения безопасности nginx. В ней не будет теории, описания основ настройки Web-сервера и прочей воды. Вместо этого ты получишь исчерпывающий практический материал, описывающий все основные шаги, которые необходимо проделать для того, чтобы получить по-настоящему защищенный Web-сервер.

Установка

Пакет nginx доступен в прекомпилированном виде для любого дистрибутива. Однако собрав сервер самостоятельно, ты сможешь сделать его более компактным и надежным, а также получишь возможность изменить строку приветствия Web-сервера, чтобы отбить несмышленых скрипт-кидди.

Измени строку приветствия Web-сервера

Скачай исходники nginx, открой файл src/http/ngx_http_header_filter_module.c и найди следующие две строки:

static char ngx_http_server_string = "Server: nginx" CRLF;
static char ngx_http_server_full_string = "Server: " NGINX_VER CRLF;

Замени их на что-то вроде этого:

static char ngx_http_server_string = "Server: ][ Web Server" CRLF;
static char ngx_http_server_full_string = "Server: ][ Web Server" CRLF;

Удали все неиспользуемые тобой nginx-модули

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

Выполни сборку с помощью следующих команд:

# ./configure --without-http_autoindex_module --without-http_ssi_module
# make
# make install

Так ты получишь nginx с заранее отключенными (и в большинстве случаев бесполезными) модулями SSI (Server Side Includes) и Autoindex. Чтобы узнать, какие модули можно безболезненно выбросить из Web-сервера, запусти скрипт configure с флагом ‘-help’.

Препарируем nginx.conf

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

Отключи показ версии сервера на всех ошибочных страницах

Добавь в файл nginx.conf строку “server_tokens off”. Это заставит nginx скрывать информацию о типе и версии Web-сервера на страницах, генерируемых в ответ на ошибочный запрос клиента.

Настрой защиту от срыва стека

Добавь в секцию server следующие строки:

# vi /etc/nginx/nginx.conf

# Максимальный размер буфера для хранения тела запроса клиента
client_body_buffer_size 1K;
# Максимальный размер буфера для хранения заголовков запроса клиента
client_header_buffer_size 1k;
# Максимальный размер тела запроса клиента, прописанный в поле Content-Length заголовка. Если сервер должен поддерживать загрузку файлов, это значение необходимо увеличить
client_max_body_size 1k;
# Количество и размер буферов для чтения большого заголовка запроса клиента
large_client_header_buffers 2 1k;

Обрати внимание на директиву large_client_header_buffers. По умолчанию, для хранения строки URI nginx выделяет четыре буфера, размер каждого из которых равен размеру страницы памяти (для x86 это 4 Кб). Буферы освобождаются каждый раз, когда по окончанию обработки запроса соединение переходит в состояние keep-alive. Два буфера по 1 Кб могут хранить URI длиной только 2 Кб, что позволяет бороться с ботами и DoS-атаками.

Для повышения производительности добавь следующие строки:

# vi /etc/nginx/nginx.conf

# Таймаут при чтении тела запроса клиента
client_body_timeout 10;
# Таймаут при чтении заголовка запроса клиента
client_header_timeout 10;
# Таймаут, по истечению которого keep-alive соединение с клиентом не будет закрыто со стороны сервера
keepalive_timeout 5 5;
# Таймаут при передаче ответа клиенту
send_timeout 10;

Контролируй количество одновременных соединений

Для защиты Web-сервера от перегрузки и попыток осуществить DoS-атаку добавь в конфиг следующие строки:

# vi /etc/nginx/nginx.conf

# Описываем зону (slimits), в которой будут храниться состояния сессий. Зона размером 1 Мб может хранить около 32000 состояний, мы устанавливаем ее размер равным 5 Мб
limit_zone slimits $binary_remote_addr 5m;
# Задаем максимальное количество одновременных соединений для одной сессии. По сути, это число задает максимальное количество соединений с одного IP
limit_conn slimits 5;

Первая директива должна находиться в секции HTTP, вторая – в секции location. Когда количество соединений выйдет за пределы лимитов, клиент получит сообщение «Service unavailable» с кодом 503.

Разреши коннекты только к своему домену

Взломщики могут использовать ботов для сканирования подсетей и поиска уязвимых Web-серверов. Обычно боты просто перебирают диапазоны IP-адресов в поисках открытых 80 портов и посылают запрос HEAD для получения информации о веб-сервере (или главной странице). Ты можешь легко предотвратить такой скан, запретив обращение к серверу по IP-адресу (добавить в подсекцию location):

# vi /etc/nginx/nginx.conf

if ($host !~ ^(host.com|www.host.com)$) {
return 444;
}

Ограничь количество доступных методов обращения к Web-серверу

Некоторые боты используют различные методы обращения к серверу для попытки определения его типа и/или проникновения, однако в документе RFC 2616 четко сказано, что Web-сервер не обязан реализовывать их все, и неподдерживаемые методы могут просто не обрабатываться. Сегодня используемыми остаются только методы GET (запрос документа), HEAD (запрос заголовков сервера) и POST (запрос на публикацию документа), поэтому все остальные можно безболезненно отключить с помощью помещения следующих строк в секцию server конфигурационного файла:

# vi /etc/nginx/nginx.conf

if ($request_method !~ ^(GET|HEAD|POST)$) {
return 444;
}

Отшивай ботов

Другой способ блокирования ботов, сканеров и прочей нечисти основан на определении типа клиента (user-agent). Он не слишком эффективен, потому как большинство ботов косят под вполне легитимные браузеры, но в ряде случаев остается полезным:

# vi /etc/nginx/nginx.conf

# Блокируем менеджеры загрузки
if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
return 403;
}
# Блокируем некоторые типы ботов
if ($http_user_agent ~* msnbot|scrapbot) {
return 403;
}

Блокируй Referrer-спам

Если твой сайт публикует Web-логи в общедоступном виде, ты легко можешь стать жертвой Referrer-спама (когда спам-боты обращаются к твоему серверу, указывая в заголовке referrer – адрес рекламируемого сайта). Такой вид спама может легко испортить SEO-рейтинги интернет-страницы, поэтому его необходимо блокировать в обязательном порядке. Один из способов сделать это – занести наиболее частые слова, встречающиеся в адресах рекламируемых сайтов, в черный список.

# vi /etc/nginx/nginx.conf

# Секция server
if ($http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen))
{
return 403;
}

Блокируй хотлинк

Хотлинк – это включение в страницу изображения (или иного контента) с другого сайта. По сути, это воровство, потому как изображение, на которое ты потратил не один час своего свободного времени, не только свободно используется другими, но и создает нагрузку на твой Web-сервер, не приводя на него посетителей. Для борьбы с хотлинками достаточно сделать так, чтобы изображения отдавались клиенту только в том случае, если он запросил их, уже находясь на сайте (другими словами, заголовок referrer-запроса должен содержать имя твоего сайта). Добавь в секцию server конфигурационного файла nginx.conf следующие строки (host.com – это адрес твоего сайта):

# vi /etc/nginx/nginx.conf

location /images/ {
valid_referers none blocked www.host.com host.com;
if ($invalid_referer) {
return 403;
}
}

В качестве альтернативы ты можешь настроить сервер на отдачу специального баннера с сообщением о воровстве вместо запрашиваемого изображения. Для этого замени строку «return 403» на строку:

rewrite ^/images/uploads.*\.(gif|jpg|jpeg|png)$ http://www.host.com/banned.jpg last

Защищай важные каталоги от посторонних

Как и любой другой Web-сервер, nginx позволяет регулировать доступ к каталогам на основе IP-адресов и паролей. Эту возможность можно использовать для закрытия некоторых частей сайта от посторонних глаз. Например, для отрезания URI от внешнего мира:

# vi /etc/nginx/nginx.conf

location /uploads/ {
# Разрешаем доступ только машинам локальной сети
allow 192.168.1.0/24;
# Отшиваем всех остальных
deny all;
}

Теперь к документам каталога uploads будут иметь доступ только пользователи локальной сети. Для установки пароля придется проделать более сложные действия. Сначала необходимо создать приватный для nginx-файл паролей и добавить в него необходимых пользователей (в качестве примера добавим пользователя admin):

# mkdir /etc/nginx/.htpasswd
# htpasswd -c /etc/nginx/.htpasswd/passwd admin

# vi /etc/nginx/nginx.conf

location /admin/ {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd/passwd;
}

Новых пользователей можно добавить с помощью следующей команды:

# htpasswd -s /etc/nginx/.htpasswd/passwd пользователь

Используй SSL

Если твой сайт работает с приватными данными пользователей, такими как номера кредитных карт, пароли от других сервисов, или же предоставляет доступ к другой важной информации, которая может стать лакомым кусочком для третьих лиц, позаботься о шифровании. Nginx хорошо работает с SSL, и этой возможностью нельзя пренебрегать.

Для настройки SSL-шифрования средствами nginx достаточно выполнить несколько простых шагов. Сначала ты должен создать сертификат с помощью следующей последовательности команд:

# cd /etc/nginx
# openssl genrsa -des3 -out server.key 1024
# openssl req -new -key server.key -out server.csr
# cp server.key server.key.org
# openssl rsa -in server.key.org -out server.key
# openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Затем описать сертификат в конфигурационном файле nginx:

# vi /etc/nginx/nginx.conf

server {
server_name host.com;
listen 443;
ssl on;
ssl_certificate /etc/nginx/server.crt;
ssl_certificate_key /etc/nginx/server.key;
access_log /etc/nginx/logs/ssl.access.log;
error_log /etc/nginx/logs/ssl.error.log;
}

После этого можно перезагрузить Web-сервер:

# /etc/init.d/nginx reload

Естественно, без поддержки со стороны самого Web-сайта это делать бессмысленно.

Другие способы

Установи правильные значения системных переменных

Открой файл /etc/sysctl.conf и помести в него следующие строки:

# vi /etc/sysctl.conf

# Защита от smurf-атак
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Защита от неправильных ICMP-сообщений
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Защита от SYN-флуда
net.ipv4.tcp_syncookies = 1
# Запрещаем маршрутизацию от источника
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# Защита от спуфинга
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Мы не маршрутизатор
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# Включаем ExecShield
kernel.exec-shield = 1
kernel.randomize_va_space = 1
# Расширяем диапазон доступных портов
net.ipv4.ip_local_port_range = 2000 65000
# Увеличиваем максимальный размер TCP-буферов
net.ipv4.tcp_rmem = 4096 87380 8388608
net.ipv4.tcp_wmem = 4096 87380 8388608
net.core.rmem_max = 8388608
net.core.wmem_max = 8388608
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_window_scaling = 1

Размести корневой каталог Web-сервера на выделенном разделе

Поместив корневой каталог Web-сервера в выделенный раздел и запретив на нем размещение любых исполняемых файлов и файлов-устройств, ты обезопасишь остальную часть системы от тех, кто сможет получить доступ к корню Web-сервера. При этом запись в файле /etc/fstab должна иметь примерно такой вид:

/dev/sda5 /nginx ext4 defaults,nosuid,noexec,nodev 1 2

Помести nginx в chroot/jail-окружение

Любая современная *nix-система позволяет запереть приложение в изолированной среде исполнения. В Linux для этого можно использовать технологии KVM, Xen, OpenVZ и VServer, во FreeBSD – Jail, в Solaris – Zones. Если ни одна из этих технологий не доступна, ты можешь поместить nginx в классический chroot, который хоть и намного более хрупок, но большинство взломщиков остановить сможет.

Установи правила SELinux для защиты nginx

Хорошей альтернативой изолированным средам исполнения являются локальные системы обнаружения и предотвращения вторжений, такие как SELinux или AppArmor. Будучи правильно настроенными, они смогут предотвратить попытки взлома Web-сервера. По дефолту ни одна из них не настроена для работы в связке с nginx, однако в рамках проекта SELinuxNginx (http://sf.net/projects/selinuxnginx/) были созданы правила для SELinux, которые может использовать любой желающий. Остается только скачать и установить:

# tar -zxvf se-ngix_1_0_10.tar.gz
# cd se-ngix_1_0_10/nginx
# make
# /usr/sbin/semodule -i nginx.pp

Настрой брандмауэр

Обычно nginx устанавливают на выделенных машинах, готовых к высокой нагрузке, поэтому зачастую он остается единственным сетевым сервисом, работающим на сервере. Чтобы обезопасить сервер, достаточно создать совсем небольшой набор правил, которые будут открывать 80, 110 и 143-й порты (если, конечно, nginx должен работать еще и как IMAP/POP3-прокси) и закрывать от внешнего мира все остальное.

Ограничь количество соединений с помощью брандмауэра

Для не слишком нагруженного Web-сайта хорошей идеей будет ограничить количество попыток соединений с одного IP-адреса в минуту. Это сможет уберечь тебя от некоторых типов DoS-атак и брутфорса. В Linux это можно сделать с помощью стандартного iptables/netfilter-модуля state:

# iptables -A INPUT -p tcp --dport 80 -i eth0 \
-m state --state NEW -m recent --set
# iptables -A INPUT -p tcp --dport 80 -i eth0 \
-m state --state NEW -m recent --update \
--seconds 60 --hitcount 15 -j DROP

Правила урезают лимит на количество подключений с одного IP в минуту до 15. То же можно сделать и с помощью pf:

# vi /etc/pf.conf

webserver_ip="1.1.1.1"
table persist
block in quick from
pass in on $ext_if proto tcp to $webserver_ip \
port www flags S/SA keep state \
(max-src-conn 100, max-src-conn-rate 15/60, \
overload flush)

Кроме лимита на количество последовательных подключений (15 в минуту), данное правило устанавливает дополнительный лимит на количество одновременных подключений равный 100.

Настрой PHP

Если ты используешь nginx в связке с PHP, не забудь настроить и его. Вот как должен выглядеть конфигурационный файл /etc/php/php.ini защищенного сервера:

# vi /etc/php/php.ini

# Отключаем опасные функции
disable_functions = phpinfo, system, mail, exec
# Максимальное время исполнения скрипта
max_execution_time = 30
# Максимальное время, которое может потратить скрипт на обработку данных запроса
max_input_time = 60
# Максимальное количество памяти, выделяемое каждому скрипту
memory_limit = 8M
# Максимальный размер данных, отсылаемых скрипту с помощью метода POST
post_max_size = 8M
# Максимальный размер загружаемых файлов
upload_max_filesize = 2M
# Не показывать ошибки PHP-скриптов пользователям
display_errors = Off
# Включаем Safe Mode
safe_mode = On
# Включаем SQL Safe Mode
sql.safe_mode = On
# Позволяем выполнять внешние команды только в этом каталоге
safe_mode_exec_dir = /путь/к/защищенному/каталогу
# Защищаемся от утечки информации о PHP
expose_php = Off
# Ведем логи
log_errors = On
# Запрещаем открытие удаленных файлов
allow_url_fopen = Off

Выводы

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

О герое дня

Nginx – один самых производительных и популярных Web-серверов в мире. Согласно данным Netcraft, он используется для поддержки более чем 12 миллионов Web-сайтов по всему миру, включая таких мастодонтов как Rambler, Yandex, Begun, WordPress.com , Wrike, vkontakte.ru , megashara.com , Либрусек и Taba.ru. Грамотная архитектура, основанная на мультиплексировании соединений с помощью системных вызовов select, epoll (Linux), kqueue (FreeBSD) и механизме управления памятью на основе пулов (небольших буферов от 1 до 16 Кб), позволяет nginx не проседать даже под очень высокими нагрузками, выдерживая свыше 10000 одновременных соединений (так называемая проблема C10K). Изначально написан Игорем Сысоевым для компании Rambler и открыт в 2004 году под BSD-подобной лицензией.

Вконтакте

Лучшие статьи по теме