Введение
Немного расскажу своими словами о том, как работает модуль ngx_http_proxy_module. Именно он реализует весь функционал, о котором пойдет речь. Допустим, у вас в локальной или виртуальной сети есть какие-то сервисы, не имеющие прямого доступа из интернета. А вы хотите таковой иметь. Можно пробрасывать нужные порты на шлюзе, можно что-то еще придумывать. А можно сделать проще всего — настроить единую точку входа на все свои сервисы в виде nginx сервера и с него проксировать различные запросы к нужным серверам.
Расскажу на конкретных примерах, где я это использую. Для наглядности и простоты буду прям по порядку перечислять эти варианты:
- Ранее я рассказывал о настройке чат серверов — matrix и mattermost. В этих статьях я как раз рассказывал о том, как проксировать запросы в чат с помощью nginx. Прошелся по теме вскользь, не останавливаясь подробно. Суть в том, что вы настраиваете на любом виртуальном сервере эти чаты, помещаете их в закрытые периметры сети без лишних доступов и просто проксируете запросы на эти сервера. Они идут через nginx, который у вас смотрит во внешний интернет и принимает все входящие соединения.
- Допустим, у вас есть большой сервер с множеством контейнеров, например докера. На нем работает множество различных сервисов. Вы устанавливаете еще один контейнер с чистым nginx, на нем настраиваете проксирование запросов на эти контейнеры. Сами контейнеры мапите только к локальному интерфейсу сервера. Таким образом, они будут полностью закрыты извне, и при этом вы можете гибко управлять доступом.
- Еще один популярный пример. Допустим, у вас есть сервер с гипервизором proxmox или любым другим. Вы настраиваете на одной из виртуальных машин шлюз, создаете локальную сеть только из виртуальных машин без доступа в нее извне. Делаете в этой локальной сети для всех виртуальных машин шлюз по-умолчанию в виде вашей виртуальной машины со шлюзом. На виртуальных серверах в локальной сети размещаете различные сервисы и не заморачиваетесь с настройками фаервола на них. Вся их сеть все равно не доступна из интернета. А доступ к сервисам проксируете с помощью nginx, установленным на шлюз или на отдельной виртуальной машине с проброшенными на нее портами.
- Мой личный пример. У меня дома есть сервер synology. Я хочу организовать к нему простой доступ по https из браузера по доменному имени. Нет ничего проще. Настраиваю на сервере nginx получение бесплатного сертификата , настраиваю проксирование запросов на мой домашний ip, там на шлюзе делаю проброс внутрь локалки на synology сервер. При этом я могу фаерволом ограничить доступ к серверу только одним ip, на котором работает nginx. В итоге на самом synology вообще ничего не надо делать. Он и знать не знает, что к нему заходят по https, по стандартному порту 443.
- Допустим, у вас большой проект, разбитый на составные части, которые живут на разных серверах. К примеру, на отдельном сервере живет форум, по пути /forum от основного домена. Вы просто берете и настраиваете проксирование всех запросов по адресу /forum на отдельный сервер. Точно так же можно без проблем все картинки перенести на другой сервер и проксировать к ним запросы. То есть вы можете создать любой location и переадресовывать запросы к нему на другие сервера.
Надеюсь в общем и целом понятно, о чем идет речь. Вариантов использования много. Я привел самые распространенные, которые пришли в голову и которые использую сам. Из плюсов, которые считаю наиболее полезными именно из своих кейсов, отмечу 2:
- Без проблем можете настроить https доступ к сервисам, при этом совершенно не трогая эти сервисы. Вы получаете и используете сертификаты на nginx сервере, используете https соединение с ним, а сам nginx уже передает информацию на сервера со службами, которые могут работать по обычному http и знать не знают о https.
- Вы очень легко можете менять адреса, куда проксируете запросы. Допустим у вас есть сайт, его запросы проксируются на отдельный сервер. Вы подготовили обновление или переезд сайта. Отладили все на новом сервере. Теперь вам достаточно на сервере nginx изменить адрес старого сервера на новый, куда будут перенаправляться запросы. И все. Если что-то пойдет не так, можете оперативно вернуть все обратно.
С теорией закончил. Перейдем теперь к примерам настройки. В своих примерах я буду использовать следующие обозначения:
blog.zeroxzed.ru | доменное имя тестового сайта |
nginx_srv | имя внешнего сервера с установленным nginx |
blog_srv | локальный сервер с сайтом, куда проксируем соединения |
94.142.141.246 | внешний ip nginx_srv |
192.168.13.31 | ip адрес blog_srv |
77.37.224.139 | ip адрес клиента, с которого я буду заходить на сайт |
Конфигурации виртуальных хостов
Стандартный виртуальный хост находится в файле default в каталоге sites-available.
Чтобы ознакомиться с общим форматом виртуального хоста, откройте этот файл:
По умолчанию виртуальный хост обрабатывает запросы на порте 80.
Это не означает, что веб-сервер обязательно будет обрабатывать каждый запрос через этот порт. Apache может переопределять конфигурации.
Настройки виртуального хоста высшего уровня
Эти параметры устанавливаются в разделе Virtual Host и применяются ко всему виртуальному хосту.
Директива ServerName задаёт доменное имя или IP-адрес сервера. Это индивидуальный параметр каждого виртуального хоста, который может переопределить настройки по умолчанию, если он совпадает со значением ServerName.
Параметр ServerAlias позволяет добавить алиасы сайта – альтернативные имена и пути, ведущие к одному контенту. Так, например, часто устанавливается алиас домена с www.
DocumentRoot задаёт каталог, в котором веб-сервер хранит контент данного виртуального хоста. В Ubuntu для этого по умолчанию используется /var/www.
В конфигурации виртуального хоста есть специальный раздел для настройки обработки отдельных каталогов файловой системы. Эти настройки также можно переопределять.
Сначала виртуальный хост предлагает набор правил для каталога / (root-каталог). Этот раздел обеспечит базовую конфигурацию виртуального хоста, поскольку он относится ко всем файлам, которые обслуживаются в файловой системе.
По умолчанию Ubuntu не накладывает никаких ограничений на файловую систему. Apache рекомендует добавить несколько стандартных ограничений доступа, например:
Это заблокирует доступ ко всему контенту, если в последующих определениях каталогов не указано иное.
Далее идут настройки каталога document root, в которых параметр allow from all переопределяет параметры каталога /.
Параметр AllowOverride позволяет настроить переопределение конфигураций с помощью файлов .htaccess. Чтобы переопределить настройки, файл .htaccess должен находиться в каталоге с контентом. По умолчанию эта функция отключена.
Настройки Alias и ScriptAlias
Иногда перед разделом Directory идут параметры Alias и ScriptAlias.
Директива Alias позволяет добавлять к обслуживаемому контенту каталоги вне DocumentRoot.
ScriptAlias работает аналогичным образом, но содержит путь к каталогам с исполняемыми файлами.
К примеру, такая строка в виртуальном хосте для сайта example.com откроет доступ к контенту в каталоге /path/to/content/ при запросе example.com/content/.
Помните, что открывая доступ к дополнительным каталогам, нужно устанавливать ограниченные привилегии на них.
Включение сайтов и модулей в Apache
Создав файл виртуального хоста, вы можете включить его. Для этого нужно создать символическую ссылку на файл в каталоге sites-enabled:
Включив сайт, перезапустите Apache, чтобы веб-сервер перечитал конфигурации:
Чтобы отключить виртуальный хост, нужно удалить символьную ссылку из sites-enabled:
После этого нужно снова перезапустить веб-сервер:
Включить и отключить модуль Apache можно с помощью следующих команд (соответственно):
Они работают так же, как и ранее упомянутые команды a2ensite иa2dissite. После включения или отключения модуля нужно перезапускать веб-сервер.
Глобальные настройки Apache
Данный раздел рассматривает важные параметры глобальных настроек Apache.
Timeout
По умолчанию этот параметр имеет значение 300. Это значит, что на выполнение каждого запроса у сервера есть максимум 300 секунд. В большинстве случаев это значение очень большое, и его рекомендуют уменьшить до 30-60 секунд.
KeepAlive
Если этот параметр имеет значение On, сервер позволит клиенту запрашивать несколько объектов в рамках одного соединения. Если параметр имеет значение Off, то каждый новый запрос будет создавать индивидуальное соединение. Такое поведение может привести к перенагрузке сайта с большим трафиком.
MaxKeepAliveRequests
Этот параметр позволяет определить максимальное количество запросов для одного соединения. Это позволяет увеличить производительность Apache.
Значение 0 позволит веб-серверу обрабатывать неограниченное количество запросов в рамках одного соединения.
KeepAliveTimeout
Данный параметр устанавливает промежуток времени между запросами. Если в течение указанного времени клиент не создал следующий запрос. Веб-сервер прервёт соединение. Если в дальнейшем этот клиент отправит запрос, сервер создаст новое соединение.
Шаг 10 — Блокировка прямого доступа к Apache (опционально)
Поскольку Apache прослушивает порт на публичном IP-адресе, он доступен кому угодно. Его можно заблокировать с помощью следующей команды IPtables в наборе правил брандмауэра.
Обязательно используйте IP-адрес своего сервера вместо выделенного красным адреса в примере. Когда ваш брандмауэр заблокирует порт , убедитесь в недоступности Apache через этот порт. Для этого откройте браузер и попробуйте получить доступ к любому из доменных имен Apache через порт . Например: http://example.com:8080
Браузер должен вывести сообщение об ошибке Unable to connect (Не удается подключиться) или Webpage is not available (Страница недоступна). Если используется опция IPtables , сторонний наблюдатель не увидит разницы между портом и портом, где отсутствует какое-либо обслуживание.
Примечание. По умолчанию правила IPtables теряют силу после перезагрузки системы. Существует несколько способов сохранения правил IPtables, но проще всего использовать параметр в хранилище Ubuntu. Прочитайте эту статью, чтобы узнать больше о настройке IPTables.
Теперь настроим Nginx для обслуживания статических файлов для сайтов Apache.
2. Настройка Nginx
Первым делом следует рассмотреть структуру конфигурационного файла. На первый взгляд, тут все может показаться очень запутанным, но там все достаточно логично:
Сначала идут глобальные опции, которые задают основные параметры программы, например, от какого пользователя она будет запущена и количество процессов. Дальше есть секция 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:
NGINX vs Apache
Веб-сервер Nginx по сравнению с Apache работает быстрее при отдаче статики и потребляет меньше серверных ресурсов. Его использует вместо или совместно с Apache для ускорения обработки запросов и уменьшения нагрузки. Это обуславливается тем, что большая часть тех возможностей, которые предлагает Apache, большинству обычных пользователей не нужно.
Поскольку широкий функционал Nginx требует и значительно больших ресурсов системы, постоянно применять полноценную связку «Nginx + Apache» нецелесообразно. Чаще оба веб-сервера используются в симбиозе — Nginx отдает статику и перенаправляет обработку скриптов Apache.
Сильные и слабые стороны
- Оба серверы хорошо работают на системах типа Unix, но производительность Nginx на Windows заметно ниже.
- При одновременной работе Nginx оказывается в два раза быстрее Apache и использует меньше памяти. С динамическим контентом скорость равна.
- Для получения пользовательской поддержки можно обратиться на форум или почту компании, но у Apache Foundation есть с этим проблемы.
- Apache хорошо справляется с хостингом нескольких сайтов сразу, но Nginx показывает лучшую «гибкость» и эффективность работы с динамическим контентом.
Создание собственных правил mod_security
В данном разделе речь пойдет о создании цепочек правил.
Для начала создайте правило, блокирующее HTML-запросы с различными спам-словами. Для этого нужно создать PHP-скрипт, отображающий введенные в текстовом поле данные.
Пользовательские правила можно добавить в любой конфигурационный файл модуля или разместить в каталогах mod_security. Создайте новый файл для правил.
Добавьте в этот файл следующий код:
Сохраните файл и перезапустите Apache.
Откройте http://yourwebsite.com/form.php в браузере и введите любое из этих слов: pills, insurance, rolex.
Появится либо страница ошибки 403 и запись лога, либо только запись лога (это зависит от настройки SecRuleEngine).
Синтаксис SecRule имеет такой вид:
В данном случае используется действие (т.е., ) chain для поиска совпадений в переменных REQUEST_FILENAME и form.php, REQUEST_METHOD и POST, REQUEST_BODY со строкой «@rx (?i:(pills|insurance|rolex))». Комбинация символов ?i: используется для регистронезависимого поиска. В случае совпадения будут выполнены действия deny и log, а на экране появится сообщение «Spam detected». Действие chain означает «И», то есть, одновременное совпадение трех перечисленных правил.
Другие способы
Установи
правильные значения системных переменных
Размести
корневой каталог Web-сервера на выделенном разделе
Помести
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, которые может использовать любой
желающий. Остается только скачать и установить:
Настрой
брандмауэр
Обычно
nginx устанавливают на выделенных машинах, готовых к высокой нагрузке,
поэтому зачастую он остается единственным сетевым сервисом, работающим на
сервере. Чтобы обезопасить сервер, достаточно создать совсем небольшой
набор правил, которые будут открывать 80, 110 и 143-й порты (если,
конечно, nginx должен работать еще и как IMAP/POP3-прокси) и закрывать от
внешнего мира все остальное.
Ограничь
количество соединений с помощью брандмауэра
Для
не слишком нагруженного Web-сайта хорошей идеей будет ограничить
количество попыток соединений с одного IP-адреса в минуту. Это сможет
уберечь тебя от некоторых типов DoS-атак и брутфорса. В Linux это можно
сделать с помощью стандартного iptables/netfilter-модуля state:
Правила
урезают лимит на количество подключений с одного IP в минуту до 15. То же
можно сделать и с помощью pf:
Кроме
лимита на количество последовательных подключений (15 в минуту), данное
правило устанавливает дополнительный лимит на количество одновременных
подключений равный 100.
Настрой
PHP
Если
ты используешь nginx в связке с PHP, не забудь настроить и его. Вот как
должен выглядеть конфигурационный файл /etc/php/php.ini защищенного
сервера:
Анализ
и оптимизация времени TTFB
Общая конфигурация и поддержка сети сайтов #Общая конфигурация и поддержка сети сайтов
Для работы WordPress на nginx вам потребуется настроить обработчик PHP (backend), это может быть php-fpm, php-cgi или fastcgi. Оптимальным и простым в установке вариантом является использование php-fpm, который поддерживается начиная с PHP 5.3
Основной файл конфигурации
Обычно это /etc/nginx/nginx.conf , но может и располагаться и в другом месте в зависимости от вашего дистрибутива операционной системы и источника пакетов nginx.
Ниже будут перечислены только те директивы, значение которых может непосредственно влиять на работу WordPress. Ваш дистрибутив должен предоставлять файл конфигурации обеспечивающий базовую работу nginx, вам следует только перепроверить его на директивы, перечисленные ниже. Строки в конфигурации начинающиеся с # являются комментариями.
Настройка PHP обработчика может быть произведена так (как в глобальном контексте http {} так и для каждого сайта в контекстах server {} , настройки должны соответствовать тем, что указаны в настройках директивы listen пула (pool) для php-fpm
Во многих дистрибутивах конфигурации для отдельных сайтов (контекст ) вынесены в папку sites-available, на которые создаются символические ссылки в папке sites-enabled. Конфигурации включенных сайтов загружаются в конце nginx.conf директивой
Некоторые полезные директивы для конфигурации сайта
server { # Это адрес сайта server_name example.com; # Путь к папке с файлами сайта (корню) root /var/www/example.com; # Файл индекса сайта. index index.php; # А вот показ индекса файлов в папках без файла-индекса отключим autoindex off; # Журнал доступа может быть записан в отдельный файл с отложенной записью access_log /var/log/jinx/www-example.com.log main buffer=2k flush=30s; # А для некоторых файлов журнал доступа можно и вовсе отключить location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { allow all; log_not_found off; access_log off; } # Закроем доступ к скрытым файлам (начинаются с точки) location ~ /\. { deny all; } # Вот так можно закрыть доступ к папке кеша (плагинов) location ~ ^/wp-content/cache { deny all; } # Запрет выполнения PHP в папках для загруженных файлов location ~* /(?:uploads|files)/.*\.php$ { deny all; } # А директивы ниже показывают как можно установить заголовки кеширования для статических ресурсов (а также изменить сжатие gzip для некоторых из них) location ~* ^.+\.(jpg|jpeg|png|ico|gif|swf|webp|srv)$ { expires 3w; gzip off; } location ~* ^.+\.(css|js)$ { expires 7d; add_header Vary Accept-Encoding; } location ~* ^.+\.(eot|ttf|woff|woff2)$ { expires 92d; add_header Vary Accept-Encoding; } # Не забываем добавить обработчик для PHP location ~ \.php$ { include fastcgi.conf; fastcgi_intercept_errors on; fastcgi_param SCRIPT_FILENAME $root$fastcgi_script_name; # Должен соответствовать имени, определенному в примере директивы upsteam выше. fastcgi_pass php; } # Ну и наконец, правила для "красивых постоянных ссылок" location / { try_files $uri $uri/ /index.php?$args; } # поближе к закрытию контекста server }
Обязательно убедитесь в том, что в php.ini установлено значение константы
это предотвратит исполнение иных (без расширения .php) файлов, возможно содержащих PHP код, возможным злоумышленником.
Много других рецептов и хитростей по конфигурированию nginx можно посмотреть например здесь: https://www.nginx.com/resources/wiki/start/topics/recipes/wordpress/
Конфигурация для сети сайтов
С тех пор, как установка сети сайтов стала частью WordPress (а не отдельным пакетом WPMU), дополнительные правила для nginx не требуются, вам следует лишь иметь идентичные блоки server{} для всех сайтов вашей сети, вы можете создать отдельный файл и включать его в конфигурации сайтов директивой e. Переопределяя лишь и если вам нужно — .
Если же ваша сеть сайтов имеет общий домен, то вы можете разместить её на одном виртуальном сервере, с одним блоком конфигурации .
Директива будет работать с любым доменом третьего уровня в домене example.com.
Внимание: вы можете оставить комментарий обратной связи к этой статье. Если данная статья показалась вам неполной или вы нашли неточности, оставьте нам сообщение используя форму ниже
Если данная статья показалась вам неполной или вы нашли неточности, оставьте нам сообщение используя форму ниже.
Также вы можете поучаствовать в составлении и дополнении документации на русском языке.Подробнее тут.