Как использовать Apache в качестве обратного прокси-сервера с mod_proxy в Ubuntu 16.04

Вступление

reverse proxy - это тип прокси-сервера, который принимает запросы HTTP (S) и прозрачно распределяет их между одним или несколькими внутренними серверами. Обратные прокси-серверы полезны, потому что многие современные веб-приложения обрабатывают входящие HTTP-запросы, используя внутренние серверы приложений, к которым пользователи не обращаются напрямую, и зачастую поддерживают только элементарные функции HTTP.

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

В этом руководстве вы настроите Apache в качестве базового обратного прокси-сервера с помощью расширенияmod_proxy для перенаправления входящих подключений на один или несколько внутренних серверов, работающих в одной сети. В этом руководстве используется простой бэкэнд, написанный с помощьюFlask web framework, но вы можете использовать любой бэкэнд-сервер по своему усмотрению.

Предпосылки

Чтобы следовать этому уроку, вам понадобится:

[[step-1 -—- enable-required-apache-modules]] == Шаг 1. Включение необходимых модулей Apache

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

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

  • mod_proxy, основной модуль прокси-сервера Apache, модуль для перенаправления соединений; он позволяет Apache выступать в качестве шлюза для базовых серверов приложений.

  • mod_proxy_http, который добавляет поддержку проксирования HTTP-соединений.

  • mod_proxy_balancer иmod_lbmethod_byrequests, которые добавляют функции балансировки нагрузки для нескольких внутренних серверов.

Чтобы включить эти четыре модуля, последовательно выполните следующие команды.

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests

Чтобы эти изменения вступили в силу, перезапустите Apache.

sudo systemctl restart apache2

Теперь Apache готов действовать в качестве обратного прокси-сервера для HTTP-запросов. На следующем (необязательном) шаге мы создадим два базовых серверных сервера. Это поможет нам проверить, правильно ли работает конфигурация, но если у вас уже есть свои собственные серверные приложения, вы можете перейти к шагу 3.

[[step-2 -—- create-backend-test-servers]] == Шаг 2. Создание серверных тестовых серверов

Запуск некоторых простых бэкэнд-серверов - это простой способ проверить правильность работы конфигурации Apache. Здесь мы создадим два тестовых сервера, которые отвечают на HTTP-запросы с печатью строки текста. Один сервер скажетHello world!, а другой скажетHowdy world!.

[.note] #Note: В нетестовых установках все внутренние серверы обычно возвращают контент одного и того же типа. Однако, в частности, для этого теста наличие двух серверов, возвращающих разные сообщения, позволяет легко проверить, что механизм балансировки нагрузки использует оба.
#

Flask - это микросхема Python для создания веб-приложений. Мы используем Flask для создания тестовых серверов, потому что базовое приложение требует всего несколько строк кода. Вам не нужно знать Python для их настройки, но если вы хотите научиться, вы можете посмотретьthese Python tutorials.

Сначала обновите список пакетов.

sudo apt-get update

Затем установите Pip, рекомендуемый менеджер пакетов Python.

sudo apt-get -y install python3-pip

Используйте Pip для установки Flask.

sudo pip3 install flask

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

nano ~/backend1.py

Скопируйте следующий код в файл, затем сохраните и закройте его.

~/backend1.py

from flask import Flask
app = Flask(__name__)

@app.route('/')
def home():
    return 'Hello world!'

Первые две строки инициализируют структуру Flask. Есть одна функцияhome(), которая возвращает строку текста (Hello world!). Строка@app.route('/') над определением функцииhome() сообщает Flask использовать возвращаемое значениеhome() в качестве ответа на HTTP-запросы, направленные на корневой URL-адрес/ приложения.

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

cp ~/backend1.py ~/backend2.py

Откройте только что скопированный файл.

nano ~/backend2.py

Измените возвращаемое сообщение сHello world! наHowdy world!, затем сохраните и закройте файл.

~/backend2.py

from flask import Flask
app = Flask(__name__)

@app.route('/')
def home():
    return 'Howdy world!'

Используйте следующую команду, чтобы запустить первый фоновый сервер на порту8080. Это также перенаправляет вывод Flask на/dev/null, потому что в дальнейшем это будет затемнять вывод консоли.

FLASK_APP=~/backend1.py flask run --port=8080 >/dev/null 2>&1 &

Здесь мы предшествуем командеflask, устанавливая переменную средыFLASK_APP в той же строке. Переменные среды являются удобным способом передачи информации в процессы, порожденные из оболочки. Вы можете узнать больше о переменных среды вHow To Read and Set Environmental and Shell Variables on a Linux VPS.

В этом случае использование переменной среды гарантирует, что параметр применяется только к выполняемой команде и не останется доступным после этого, поскольку мы передадим другое имя файла таким же образом, чтобы указать командеflask запустить второй сервер

Точно так же используйте эту команду для запуска второго сервера на порту8081. Обратите внимание на другое значение переменной средыFLASK_APP.

FLASK_APP=~/backend2.py flask run --port=8081 >/dev/null 2>&1 &

Вы можете проверить, что два сервера работают, используяcurl. Протестируйте первый сервер:

curl http://127.0.0.1:8080/

Это выведетHello world! в терминал. Протестируйте второй сервер:

curl http://127.0.0.1:8081/

Вместо этого будет выведеноHowdy world!.

[.note] #Note: чтобы закрыть оба тестовых сервера после того, как они больше не нужны, например, когда вы закончите это руководство, вы можете просто выполнитьkillall flask.
#

На следующем шаге мы изменим файл конфигурации Apache, чтобы разрешить его использование в качестве обратного прокси-сервера.

[[step-3 -—- modifying-the-default-configuration-to-enable-reverse-proxy]] == Шаг 3. Изменение конфигурации по умолчанию для включения обратного прокси

В этом разделе мы настроим виртуальный хост Apache по умолчанию для использования в качестве обратного прокси-сервера для одного внутреннего сервера или массива внутренних серверов с балансировкой нагрузки.

[.Примечание]##

Note: в этом руководстве мы применяем конфигурацию на уровне виртуального хоста. При установке Apache по умолчанию включен только один виртуальный хост по умолчанию. Однако вы можете использовать все эти фрагменты конфигурации и на других виртуальных хостах. Чтобы узнать больше о виртуальных хостах в Apache, вы можете прочитать это руководствоHow To Set Up Apache Virtual Hosts on Ubuntu 16.04.

Если ваш сервер Apache действует как сервер HTTP и HTTPS, конфигурация обратного прокси-сервера должна быть размещена на виртуальных хостах HTTP и HTTPS. Чтобы узнать больше о SSL с Apache, вы можете прочитать это руководствоHow To Create a Self-Signed SSL Certificate for Apache in Ubuntu 16.04.

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

sudo nano /etc/apache2/sites-available/000-default.conf

Внутри этого файла вы найдете блок<VirtualHost *:80>, начинающийся с первой строки. В первом примере ниже объясняется, как настроить этот блок для обратного прокси-сервера для одного внутреннего сервера, а во втором - обратный прокси-сервер с балансировкой нагрузки для нескольких внутренних серверов.

[[example-1 -—- reverse-proxying-a-single-backend-server]] === Пример 1. Обратное проксирование отдельного внутреннего сервера

Замените все содержимое в блокеVirtualHost следующим, чтобы ваш файл конфигурации выглядел так:

/etc/apache2/sites-available/000-default.conf


    ProxyPreserveHost On

    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/

Если вы следовали примеру серверов на шаге 2, используйте127.0.0.1:8080, как написано в блоке выше. Если у вас есть свои собственные серверы приложений, используйте их адреса.

Здесь есть три директивы:

  • ProxyPreserveHost заставляет Apache передавать исходный заголовокHost внутреннему серверу. Это полезно, так как сервер уведомляет адрес, используемый для доступа к приложению.

  • ProxyPass - это основная директива конфигурации прокси. В этом случае он указывает, что все, что находится под корневым URL-адресом (/), должно быть сопоставлено с внутренним сервером по данному адресу. Например, если Apache получит запрос/example, он подключится кhttp://your_backend_server/example и вернет ответ исходному клиенту.

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

Чтобы эти изменения вступили в силу, перезапустите Apache.

sudo systemctl restart apache2

Теперь, если вы получите доступ кhttp://your_server_ip в веб-браузере, вы увидите ответ внутреннего сервера вместо стандартной страницы приветствия Apache. Если вы выполнили шаг 2, это означает, что вы увидитеHellow world!.

[[example-2 -—- load-balancing-between-multiple-backend-servers]] === Пример 2 - Балансировка нагрузки между несколькими Backend-серверами

Если у вас несколько внутренних серверов, хороший способ распределить трафик между ними при проксировании - использовать функции балансировки нагрузкиmod_proxy.

Замените все содержимое в блокеVirtualHost следующим, чтобы ваш файл конфигурации выглядел так:

/etc/apache2/sites-available/000-default.conf



    BalancerMember http://127.0.0.1:8080
    BalancerMember http://127.0.0.1:8081


    ProxyPreserveHost On

    ProxyPass / balancer://mycluster/
    ProxyPassReverse / balancer://mycluster/

Конфигурация аналогична предыдущей, но вместо того, чтобы указывать один сервер напрямую, мы использовали дополнительный блокProxy для определения нескольких серверов. Блок называетсяbalancer://mycluster (имя можно свободно изменять) и состоит из одной или нескольких директивBalancerMember+`s, which specify the underlying backend server addresses. The `+ProxyPass, аProxyPassReverse использует пул балансировщика нагрузки с именемmycluster вместо определенного сервер.

Если вы следовали примеру серверов на шаге 2, используйте127.0.0.1:8080 и127.0.0.1:8081 для директивBalancerMember, как написано в блоке выше. Если у вас есть свои собственные серверы приложений, используйте их адреса.

Чтобы эти изменения вступили в силу, перезапустите Apache.

sudo systemctl restart apache2

Если вы войдете вhttp://your_server_ip в веб-браузере, вы увидите ответы своих внутренних серверов вместо стандартной страницы Apache. Если вы выполнили шаг 2, при многократном обновлении страницы должны отображатьсяHello world! иHowdy world!, что означает, что обратный прокси-сервер работал и выполняет балансировку нагрузки между обоими серверами.

Заключение

Теперь вы знаете, как настроить Apache в качестве обратного прокси-сервера для одного или нескольких базовых серверов приложений. mod_proxy можно эффективно использовать для настройки обратного прокси-сервера для серверов приложений, написанных на широком спектре языков и технологий, таких как Python и Django или Ruby и Ruby on Rails. Он также может использоваться для балансировки трафика между несколькими внутренними серверами для сайтов с большим трафиком, или для обеспечения высокой доступности через несколько серверов, или для обеспечения безопасной поддержки SSL для внутренних серверов, не поддерживающих SSL изначально.

Хотяmod_proxy сmod_proxy_http - это, пожалуй, наиболее часто используемая комбинация модулей, есть несколько других, которые поддерживают разные сетевые протоколы. Мы не использовали их здесь, но некоторые другие популярные модули включают в себя:

  • mod_proxy_ftp для FTP.

  • mod_proxy_connect для туннелирования SSL.

  • mod_proxy_ajp для AJP (протокол Apache JServ), например серверные части на основе Tomcat.

  • mod_proxy_wstunnel для веб-сокетов.

Чтобы узнать больше оmod_proxy, вы можете прочитатьthe official Apache mod_proxy documentation.

Related