Назад | Перейти на главную страницу

Балансировка нагрузки на основе сертификата клиента с Apache mod_proxy_ajp и Tomcat

В настоящее время я использую mod_proxy_ajp для загрузки запросов балансировки на несколько серверов Tomcat. Вызывающие абоненты проходят аутентификацию с использованием клиентских сертификатов и ACL. Это работает нормально, звонящие направляются на любой из серверов с одинаковой скоростью. Теперь я хочу предварительно получить и кэшировать данные для каждого пользователя, чтобы каждый сервер Tomcat обслуживал известный набор пользователей. Поэтому я думаю, что было бы хорошо разделить звонящего по алфавиту; Пользователь с именами (CN или DN), начинающимися с A-M, переходит на сервер 1, пользователи с именами, начинающимися с [N-Z], переходят на сервер 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, для приема различных запросов.

У кого-нибудь есть хороший способ сделать это?

Интересная идея для кеширования! Посмотрим, сможем ли мы заставить его работать ...

У меня есть несколько вариантов: один будет более эффективным, но я понятия не имею, сработает ли он, и другой, менее эффективный, но я уверен, что он будет работать нормально.

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

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