Вопрос или проблема
У нас есть сервер обратного проксирования перед сервером Exchange, и мы хотели бы заблокировать больше путей. Минимизированные примеры:
Не работает (но работает для всех страниц, которые не требуют аутентификации):
<VirtualHost 192.168.1.81:443>
ServerName autodiscover.example.com
SSLEngine On
SSLProxyEngine On
Include conf/sslcert.conf
RewriteEngine On
RewriteRule (.*) https://exchangecluster.example.com$1 [P,L]
ProxyPassReverse / https://exchangecluster.example.com/
</VirtualHost>
Работает:
<VirtualHost 192.168.1.81:443>
ServerName autodiscover.example.com
SSLEngine On
SSLProxyEngine On
Include conf/sslcert.conf
RewriteEngine On
ProxyPass / https://exchangecluster.example.com/
ProxyPassReverse / https://exchangecluster.example.com/
</VirtualHost>
Запрос проходит при использовании правила переписывания и отвечает с 401 и предоставляет опции для WWW-Authenticate, как и ожидалось. С ProxyPass аутентификация пользователя работает, в то время как с RewriteRule пользователь постоянно запрашивает аутентификацию, что, как я предполагаю, связано с NTLM.
Есть несколько вопросов на StackExchange, которые говорят, что mod_proxy не может обрабатывать аутентификацию NTLM, но в этом случае это работает.
Проблему с mod-rewrite можно обойти, обрабатывая пути, которые не требуют аутентификации, затем запрещая пути, которые должны быть заблокированы, и затем выполняя глобальный ProxyPass.
Обходной путь:
<VirtualHost 192.168.1.81:443>
ServerName autodiscover.example.com
SSLEngine On
SSLProxyEngine On
Include conf/sslcert.conf
RewriteEngine On
# Заблокировать все запросы, кроме URL-адресов autodiscover
RewriteCond "%{REQUEST_URI}" "!^/autodiscover/autodiscover\.(?:xml|json|svc)$" [NC]
RewriteRule ^ - [F]
ProxyPass / https://exchangecluster.example.com/
ProxyPassReverse / https://exchangecluster.example.com/
</VirtualHost>
В комментарии к другому вопросу предлагалось использовать mpm_prefork_module вместо mpm_worker_module. Я проверил наш 00_mpm.conf, и мы используем worker, и это работает с proxypass, так что кажется, что мы упускаем что-то для опции прокси mod_rewrite.
Большинство вопросов, которые я нашел, касаются того, чтобы обратный прокси аутентифицировался через NTLM. Этот вопрос касается передачи аутентификации на сервер и сохранения сеанса, а не аутентификации с Apache (предполагается, что это не требуется для работы).
Необходимо ли включить какие-либо настройки для разрешения проксирования при использовании mod_rewrite?
Сделал это на Windows с NTLM для аналогичной проблемы на Jenkins, чтобы разрешить неограниченный доступ к wsagents.
# ограниченный доступ, кроме ProxyMatch
<ProxyMatch "^((?!tcpSlaveAgentListener|wsagents).)*$">
NTLMAuth On
NTLMAuthoritative On
NTLMOfferBasic Off
# Здесь добавьте ваши Requires...
</ProxyMatch>
<Proxy "wsagents">
Require all granted
</Proxy>
Ответ или решение
Ваш вопрос касается проблем, связанных с использованием Apache в качестве обратного прокси-сервера для передачи NTLM-аутентификации от клиента к серверу. В частности, наблюдается ситуация, когда использование модуля mod_rewrite
для проксирования запросов недостаточно эффективно в контексте NTLM-аутентификации по сравнению с применением mod_proxy
.
Теория
На первый взгляд, mod_rewrite
и mod_proxy
могут казаться взаимозаменяемыми, поскольку оба они могут быть использованы для перенаправления и проксирования HTTP-запросов. mod_proxy
является специализированным модулем для проксирования запросов, предоставляя более глубокую интеграцию и оптимизацию, в то время как mod_rewrite
изначально разработан для манипуляции URI и перенаправления. Один из ключевых моментов здесь заключается в том, как эти модули обрабатывают заголовки HTTP, особенно в контексте сложной схемы аутентификации, такой как NTLM.
NTLM-аутентификация требует поддержки сессий, поскольку она включает в себя многоступенчатый обмен данными между клиентом и сервером. Процесс NTLM-аутентификации предполагает три этапа, включая отправку и обработку токенов аутентификации между браузером и сервером. Важно, чтобы все эти обмены происходили в рамках одной и той же сессии.
Пример
В предоставленном вами рабочем решении с использованием ProxyPass
:
<VirtualHost 192.168.1.81:443>
ServerName autodiscover.example.com
SSLEngine On
SSLProxyEngine On
Include conf/sslcert.conf
RewriteEngine On
ProxyPass / https://exchangecluster.example.com/
ProxyPassReverse / https://exchangecluster.example.com/
</VirtualHost>
mod_proxy
позволяет Apache обрабатывать сессии NTLM, сохраняя все требуемые атрибуты подключения, такие как заголовки, необходимые для успешной аутентификации. Это происходит за счет специфической обработки заголовков, таких как WWW-Authenticate
, что обеспечивает корректный поток обмена NTLM-пакетами.
Применение
Когда используется mod_rewrite
:
<VirtualHost 192.168.1.81:443>
ServerName autodiscover.example.com
SSLEngine On
SSLProxyEngine On
Include conf/sslcert.conf
RewriteEngine On
RewriteRule (.*) https://exchangecluster.example.com$1 [P,L]
ProxyPassReverse / https://exchangecluster.example.com/
</VirtualHost>
Существует вероятность, что mod_rewrite
может не корректно передавать все необходимые заголовки или нюансы, связанные с управлением сессиями NTLM. Причиной этому может быть ограниченная функциональность или настройки, которые не позволяют полностью сохранить контекст NTLM-аутентификации. Именно поэтому, даже если запрос и проходит, происходит повторная проверка подлинности: сессия не сохраняется корректно, и сервер продолжает запрашивать повторную аутентификацию у клиента.
Для решения этой проблемы вы можете использовать комбинирование конфигураций или уклоняться от использования mod_rewrite
для сложной обработки случаев, связанных с NTLM. С точки зрения конфигурации, где вы заблокируете пути, не требующие аутентификации, а затем используете стандартный ProxyPass
, это позволит избежать вышеупомянутого ограничения:
<VirtualHost 192.168.1.81:443>
ServerName autodiscover.example.com
SSLEngine On
SSLProxyEngine On
Include conf/sslcert.conf
RewriteEngine On
# Block all requests except the autodiscover URLs
RewriteCond "%{REQUEST_URI}" "!^/autodiscover/autodiscover\.(?:xml|json|svc)$" [NC]
RewriteRule ^ - [F]
ProxyPass / https://exchangecluster.example.com/
ProxyPassReverse / https://exchangecluster.example.com/
</VirtualHost>
Если вам все же необходимо использовать mod_rewrite
, возможно, вы сможете улучшить его поведение, строго контролируя заголовки, которые должны быть переданы клиенту или серверу для поддержания сессии NTLM. Убедитесь в том, что ProxyPreserveHost On
и любые другие параметры, обеспечивающие корректное управление HTTP-заголовками, корректно настроены.
Таким образом, решение вашего вопроса может заключаться в полном отказе от использования mod_rewrite
для NTLM или более тщательной проверке и настройке правил проксирования и аутентификации, чтобы обеспечить полную и непрерывную поддержку сессий.