Apache HTTP Server, leveraging свой набор модулей mod_proxy, функционирует как эффективный обратный прокси, перенаправляя клиентские запросы к внутренним серверам и возвращая их ответы, что повышает безопасность, производительность и возможности балансировки нагрузки для веб-приложений.
Обратный прокси-сервер действует как посредник между клиентами и внутренними серверами. Он принимает запросы от клиентов, перенаправляет их к соответствующим внутренним серверам, а затем возвращает ответы этих серверов клиентам. Apache с mod_proxy является гибким и мощным инструментом для реализации этой архитектуры, предлагая функционал для маршрутизации HTTP/S, балансировки нагрузки, кэширования и обеспечения безопасности.
Основные модули mod_proxy
Для работы Apache в режиме обратного прокси требуется активировать несколько ключевых модулей. Минимальный набор включает mod_proxy и протокольно-специфичные модули.
mod_proxy: Основной прокси-модуль. Он предоставляет базовую функциональность проксирования.mod_proxy_http: Обеспечивает поддержку проксирования HTTP и HTTPS-трафика.mod_proxy_balancer: Добавляет возможности балансировки нагрузки между несколькими внутренними серверами.mod_proxy_ftp: Поддерживает проксирование FTP-трафика.mod_proxy_ajp: Позволяет проксировать трафик по протоколу AJP (Apache JServ Protocol), часто используемому с серверами приложений, такими как Tomcat.mod_proxy_wstunnel: Добавляет поддержку проксирования WebSockets.mod_ssl: Требуется для обработки SSL/TLS соединений, включая терминирование SSL и проксирование HTTPS к внутренним серверам.mod_cache,mod_cache_disk: Модули для кэширования содержимого, уменьшающие нагрузку на внутренние серверы.
Для активации модулей используйте команду a2enmod (для Debian/Ubuntu-подобных систем) или вручную раскомментируйте строки LoadModule в файле конфигурации Apache (httpd.conf или apache2.conf).
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod proxy_wstunnel
sudo a2enmod ssl
sudo systemctl restart apache2
Базовая конфигурация обратного прокси
Базовая настройка обратного прокси включает директивы ProxyPass и ProxyPassReverse.
ProxyRequests Off: Отключает функциональность прямого прокси, что является критически важной мерой безопасности для обратного прокси. Без этой директивы ваш сервер может быть использован как открытый прокси.ProxyPass [путь_на_прокси] [URL_внутреннего_сервера]: Сопоставляет URL-путь на прокси-сервере с URL-адресом внутреннего сервера. Запросы кпуть_на_проксибудут перенаправляться кURL_внутреннего_сервера.ProxyPassReverse [путь_на_прокси] [URL_внутреннего_сервера]: Переписывает заголовкиLocation,Content-LocationиURIв ответах от внутреннего сервера, чтобы они соответствовали URL-адресу, доступному клиенту через прокси. Это предотвращает раскрытие внутренней структуры сети и некорректные редиректы.ProxyPreserveHost On|Off: ЕслиOn, Apache будет передавать оригинальный заголовокHostот клиента к внутреннему серверу. ЕслиOff(по умолчанию), будет использоватьсяHostзаголовок, соответствующийURL_внутреннего_сервера. Обычно рекомендуется использоватьOnдля корректной работы многих веб-приложений.
Пример простой настройки обратного прокси для приложения, работающего на http://backend-app:8080/:
<VirtualHost *:80>
ServerName yourdomain.com
ServerAlias www.yourdomain.com
# Отключение прямого прокси
ProxyRequests Off
# Передача оригинального заголовка Host
ProxyPreserveHost On
# Проксирование всех запросов к корневому пути
ProxyPass / http://backend-app:8080/
ProxyPassReverse / http://backend-app:8080/
# Ограничение доступа к прокси-функционалу
<Proxy *>
Require all granted
# Если нужно ограничить по IP:
# Require ip 192.168.1.0/24
</Proxy>
ErrorLog ${APACHE_LOG_DIR}/yourdomain_error.log
CustomLog ${APACHE_LOG_DIR}/yourdomain_access.log combined
</VirtualHost>
Для проксирования только определенного пути:
<VirtualHost *:80>
ServerName yourdomain.com
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /api/ http://backend-api-server:9000/
ProxyPassReverse /api/ http://backend-api-server:9000/
# Другие запросы могут быть обработаны локально или другим прокси
DocumentRoot /var/www/html/frontend
<Proxy *>
Require all granted
</Proxy>
ErrorLog ${APACHE_LOG_DIR}/yourdomain_error.log
CustomLog ${APACHE_LOG_DIR}/yourdomain_access.log combined
</VirtualHost>
Балансировка нагрузки с mod_proxy_balancer
mod_proxy_balancer позволяет распределять входящие запросы между несколькими внутренними серверами, повышая доступность и масштабируемость.
Настройка балансировщика осуществляется с помощью директивы ProxyPass с префиксом balancer://. Каждый внутренний сервер (член балансировщика) определяется с помощью директивы BalancerMember.
<VirtualHost *:80>
ServerName yourdomain.com
ProxyRequests Off
ProxyPreserveHost On
<Proxy balancer://mycluster>
BalancerMember http://backend1.example.com:8080 route=1
BalancerMember http://backend2.example.com:8080 route=2
# Дополнительные параметры для BalancerMember:
# loadfactor=N (вес сервера)
# status=+ID (идентификатор для sticky sessions)
# timeout=N (таймаут соединения)
# max=N (максимальное количество соединений)
# acquire=N (максимальное количество запросов в очереди)
# disablereuse=on (отключает повторное использование соединений)
# Алгоритм балансировки:
# byrequests (по умолчанию, Round Robin)
# bytraffic (по объему трафика)
# bybusyness (по наименьшему количеству активных запросов)
# byexponent (экспоненциальный)
ProxySet lbmethod=byrequests
# "Липкие" сессии (sticky sessions)
# Позволяют направлять запросы одного клиента всегда на один и тот же backend
# Используйте route=N в BalancerMember и ProxySet stickysession=JSESSIONID|route
ProxySet stickysession=JSESSIONID|route
</Proxy>
ProxyPass /app/ balancer://mycluster/
ProxyPassReverse /app/ balancer://mycluster/
<Proxy *>
Require all granted
</Proxy>
ErrorLog ${APACHE_LOG_DIR}/yourdomain_error.log
CustomLog ${APACHE_LOG_DIR}/yourdomain_access.log combined
</VirtualHost>
Методы балансировки нагрузки
Метод (lbmethod) |
Описание | Применение |
|---|---|---|
byrequests |
Round Robin (по умолчанию). Распределяет запросы по очереди между серверами. Простой и эффективный для равномерной нагрузки. | Общее назначение, когда все внутренние серверы равнозначны. |
bytraffic |
Распределяет запросы на основе объема переданного трафика. Серверы с меньшим объемом трафика получают больше запросов. | Для серверов, производительность которых зависит от объема данных. |
bybusyness |
Направляет запросы на сервер с наименьшим количеством активных запросов. | Подходит для серверов с переменной производительностью или когда запросы имеют разную длительность. |
byexponent |
Распределяет запросы на основе экспоненциального взвешивания, учитывая время ответа и количество ошибок. | Для динамической адаптации к изменяющейся производительности серверов. |
SSL/TLS терминирование и проксирование
Обратный прокси часто используется для терминирования SSL/TLS соединений. Клиент устанавливает зашифрованное соединение с прокси, а прокси затем передает расшифрованные запросы внутренним серверам (возможно, по незашифрованному HTTP или по другому зашифрованному HTTPS-соединению).
Для SSL/TLS терминирования требуются mod_ssl и настроенные сертификаты.
<VirtualHost *:443>
ServerName yourdomain.com
SSLEngine On
SSLCertificateFile /etc/ssl/certs/yourdomain.com.crt
SSLCertificateKeyFile /etc/ssl/private/yourdomain.com.key
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder On
ProxyRequests Off
ProxyPreserveHost On
# Проксирование на внутренний HTTP-сервер
ProxyPass / http://backend-app:8080/
ProxyPassReverse / http://backend-app:8080/
# Или проксирование на внутренний HTTPS-сервер (с проверкой сертификата)
# SSLProxyEngine On # Включает SSL для исходящих прокси-соединений
# SSLProxyCACertificateFile /etc/ssl/certs/internal_ca.crt # CA для внутренних серверов
# ProxyPass / https://backend-secure:8443/
# ProxyPassReverse / https://backend-secure:8443/
<Proxy *>
Require all granted
</Proxy>
ErrorLog ${APACHE_LOG_DIR}/yourdomain_ssl_error.log
CustomLog ${APACHE_LOG_DIR}/yourdomain_ssl_access.log combined
</VirtualHost>
# Перенаправление HTTP на HTTPS
<VirtualHost *:80>
ServerName yourdomain.com
Redirect permanent / https://yourdomain.com/
</VirtualHost>
SSLProxyEngine On необходима, если Apache сам должен инициировать HTTPS-соединение с внутренним сервером. SSLProxyCACertificateFile или SSLProxyCACertificatePath используются для проверки сертификатов внутренних HTTPS-серверов.
Проксирование WebSockets с mod_proxy_wstunnel
WebSockets требуют специальной обработки, так как они устанавливают долгоживущее соединение, отличное от стандартного HTTP-запрос/ответ цикла. mod_proxy_wstunnel обеспечивает эту функциональность.
<VirtualHost *:80>
ServerName yourdomain.com
ProxyRequests Off
ProxyPreserveHost On
# Проксирование обычного HTTP-трафика
ProxyPass /app/ http://backend-app:8080/
ProxyPassReverse /app/ http://backend-app:8080/
# Проксирование WebSockets
# Используйте ws:// или wss:// в зависимости от протокола внутреннего сервера
ProxyPass /ws/ ws://backend-app:8080/ws/
ProxyPassReverse /ws/ ws://backend-app:8080/ws/
<Proxy *>
Require all granted
</Proxy>
ErrorLog ${APACHE_LOG_DIR}/yourdomain_error.log
CustomLog ${APACHE_LOG_DIR}/yourdomain_access.log combined
</VirtualHost>
Для HTTPS-соединений, терминируемых на Apache, и проксирования WebSockets к внутреннему серверу по ws://, конфигурация будет аналогичной, но в VirtualHost *:443. Если внутренний сервер также использует wss://, то ProxyPass должен быть настроен с wss://, и SSLProxyEngine On также может потребоваться.
Кэширование с mod_cache и mod_cache_disk
Модули кэширования позволяют Apache сохранять ответы от внутренних серверов и отдавать их напрямую клиентам при повторных запросах, не обращаясь к бэкенду. Это снижает нагрузку и улучшает время отклика.
# Включите модули кэширования
# sudo a2enmod cache
# sudo a2enmod cache_disk
# sudo systemctl restart apache2
<IfModule mod_cache.c>
<IfModule mod_cache_disk.c>
# Директория для хранения кэшированных файлов
CacheRoot "/var/cache/apache2/mod_cache_disk"
# Уровни поддиректорий для распределения файлов
CacheDirLevels 2
# Количество символов в имени директории на каждом уровне
CacheDirLength 1
# Максимальный размер кэша (в КБ), 0 = без ограничений
CacheMaxFileSize 10000000 # ~10MB
CacheMinFileSize 1024 # ~1KB
# Автоматическое удаление устаревших/неиспользуемых файлов
CacheGcInterval 4
# Включение кэширования для определенного пути
CacheEnable disk /static/
CacheEnable disk /images/
# Отключение кэширования для определенных путей (например, для динамического контента)
CacheDisable /admin/
CacheDisable /login/
# Настройки для кэширования заголовков
CacheHeader On
CacheIgnoreCacheControl On # Игнорировать Cache-Control от backend
# Максимальное время жизни кэшированного объекта, если backend не предоставляет Cache-Control/Expires
CacheDefaultExpire 3600
# Максимальное время жизни кэшированного объекта после модификации, если backend не предоставляет Last-Modified
CacheMaxExpire 86400
# Управление заголовками Cache-Control
<Location /static/>
# Добавляем Cache-Control для клиентов, чтобы они тоже кэшировали
Header set Cache-Control "max-age=3600, public"
</Location>
</IfModule>
</IfModule>
<VirtualHost *:80>
ServerName yourdomain.com
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://backend-app:8080/
ProxyPassReverse / http://backend-app:8080/
<Proxy *>
Require all granted
</Proxy>
ErrorLog ${APACHE_LOG_DIR}/yourdomain_error.log
CustomLog ${APACHE_LOG_DIR}/yourdomain_access.log combined
</VirtualHost>
Создайте директорию для кэша и установите правильные права:
sudo mkdir -p /var/cache/apache2/mod_cache_disk
sudo chown -R www-data:www-data /var/cache/apache2/mod_cache_disk
Вопросы безопасности
Настройка обратного прокси требует внимания к безопасности, чтобы предотвратить несанкционированный доступ и злоупотребления.
ProxyRequests Off: Это самая важная директива. Она отключает функциональность прямого прокси, которая по умолчанию включена вmod_proxy. ЕслиProxyRequestsне отключен, ваш Apache-сервер может быть использован как открытый прокси для доступа к любым ресурсам в интернете, что является серьезной уязвимостью.- Контроль доступа: Используйте директивы
Requireвнутри<Proxy>блоков для ограничения доступа к прокси-функционалу.
apacheconf <Proxy *> Require all denied # Запретить всем по умолчанию Require ip 192.168.1.0/24 # Разрешить только из внутренней сети Require host trusted.example.com # Разрешить только с определенных хостов </Proxy> ProxyPreserveHost On: Передача оригинального заголовкаHostможет быть важна для работы backend-приложений, но также может быть фактором в некоторых атаках, если backend не обрабатываетHostзаголовок корректно.- Управление заголовками: Используйте
RequestHeaderиResponseHeaderдля добавления, удаления или изменения заголовков HTTP, проходящих через прокси. Например, можно удалить заголовки, раскрывающие внутреннюю информацию (Server,X-Powered-By).
apacheconf RequestHeader unset X-Forwarded-For ResponseHeader unset X-Powered-By - Заголовки
X-Forwarded-*: Apache автоматически добавляет заголовкиX-Forwarded-For,X-Forwarded-Host,X-Forwarded-Serverдля информирования backend о реальном IP-адресе клиента, оригинальном хосте и имени прокси-сервера. Эти заголовки критически важны для логирования и работы приложений. Убедитесь, что backend-приложения используют их для получения реальной информации о клиенте. - Модули безопасности:
mod_security: Мощный Web Application Firewall (WAF), который может быть интегрирован с Apache для фильтрации вредоносных запросов до их попадания на backend.mod_evasive: Помогает предотвращать атаки типа DoS/DDoS, ограничивая количество запросов от одного IP-адреса.
- Обновления: Регулярно обновляйте Apache и операционную систему для устранения известных уязвимостей.
Диагностика и устранение неисправностей
При возникновении проблем с Apache в режиме обратного прокси, используйте следующие методы для диагностики:
- Логи Apache:
error_log: Основной источник информации об ошибках. УстановитеLogLevelнаinfoилиdebugдля получения более подробных сообщений.access_log: Показывает, какие запросы Apache получил и как он их обработал (HTTP-код ответа).
- Тестирование прямого доступа к backend: Убедитесь, что внутренний сервер доступен и корректно отвечает, минуя прокси. Это поможет определить, проблема в Apache или в backend.
curlс прокси: Используйтеcurl -v http://yourdomain.com/для получения подробной информации о запросе и ответе, включая заголовки.mod_infoиmod_status:mod_info: Предоставляет полную информацию о конфигурации Apache.mod_status: Показывает статистику работы сервера, активные соединения и запросы.
Активируйте их и настройте доступ только из доверенных IP-адресов:
apacheconf <Location /server-status> SetHandler server-status Require ip 127.0.0.1 Require ip 192.168.1.0/24 </Location> <Location /server-info> SetHandler server-info Require ip 127.0.0.1 Require ip 192.168.1.0/24 </Location>
ProxyPassиProxyPassReverse: Проверьте правильность путей и URL-адресов. Ошибки здесь часто приводят к некорректным редиректам или ошибкам 404/503.- SSL/TLS: Убедитесь, что сертификаты корректны, не просрочены и соответствуют домену. Проверьте
SSLCertificateFile,SSLCertificateKeyFileиSSLProxyEngine. - Firewall: Убедитесь, что правила брандмауэра на прокси-сервере и на внутренних серверах разрешают необходимый трафик (например, Apache должен иметь возможность подключаться к портам backend-серверов).