Настройка Nginx в качестве reverse прокси для Apache

Схема работа Nginx reverse proxyВеб сервер Apache на сегодня считается достаточно медленным и для оптимизации работы сервера и ускорения работы сайта рекомендуется от него полностью отказываться, но бывают ситуации когда без него не обойтись. В таком случае наиболее частым приемом становится установка веб сервера Nginx в качестве прокси сервера для Apache. Таким образом принимать запросы от пользователям у нас уже будет быстрый сервер Nginx и дальше уже решать: отправить запрос Apache или выдать клиенту все данные самому, если у него есть такая возможность, например данные на нем закэшированы.

Основные варианты использования:

Защита от DDOS: Nginx будет пропускать только реальные http запросы на медленный Apache, а остальные или отдавать из кэша или блокировать. При определенном варианте, при таком режиме можно даже защищаться от DDOS атак.

GZIP сжатие: Nginx может осуществлять GZIP сжатие данных перед отправкой клиенту и таким образом уменьшить скорость загрузки и нагрузку на сеть.

Балансировка: Nginx может выступать в качестве балансировщика нагрузки и распределять запросы по нескольким физическим серверам.

 

Пропустим процедуру установки и попробуем разобраться как же настроить оба сервера для их работы в паре. Рассмотрим простейший вариант когда Apache будет обрабатывать скрипты, а nginx просто транслировать их клиенту. По такому принципу у меня работает task менеджер redmine. Apache занимается только обработкой запросов от mod_passanger, а все остальные сайты на сервере напрямую отдает nginx.

Настройки Apache

Тут от настроек не так много, главное установить нужный порт и настроить видимость сервера только внутри себя. Порт 80 мы использовать больше не можем, так как им будет пользоваться nginx поэтому возьмем порт 81.

Редактируем файл /etc/httpd/httpd.conf

#ставим внутренний адрес и меняем порт на 81
Listen 127.0.0.1:81

#KeepAlive запросы позволяют устанавливать постоянные соединения между клиентом и сервером. Это экономит ресурсы на отсутствии повторной установки соединений.
KeepAlive Off

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

Создаем виртуальный хост для нашего сайта с минимальными настройками. Это может быть общий файл httpd-vhosts.conf или на каждый сайт свой файл.

# Указываем выбранный порт:
 <VirtualHost 127.0.0.1:81>
    ServerName site.ru
    ServerAlias www.site.ru
    DocumentRoot /home/www/html/site
    CustomLog /var/log/httpd/site.ru_access.log combined
    ErrorLog /var/log/httpd/site.ru_error.log
<Directory "/home/www/htmlsite">
    AllowOverride none
</Directory>
</VirtualHost>

Директива AllowOverride включает использование файла .htaccess. В этом случае при каждом запросе Apache будет обращаться к директории сайта для его поиска. Лучше переместить все настройки в конфигурационный файл немного ускорив обработку.

Настройка Nginx

Настроим основной конфигурационный файл /etc/nginx/nginx.conf

user nginx;
worker_processes auto; #можно указать количество ядер процессора
worker_rlimit_nofile 8192; 
worker_priority -1; #чтобы не вешало сервер при большой нагрузке

# Общий лог для ошибок
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 8096; # Максимальное количество рабочих соединений
    use epoll; # Метод обработки соединений. for Linux 2.6+
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    #Связка из 3х параметров для ускорения отдачи ответов с сервера
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;

    #Keepalive соединения позволяют избежать необходимости повторного создания соединения между клиентом и сервером
    # Будет ждать 30 секунд перед закрытием keepalive соединения
    keepalive_timeout   30;
    types_hash_max_size 2048;
    # Максимальное количество keepalive запросов от одного клиента
    keepalive_requests 50;
    #Много проблем могут создать медленные (тупящие) клиенты. Медленная передача тела запроса от клиента к серверу и неожиданное закрытие клиентом соединений могут создать большое количество лишних соединений на сервере.
    reset_timedout_connection on;
    # Если клиент перестал читать отвечать, Nginx будет сбрасывать соединение с ним
    client_body_timeout 10;
    # Будет ждать 10 секунд тело запроса от клиента, после чего сбросит соединение
    send_timeout 10;
    # Если клиент прекратит чтение ответа, Nginx подождет 2 секунды и сбросит соединение

    #Ограничивайте отправку больших запросов на сервер (например, загрузку больших файлов), если это не предусмотрено сайтом
    client_max_body_size  10m;

    # Не отдавать версию nginx в заголовке ответа
    server_tokens off;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;
    
}

Вот тут уже KeepAlive запросы необходимо включить.

Если мы хотим использовать кэширование, то в этот файл необходимо добавить ещё его настройку:

 # Cache
    ## Создаем кеш зону getcache (память под ключи в 50Мб) с настройками:
    # inactive: xранить кеш 10 минут
    # max_size: максимальный размер кеш данные 200Мб
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=getcache:50m inactive=10m max_size=200m;
    proxy_temp_path /var/cache/nginx/temp;

    # Ключ по которому сохраняются и берутся данные из кеша
    proxy_cache_key "$request_method|$is_args|$host|$request_uri";
    #proxy_cache_key "$scheme$proxy_host$uri$is_args$args";

    # Защита от раздачи одинаковой куки в кешированном ответе
    proxy_hide_header "Set-Cookie";
    # Игнорировать параметры кеша заданные бекэндом
    proxy_ignore_headers "Cache-Control" "Expires";

    # Указывает в каких случаях клиенту можно отдать несвежий ответ из кеша
    proxy_cache_use_stale error timeout invalid_header http_500 http_502 http_503 http_504 http_403;
    proxy_cache_valid any 1d;

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

 limit_req_zone $binary_remote_addr zone=one:10m rate=10r/m;

Обычно эту настройку применяют для отработки DDOS атак. Тут мы выделяем 10Мб в памяти для обработки зоны one и настраиваем её на ограничение в 10 запросов в минуту. Все, что больше будет отвергнуто сервером с ответом 503(или заданным настройками). Для разных сайтов лучше создавать разные зоны.

Далее настроим зону самого сайта

Для этого создадим файл /etc/nginx/conf.d/site.ru.conf

server {
listen 80;
server_name site.ru www.site.ru;

# Ведём журнал доступа:
access_log /var/log/nginx/site.ru_access.log;
#access_log off;
error_log /var/log/nginx/site.ru_error.log;

# Разделяем статику и динамку, статику храним в кэше 7 дней:
location ~* \.(jpg|jpeg|gif|png|ico|css|bmp|swf|js|doc|docx|pdf|xls|xlsx|rar|zip|tbz|7z|exe|woff|woff2|ttf|svg|eot|txt|htm|html)$ {
root /home/www/html/site.ru/;
expires 7d;
access_log off;
#не писать в лог если файл не найден
# log_not_found off;
include conf.d/gzip.inc; #подключаем gzip сжатие
}

# .htaccess и .htpasswd и .git не отдаем:
location ~ /\.(ht|git) {
deny all;
}

location / {
proxy_pass http://127.0.0.1:81/;
include conf.d/proxypass.inc;

#включаем кэширование запросов
#proxy_cache sitecache;
#proxy_cache_valid 200 301 302 304 10m;
}

#auth_basic "Restricted Access";
#auth_basic_user_file /var/www/all.htpasswd;
}

# только для главной, если ddos
#location = / {
#   limit_req zone=one burst=2 nodelay;
#    limit_req_status 444;
#}

#убираем www
if ($host ~* www\.(.*)) {
set $host_without_www $1;
rewrite ^(.*)$ http://$host_without_www$1 permanent;
}
}

Выдача кода 444 при DDOS атаке максимально разгружает сервер на каждом запросе. Это самый «легкий» ответ который сервер может отдать клиенту.

Определим подключаемые файлы:

conf.d/gzip.inc

gzip on;
# Минимальная длина ответа, при которой модуль будет жать, в байтах
gzip_min_length  1100;
# Разрешить сжатие для всех проксированных запросов
gzip_proxied     any;
# Запрещает сжатие ответа методом gzip для IE6
gzip_disable     "msie6";
# Уровень gzip-компрессии
gzip_comp_level  3;

gzip_vary on;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript

Файл conf.d/proxy.inc

proxy_buffering off;
proxy_connect_timeout 59s;
proxy_send_timeout 120;
proxy_read_timeout 180;

proxy_buffer_size 64k;
proxy_buffers 16 32k;
proxy_busy_buffers_size 64k;

proxy_temp_file_write_size 64k;
proxy_pass_header Set-Cookie; #важный параметр если мы хотим передавать Cookie
proxy_redirect off;
proxy_hide_header Vary;
proxy_hide_header X-Powered-By;
proxy_set_header Accept-Encoding '';

#If you want to get the cache-control and expire headers from apache, comment out 'proxy_ignore_headers' and uncomment 'proxy_pass_header Expires;' and 'proxy_pass_header Cache-Control
#proxy_pass_header Expires;
#proxy_pass_header Cache-Control;
proxy_ignore_headers Cache-Control Expires;

proxy_set_header Referer $http_referer;
proxy_set_header Host $host;
proxy_set_header Cookie $http_cookie;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Так как запросы от клиента у нас принимает nginx, то только он знает его настоящий ip. На Apache при этом приходит уже ip nginx, то есть 127.0.0.1. Для многих скриптов это критично важно и для «проброски» адреса существует специальный модуль.

До Apache версии 2.4.6 использовался mod_rpaf

https://centos.pkgs.org/7/nux-misc-x86_64/mod_rpaf-0.8.4-1.el7.nux.x86_64.rpm.html

После этой версии надо использовать mod_remoteip.

LoadModule remoteip_module /usr/lib/apache2/modules/mod_remoteip.so
<IfModule remoteip_module>
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 127.0.0.1
</IfModule>

После проведенных настроек перезагружаем оба сервера и проверяем работу

service httpd restart && service nginx restart
Запись опубликована в рубрике Администрирование с метками , , , . Добавьте в закладки постоянную ссылку.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *