Вопрос или проблема
Я использую Tomcat 9 за Apache Httpd в классической конфигурации с использованием mod_proxy
Apache Httpd настроен как обратный прокси:
<IfModule mod_proxy.c>
# Явно не проксируем страницы ошибок
ProxyPass "/http_error/" !
# Передаем каждый запрос Tomcat, который слушает на 127.0.0.1:8080
ProxyPass "/" "http://127.0.0.1:8080/"
ProxyPassReverse "/" "http://127.0.0.1:8080/"
</IfModule>
Я могу легко добавить контроль доступа на уровне Apache Http с помощью mod_authz_core
и mod_authz_host
.
Но могу ли я сделать это на уровне Tomcat?
Например, приложение менеджера по умолчанию выполняет фильтрацию в своем META-INF/context.xml
(в моем случае, /var/lib/tomcat/webapps/manager/META-INF/context.xml
), настраивая RemoteAddressValve
:
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
Это гарантирует, что приложение менеджера может быть доступно только клиентами, обращающимися с локального адреса. В случае Tomcat, находящегося за прокси, это, конечно, всегда правда – все запросы приходят с 127.0.0.1
.
Поэтому я подумал, что могу ограничить доступ к хосту 192.168.1.34
(например), сделав следующее:
Сделать IP-адрес клиента проверяемым
Настроить RemoteIpValve
для передачи X-Forwarded-For
заголовков в поле исходного IP-адреса запросов:
В server.xml
, на уровне Engine
:
<Valve className="org.apache.catalina.valves.RemoteIpValve"
internalProxies="192\.168\.1\.30|127\.0\.0\.\1" />
где internalProxies
указывает ожидаемый адрес обратного прокси.
Фильтрация по IP-адресу
Изменить запись RemoteAddressValve
в context.xml
веб-приложения на:
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="192\.168\.1\.34" />
Теперь мы должны иметь возможность получить доступ к веб-приложению с клиента с IP-адресом 192.168.1.34
.
Этот трюк не срабатывает – доступ с 192.168.1.34
фактически отклоняется!
Поэтому, возможно, конфигурация правильная. Из справочного материала:
usePeerAddress
: Используйте адрес соединения пира вместо IP-адреса клиента. Они будут различаться, если перед Tomcat используется обратный прокси в сочетании либо с протоколом AJP, либо с HTTP-протоколом плюсRemoteIp(Valve|Filter)
.
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
usePeerAddress="true"
allow="192\.168\.1\.34" />
Но это тоже не срабатывает, доступ не разрешен.
Можно ли сделать так, чтобы это работало?
Ответ или решение
Вопрос: Можно ли ограничить доступ к URL-адресам в Tomcat за обратным прокси с использованием RemoteAddrValve
?
Введение
В данной статье рассмотрим возможность ограничения доступа к ресурсам веб-приложений в Tomcat, работающем за обратным прокси-сервером Apache Httpd. Вы правильно отметили, что Apache Httpd может осуществлять контроль доступа на своем уровне с использованием модулей, таких как mod_authz_core
и mod_authz_host
. Однако, вопрос о том, можно ли реализовать подобный контроль доступа в самом Tomcat, также имеет важное значение.
Настройка обратного прокси
Обратный прокси-сервер Apache Httpd предоставляет гибкие возможности для настройки маршрутизации и фильтрации запросов. Как вы верно указали в вашей конфигурации, сервер перенаправляет все запросы к Tomcat, работающему на локальной машине. Важно понимать, что после этого все входящие запросы, по сути, будут восприниматься Tomcat как исходящие от 127.0.0.1
, что затрудняет использование фильтров на основе IP-адресов на уровне приложения.
Передача информации о клиентском IP-адресе
Для решения этой проблемы вы можете использовать RemoteIpValve
, который позволяет передавать исходные IP-адреса клиентов через заголовок X-Forwarded-For
. В вашем случае правильная настройка в файле server.xml
может выглядеть так:
<Valve className="org.apache.catalina.valves.RemoteIpValve"
internalProxies="192\.168\.1\.30|127\.0\.0\.\1"
remoteIpHeader="X-Forwarded-For"
proxiesHeader="X-Forwarded-By" />
Здесь internalProxies
указывает адреса доверенных прокси, и только запросы от них смогут передавать корректный IP-адрес клиента.
Настройка фильтрации IP-адресов в Tomcat
Теперь, когда клиентский IP-адрес будет правильно обрабатываться, вы можете настроить RemoteAddrValve
в конфигурации вашего приложения (например, в META-INF/context.xml
):
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="192\.168\.1\.34" />
Это должно обеспечить доступ к вашему приложению только для клиентов с адресом 192.168.1.34
.
Использование параметра usePeerAddress
Опция usePeerAddress
предназначена для случаев, когда необходимо использовать адрес подключенного клиента вместо адреса, полученного через RemoteIpValve
. Если вы уже настроили RemoteIpValve
, то значение usePeerAddress
должно оставаться по умолчанию (false), иначе Tomcat будет рассматривать соединение как исходящее от прокси, а не от клиента.
Если вы установите:
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
usePeerAddress="true"
allow="192\.168\.1\.34" />
То это может вызвать проблемы, так как Tomcat может уже не "видеть" IP-адреса пользователей, передаваемые через заголовки.
Заключение
Таким образом, для возможности ограничения доступа к URL-адресам в Tomcat, работающем за прокси, рекомендуем использовать RemoteIpValve
, чтобы правильно передавать IP-адреса клиентов, и затем фильтровать доступ с помощью RemoteAddrValve
. Не забывайте также проверять, что соответствующие заголовки корректно передаются от прокси-сервера к Tomcat и что конфигурация соответствует требованиям безопасности вашей окружения.
Помните, что правильная настройка обратного прокси требует детального подхода к безопасному хранению и обновлению конфигураций. При возникновении дополнительных вопросов или проблем всегда можно обратиться к документации Tomcat и Apache Httpd или найти помощь в сообществах пользователей.