Разберём, что такое Reverse Proxy. А также я покажу как настроить Nginx в качестве Reverse Proxy (обратного прокси сервера).

Теоретическая часть

Иногда бывает нужно чтобы различные url запросы обрабатывались на разных серверах, но первоначально приходили на один сервер. Например вы пробросили порт на своем роутере на один веб-сервер в вашей внутренней сети. Но хотите чтобы каталог /xxx открывался на втором веб-сервере, а /yyy открывался на третьем, и не хотите пробрасывать порты на каждый web-сервер. Получается вот такая схема:

Reverse Proxy

То что мы хотим сделать из сервера web1, называется reverse proxy (обратный прокси).

В то время как forward proxy (прямой прокси) работают от имени клиентов, то есть нам нужно настраивать браузер (клиент), чтобы тот ходил через прямой прокси сервер. Обратные же прокси работают от имени серверов, то есть клиент не знает, что он обращается на прокси сервер.

Reverse proxy принимает запросы от клиентов для того чтобы проксировать их на проксируемые web-сервера (как показано на рисунке).

В качестве обратного прокси сервера для веб серверов может выступать apace или nginx. Есть и другие решения, но в этой статье разберём настройку nginx. На официальном сайте nginx есть небольшой раздел, посвящённый reverse proxy.

Схема нашей лаборатории

Я буду использовать операционную систему Devuan, это облегченный вариант Debian без systemd. Про установку Devuan я уже писал здесь.

У нас будет три сервера:

  • proxy – reverse proxy (ip 192.168.5.82) – установлен nginx;
  • web1 – backend web server (ip 192.168.5.84) – установлен apache2;
  • web2 – backend web server (ip 192.168.5.83) – установлен apache2;

Практическая часть

Настраиваем nginx

Устанавливаем nginx на сервере proxy:

# apt install -y nginx

У меня установился nginx такой версией:

# nginx -v
nginx version: nginx/1.14.2

Для настройки прокси создадим новый виртуальный хост:

# nano /etc/nginx/sites-available/proxy
server {
        # Основные настройки
        listen 80 default_server;
        listen [::]:80 default_server;
        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;
        server_name proxy;

        # Управление заголовками на прокси сервере
        proxy_set_header X-Scheme http;
        proxy_set_header X-Forwarded-Proto http;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-PORT $remote_port;
        proxy_set_header X-Real-IP $remote_addr;

        # настройка буфера для прокси сервера
        proxy_buffering  on;
        proxy_buffer_size 8k;
        proxy_buffers 8 8k;

        location / {
                # вначале попытаемся обработать запрос как файл,
                # затем как каталог, затем вернём ошибку 404
                try_files $uri $uri/ =404;
        }
        
        # проксируем запрос /xxx на web1
        location /xxx {
                proxy_pass http://192.168.5.84/test/;
        }
        
        # проксируем запрос /yyy на web2
        location /yyy {
                proxy_pass http://192.168.5.83/test/;
        }
}

Разбор конфига

На основных настройках я не буду заострять внимание, потому как они не относятся к настройке reverse proxy. Если вкратце там мы указали какие порты слушает наш сервер, корень сайта, индексные страницы и имя сервера.

Следующие опции управляют http заголовками на прокси сервере:

  • proxy_set_header X-Scheme http; – схема по которой подключается клиент (http или https);
  • proxy_set_header X-Forwarded-Proto http; – протокол который использует клиент (http или https);
  • proxy_set_header Host $http_host; – url-адрес по умолчанию, в качестве значения можем указать следующие переменные:
    • $http_host – то что клиент фактически набрал в адресной строке в браузере;
    • $proxy_host – имя и порт проксируемого сервера (web1 или web2), как указано в proxy_pass;
    • $host – имя этого сервера, как указано в server_name (proxy);
  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; – этот заголовок содержит список прокси серверов по которым прошёлся клиент перед этим сервером, а переменная $proxy_add_x_forwarded_for содержит полученный заголовок X-Forwarder-For плюс добавляет свой сервер в этот список (это используется для передачи реального ip-клиента на backend);
  • proxy_set_header X-Real-PORT $remote_port; – заголовок содержит порт клиента и переменная $remote_port содержит тоже порт клиента;
  • proxy_set_header X-Real-IP $remote_addr; – заголовок содержит ip-адрес клиента и переменная $remote_addr содержит тоже самое.

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

  • proxy_buffering on; – включаем буфер для прокси сервера;
  • proxy_buffer_size 8k; – размер буфера для первой части ответа получаемого от проксируемого сервера, такая часть ответа включает в себя только заголовки и хранится отдельно от остальной информации;
  • proxy_buffers 8 8k; – число и размер буферов для одного соединения, а вот сюда помещается ответ от проксируемого сервера.

Теперь разберем часть где мы указываем что проксировать и куда проксировать:

location /xxx {
         proxy_pass http://192.168.5.84/test/;
}
  • /xxx – запрос который будем проксировать;
  • proxy_pass http://192.168.5.84/test/; – куда будем проксировать, то есть на сервер 192.168.5.84 и на каталог /test.
  • Ниже подобный блок для /yyy .

Отключим конфиг “default“, включим созданный нами конфиг “proxy” и перезагрузим службу сервера:

# rm /etc/nginx/sites-enabled/default
# ln -s /etc/nginx/sites-available/proxy /etc/nginx/sites-enabled/proxy
# service nginx restart

Настраиваем backend сервера

На обоих серверах проделаем одно и тоже! Во-первых установим apache2, затем создадим новый каталог /var/www/html/test. В этом каталоге сделаем индексную страничку index.html в которую запишем имя сервера. Вдобавок поменяем владельца нового каталога на www-data.

Проделываем следующее на обоих серверах:

# apt install apache2
# mkdir /var/www/html/test
# echo $HOSTNAME > /var/www/html/test/index.html
# chown -R www-data:www-data /var/www/html/test/

Проверка

Используя адрес прокси сервера, откроем xxx:

Используя адрес прокси сервера, откроем yyy:

Как видим у нас открылись разные странички, которые лежат на разных серверах:

  • web1 лежит на сервере с адресом 192.168.5.84 в каталоге test:
  • web2 лежит на сервере с адресом 192.168.5.83 в каталоге test:

Резервирование серверов

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

  • /xxx – проксируем на http://172.30.93.84/test/ – если он доступен;
  • а если не доступен, то проксируем на http://172.30.93.83/test/.

Для этого поправим наш конфиг /etc/nginx/sites-enabled/proxy и перед блоком server добавим блок upstream:

# nano /etc/nginx/sites-enabled/proxy
upstream backend {
        server 192.168.5.84:80 fail_timeout=120s max_fails=3;
        server 192.168.5.83:80 backup;
}

server {
        listen 80 default_server;

*** сократил ***

В этом блоке указываем оба web-сервера. При этом webбудет основным сервером. Но если proxy в течении 120 секунд получит три ошибки при обращении к web1, то на 120 секунд все запросы пойдут на web2.

Ниже в блоке server, где мы указывали что на что проксировать (блоки location), поменяем записи. Вместо ip-адреса web-сервера укажем название апстрима, которое мы придумали выше (backend). Второй блок (location /yyy) – удаляем. Получится так:

# проксируем запрос /xxx
location /xxx {
         proxy_pass http://backend/test/;
}

Полностью конфиг будет выглядеть так:

upstream backend {
        server 192.168.5.84:80 fail_timeout=3s max_fails=2;
        server 192.168.5.83:80 backup;
}

server {
        listen 80 default_server;
        listen [::]:80 default_server;
        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;
        server_name proxy;

        # Управление заголовками на прокси сервере
        proxy_set_header X-Scheme https;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-PORT $remote_port;
        proxy_set_header X-Real-IP $remote_addr;

        # настройка буфера для прокси сервера
        proxy_buffering  on;
        proxy_buffer_size 32k;
        proxy_buffers 20 512k;

        location / {
                # вначале попытаемся обработать запрос как файл,
                # затем как каталог, затем вернём ошибку 404
                try_files $uri $uri/ =404;
        }

        # проксируем запрос /xxx
        location /xxx {
                proxy_pass http://backend/test/;
        }
}

Перезапустим nginx:

# service nginx restart

Проверка резервирования

В браузере, используя адрес прокси сервера, открываем /xxx:

Затем отключаем сервер web1 и обновляем страничку:

Как видим мы перешли на второй сервер. Теперь включим обратно первый сервер и обновим страничку еще раз:

Теперь мы вернулись на первый сервер.

Таким образом вы можете создать два одинаковых веб сайта и в случае неисправности первого сервера, ваш сайт продолжит работать на втором сервере. Клиенты могут даже ничего не заметить.


Итог

Здесь я разобрал многое, но не всё. Например, можно настроить не резервирование, а балансировку. Про неё, кстати, статей в интернете больше чем про резервный сервер. Я постарался использовать многие http заголовки, чтобы показать как их можно изменять при проксировании. Возможно не все заголовки вам будут нужны в реальной конфигурации. Это зависит от web-приложения, которое вы используете. Буфер для прокси сервера тоже нужно настраивать под конкретную задачу. Поэтому просто копировать приведённые выше конфиги не желательно, нужно анализировать свои действия и все перепроверять.

Сводка
Nginx. Reverse Proxy
Имя статьи
Nginx. Reverse Proxy
Описание
Разберём, что такое Reverse Proxy. А также я покажу как настроить Nginx в качестве Reverse Proxy (обратного прокси сервера)

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

Ваш адрес email не будет опубликован.