Балансировка нагрузки на основе сертификата клиента с помощью Apache mod_proxy_ajp и Tomcat
В настоящее время я использую mod_proxy_ajp для загрузки запросов баланса на несколько серверов Tomcat. Абоненты аутентифицируются с использованием клиентских сертификатов и ACL. Это работает нормально, абоненты направляются на любой сервер с одинаковой скоростью. Теперь я хочу предварительно выбрать и кэшировать данные для каждого пользователя, чтобы каждый сервер Tomcat обслуживал известный набор пользователей. Так что я думаю, что было бы хорошо разделить абонента по алфавиту; пользователи с именами (CN или DN), начинающимися с AM, переходят на сервер 1, пользователи с именами, начинающимися с [NZ], переходят на сервер 2. Но я не знаю, как это сделать.
В настоящее время у меня есть:
<Proxy balancer://lb-service>
BalancerMember ajp://svr1:8009 loadfactor=1
BalancerMember ajp://svr2:8009 loadfactor=1
</Proxy>
<Location /lookup>
ProxyPass balancer://lb-service/lookup
</Location>
Я рассматриваю возможность использования mod_rewite для изменения URL-адреса, чтобы включить CN пользователя, но я не могу заставить эту работу работать.
Я довольно сильно застрял, используя apache mod_proxy_ajp и Tomcat для балансировки нагрузки. Я могу изменить службы, на которых запущен Tomcat, для приема разных запросов.
У кого-нибудь есть хороший способ сделать это?
1 ответ
Интересная идея для кеширования! Посмотрим, сможем ли мы заставить его работать..
У меня есть несколько вариантов: один, который будет более эффективным, но я действительно не знаю, сработает ли он, и другой, который менее эффективен, но я уверен, что он будет работать нормально.
Проблема с более эффективной опцией (и, в более общем смысле, с использованием чего-то вроде клиентского сертификата для определения назначения балансировщика нагрузки) заключается в том, что, насколько я знаю, нет способа изменить мнение mod_proxy_balancer о назначении узла после поступления запроса - есть возможно, какая-то креативная хакерская атака, которая могла бы сделать это, но я не придумываю какие-либо лучшие идеи из головы. Суть в том, что он выполняет перенаправление в то же местоположение, в котором находится, для того, чтобы иметь cookie на месте для первого запроса, который передается через прокси, чтобы найти правильный маршрут - и я не уверен, будет ли это работать, Стоит попробовать:
RewriteEngine On
RewriteCond %{ENV:BALANCER_ROUTE_CHANGED} 1
RewriteCond %{SSL:SSL_CLIENT_S_DN} ^[a-m] [NC]
RewriteRule ^(.*)$ /.$1 [R,CO=ROUTEID:route.1:.yourdomain.com]
RewriteCond %{ENV:BALANCER_ROUTE_CHANGED} 1
RewriteCond %{SSL:SSL_CLIENT_S_DN} ^[n-z] [NC]
RewriteRule ^(.*)$ /.$1 [R,CO=ROUTEID:route.2:.yourdomain.com]
<Proxy balancer://lb-service>
BalancerMember ajp://svr1:8009 loadfactor=1 route=1
BalancerMember ajp://svr2:8009 loadfactor=1 route=2
ProxySet stickysession=ROUTEID
</Proxy>
<Location /lookup>
ProxyPass balancer://lb-service/lookup
</Location>
Если это не сработает, то вот план B; просто сопоставляйте DN сертификата клиента каждый раз. Добавление дополнительной нагрузки к каждому запросу, но это не должно быть слишком плохим влиянием на производительность в целом.
<Proxy */lookup>
RewriteEngine On
RewriteCond %{SSL:SSL_CLIENT_S_DN} ^[a-m] [NC]
RewriteRule ^/lookup((?:/.*|))$ ajp://svr1:8009/lookup$1 [P,L]
RewriteCond %{SSL:SSL_CLIENT_S_DN} ^[n-z] [NC]
RewriteRule ^/lookup((?:/.*|))$ ajp://svr2:8009/lookup$1 [P,L]
# This will take care of any other orphan requests (say, those with no client
# cert) - we'll just lump those on server 1; if there's a lot then we can do
# something else to balance randomly (like just leave the current config there)
RewriteRule ^/lookup((?:/.*|))$ ajp://svr1:8009/lookup$1 [P,L]
</Proxy>
У меня есть это соответствие для конечной косой черты после /lookup
чтобы избежать неприятной уязвимости безопасности, когда злоумышленник может попасть в вашу внутреннюю сеть - если это не сработает для вашего приложения, тогда мы можем обойти это.