Балансировка нагрузки на основе сертификата клиента с помощью 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 чтобы избежать неприятной уязвимости безопасности, когда злоумышленник может попасть в вашу внутреннюю сеть - если это не сработает для вашего приложения, тогда мы можем обойти это.

Другие вопросы по тегам