Como limitar o número de sessões?

8

Preciso de uma maneira de acompanhar e limitar as sessões da web a um aplicativo da web. Uma "sessão" é definida livremente como o único usuário navegando nas páginas do referido aplicativo da web. Eu acho que pode ser traduzido para:

  • uma sessão é definida como uma tupla <clientIP,vHost>alternativamente como <clientIP,serverIP,serverPort>ou <cookie,vHost>, dependendo da camada e dos dados disponíveis
  • uma sessão inicia após o usuário enviar dados de autenticação para um URI de login definido
  • uma sessão termina após o usuário acessar o URI de logout definido
  • uma sessão termina se um tempo limite especificado expirar após o cliente solicitar o último objeto

Depois que o limite de sessão especificado for atingido, o próximo usuário deverá ser direcionado para uma página de erro personalizada. Também preciso de uma maneira de rastrear o número atual de sessões para fins de monitoramento e a capacidade de colocar na lista de permissões o servidor de monitoramento (que está emitindo consultas para o aplicativo da Web periodicamente) e isentá-lo do limite.

Com o que posso trabalhar:

  • RadWare AppDirector em que o aplicativo Web possui um próprio farm definido e está sendo executado no modo de proxy reverso
  • Apache 2.2
  • SLES 11 SP2

Eu preferiria não envolver um servidor proxy adicional, embora o considere se nenhuma outra opção permanecer.

A lógica por trás de tudo isso é que o aplicativo da Web mencionado acima é facilmente sobrecarregado e começa a negar solicitações erraticamente, irritando os usuários que geralmente perdem dados de entrada de formulário no processo. Ao especificar um limite em que uma condição de sobrecarga é menos provável, esperamos criar uma condição de falha bem definida, na qual os usuários serão solicitados a retornar mais tarde se for provável que a carga ocorra.

Editar : o aplicativo da web é uma implementação em três camadas, com a primeira camada (camada de apresentação, implementada como código CGI em um Apache vHost) bastante simplista e aparentemente limitada ao tratamento básico de erros e ao balanceamento de carga entre os servidores de aplicativos. Ele não impõe nenhuma carga significativa nos servidores Web em que é executado - é por isso que o executamos no mero modo de failover (sem balanceamento de carga) no farm do AppDirector, o que deve simplificar um pouco as coisas.

Tudo além desse ponto é basicamente uma caixa preta para nós - na camada de dados, temos um banco de dados MSSQL, mas é quase impossível obter do fornecedor qualquer informação significativa sobre a estrutura da tabela. Os servidores de aplicativos são de código fechado, o fornecedor usou uma estrutura bastante abrangente para a implementação, mas parece incapaz de responder a perguntas ainda menos complexas relacionadas à operação.

o wabbit
fonte
Você pode fornecer detalhes gerais sobre o aplicativo Web? É o mesmo em cada vHost? Ou você não forneceu os detalhes, porque talvez você queira uma solução independente do aplicativo Web? É um aplicativo da web proprietário?
Lsmooth # 28/13
Depois que a conexão é fechada, devido à inatividade, alguém pode retomar uma sessão usando o cookie da sessão (se o tempo limite do aplicativo não tiver sido atingido)?
manjiki
@jijix, este é um caso de fronteira que é considerado raro o suficiente para não se preocupar com isso, se aumentar a complexidade da implementação. Fora isso, acho que seria melhor especificar como "reinstalar a sessão sem verificar os limites da sessão" .
the-wabbit
Eu costumo fazer isso contando URLs "típicos" no httpd-access-log. Qual é o número aproximado e simultâneo de que estamos falando aqui? Talvez um limite de threads possa ajudar aqui no lado do httpd?
Nils
Eu sei que o HAProxy pode limitar o número de conexões. Mas você está pedindo algo um pouco diferente ...
Matt

Respostas:

5

O problema que você está tentando resolver está na capacidade do aplicativo - e é aí que você deve resolver o problema. Nenhum dos componentes que você mencionou tem algo a ver com o gerenciamento de sessões para um aplicativo HTTP.

Existem alguns truques que você pode aplicar com o módulo recente no iptables ou usando o fail2ban da maneira oposta à finalidade para a qual foi projetado - mas esses dois exigem uma compreensão muito detalhada das ferramentas e do domínio do problema. Você pode implementar o controle de acesso no nível desses componentes, mas orientado pelas informações publicadas do estado do aplicativo no número de sessões.

Também preciso de uma maneira de acompanhar o número atual de sessões para fins de monitoramento

Supondo, por enquanto, que o aplicativo seja uma caixa preta sem escopo para modificação / instrumentação (o que é altamente improvável), você pode obter essas informações dos logs do apache incluindo o cookie da sessão - filtre ou siga os logs para manter um lista de cookies ativos - e remova as entradas da lista quando coincidirem com o URL de logout ou não foram vistas para o TTL.

symcbean
fonte
Esqueça minhas perguntas acima, é exatamente isso que eu estava falando.
Lsmooth # 29/13
Você tem certeza de que o RadWare AppDirector não pode resolver esse problema pelo menos em tratamento prolongado? - o controle da sessão é solicitado para evitar a sobrecarga do nó que pode ser alcançada por outros meios.
Veniamin 29/11
Não, eu não tenho certeza - como eu disse acima, você pode falsificar o gerenciamento de sessões em outros lugares da pilha - mas é muito, muito mais difícil fazê-lo no lugar errado. Corrigir o problema onde o problema está ocorrendo é muito mais fácil.
symcbean
Se você considerar o local certo para o gerenciamento de sessões, é um módulo integrado no aplicativo ou em outro local, por nó, que não está claro como fazê-lo funcionar junto com o balanceamento de carga no nível do AppDirector.
Veniamin 29/11
A idéia de usar os logs do apache para rastreamento de sessão tem algum mérito. Quanto ao resto - você sabe que não escrevi o aplicativo e tenho pouca (se houver) influência sobre o desenvolvimento futuro. Não foi minha decisão colocá-lo em prática, minha autoridade é limitada à infraestrutura em que ele é executado. O ponto em que o aplicativo é abaixo do ideal foi esclarecido para o gerenciamento, mas mesmo que isso pudesse mudar alguma coisa, qualquer alteração seria levar uma quantidade significativa de tempo. Portanto, meu trabalho atual é encontrar um modo de operação "o melhor possível".
the-wabbit
1

Não é exatamente isso que você está pedindo, mas eu já fiz o seguinte com os balanceadores de carga F5:

  • Conte o número de solicitações de postagem na página de login.
  • Atrasar os usuários se logins por segundo estiver acima do primeiro limite
  • Envie os usuários para uma página de manutenção se os logins por segundo estiverem acima de um segundo limite

Como o site às vezes estava sob carga pesada (corridas de cavalos), isso ajudou.


fonte
Obrigado pela idéia, preciso verificar com o pessoal do AppDirector se podemos implementar algo semelhante.
precisa
@ syneticon-dj: se você precisa verificar se pode implementar algo assim (o que realmente não resolve o problema, BTW) e você não pode consertar o aplicativo, está realmente com um monte de problemas. Refletindo, posso pensar em pelo menos mais duas maneiras de resolver o problema - mas elas são tecnicamente exigentes - e implementadas incorretamente tornarão o problema pior e não melhor. Você precisa de mais ajuda do que aqui.
symcbean
@symcbean Nada que eu possa fazer resolverá o problema, que é a falta de qualificação na equipe de desenvolvimento e suporte do fornecedor e uma decisão tomada para usar esse aplicativo por ignorá-lo. Se você tiver outras idéias, ficarei feliz em ouvi-las. "Demandar" não é um problema, desde que não aumente a complexidade nas operações do dia-a-dia.
the-wabbit
1

Esse problema é solucionável usando o RadWare AppDirector e (para ser completo) provavelmente também usando o Apache mod_security conforme sua excelente descoberta no comentário abaixo.

Para uma solução AppDirector, acredito que é possível criar dois farms mapeados para os mesmos servidores back-end. Esses farms podem ter critérios e condições operacionais diferentes aplicados a eles. Um farm seria o "padrão" e o outro responderia aos URI: s que você define como sendo "uma sessão". O último obteria um limite para a quantidade de sessões que ele aceita no balanceador de carga.

A partir de agora, substituirei o termo "sessão" por "logado" por dois motivos:

  • Isso evita ambiguidade, pois define claramente o estado desejado no qual o usuário é autenticado.
  • O AppDirector User Guide e GUI redefinem o termo "conexão" para ter um significado para todos os fins práticos idênticos a "sessão", veja abaixo. Isso adiciona confusão que tentamos evitar.

Também é possível mostrar uma página de desculpas se o farm "logado" atingiu o limite de conexão escolhido.

Antes de começar, como devo declarar claramente que não tenho experiência operacional com o produto AppDirector, mas administro diariamente um balanceador de carga concorrente e um pouco menos avançado. O produto que eu uso pode fazer esse cenário imediatamente. Encontrei informações no Guia do usuário do AppDirector e qual documentação on-line está disponível, o que sugere que o mesmo se aplica ao AppDirector. No entanto, embora os conceitos sejam semelhantes, a terminologia é diferente. Estou simplesmente fazendo um ato quando em Roma com relação à redação, esperando acertar bastante sem ser obviamente um idiota sem noção.

O maior obstáculo foi o acesso a um manual, que não é disponibilizado, a menos que se seja um cliente ativo. Através de algumas pesquisas no Google, foi possível encontrar uma versão antiga que, espero, não esteja muito desatualizada, também encontrei alguns artigos da base de conhecimento e este link: Radware AppDirector - Configuração: aplicativo básico .

Aqui está um rascunho da solução, interpretado principalmente pelo Guia do Usuário:

A entrada do cliente no balanceador de carga é feita por meio de um VIP, usado para conectar as sessões "padrão" e as "sessões de logon". Isso é alcançado através de uma política L4, conforme a p.99 no Guia do Usuário:

"When AppDirector receives the first packet of a session destined to a
Virtual IP address, it searches for a Layer 4 Policy that matches the
Layer 4 Protocol, Destination port, Source IP, etc. Then, based on this
information, AppDirector selects the farm allocated to this service and
the best server for the task from that farm, and forwards the packet to
that server.

A política L4 pode ser vinculada às políticas L7, usadas para selecionar um farm adequado. O processo da política L7 é descrito assim no Guia do Usuário p.104:

"The Layer 7 content aware decision making mechanism allows you to have
a single point of entry to the site, and provides differentiated service
for different user groups.

A Layer 7 decision is made using a mechanism called Delayed Binding.
When Delayed Binding is used, AppDirector first performs a TCP handshake
with the client to receive the HTTP request. AppDirector parses the HTTP
request’s data, usually HTTP headers, and performs the load balancing
decision. Only after that, does AppDirector select a farm and a server.
Lastly, AppDirector initiates a TCP handshake with the server and
forwards the traffic to it
[...]
When Layer 7 Policies are used, farm selection is based on matching the
request data with a list of Layer 7 Policies defining the Layer 7
parameters differentiating the service. The process of server selection
within the farm can also be content-based, using a third Layer 7
parameter."

Os métodos disponíveis para definir um comportamento L7 estão descritos na p.106, dos quais você pode escolher um método adequado para escolher o roteamento para o seu farm "logado" em vez do farm "padrão":

"Methods are the basic building blocks for Layer 7 service selection.
They define content by which traffic is differentiated. You can use
the same Method to select one or more services. The following Method
Types are available:

- URL: Looks for a specified host name and/or path in the HTTP request.
- File Type: Looks for a specified File Type in the HTTP request.
- Header Field: Looks for a specified Header Field in the HTTP request.
- Cookie: Looks for a specified Cookie in the HTTP request.
- Regular Expression: Looks for a regular expression anywhere in the
HTTP request. AppDirector supports Posix 1002.3 regular expressions;
the string can be up to 80 characters.
- Text: Looks for a text string anywhere in the HTTP request."

Como visto no link do aplicativo básico , pode-se, por exemplo, criar uma política L7 que avalie os padrões de URI para rotear para diferentes farms. Os padrões de URI inventados '^ / login? = True' e '^ / login' podem ser roteados para o farm "logado". O padrão criado '^ / logout' (e todos os outros URI: s) também pode ser roteado para um farm "padrão".

Um farm é definido pelo Guia do Usuário p.121, assim: "Um farm do AppDirector é um grupo de servidores em rede que fornecem o mesmo serviço [...] Um servidor que fornece vários serviços pode ser usado em vários farms".

Um servidor é ainda mais diferenciado ao separar a definição de servidor backend em duas camadas, a camada de objeto 'Physical Server', que representa o endereço IP de um servidor, e a camada de objeto 'Farm Server', que representa serviços em execução em um ou mais servidores físicos .

A limitação de sessão em um farm pode, de acordo com o 'Guia do Usuário do AppDirector', ser realizada por cada objeto do Servidor do Farm definido para um farm (e por outros meios), além do objeto do Servidor Físico. Isso é descrito entre outros lugares na p.137:

"The Connection Limit is the maximum number of users that can be directed
to a server for a service provided by the farm. The number of users allowed
depends on the Sessions mode selected because it determines the number of
active entries in the Client Table for sessions destined to the specific server.

When the Entry Per Session or Server Per Session modes are selected, the number
of active entries destined to the same server is higher than in the Regular
mode (see Regular, page 153).

When the Regular mode is selected, all requests from a single client IP destined
to the same server are reflected by a single entry in the Client Table (see
Client Table Views, page 164).

The default value for the Connection Limit parameter is 0. When it is configured
to 0, it is disabled for this server and there is no user number limit."

A tabela do cliente e seu 'modo regular' estão definidos na p.153:

"The Layer 3 Client Table is always used when Entry Per Session is used.
AppDirector uses the Layer 3 Client Table to ensure Layer 3 persistency.

This table contains information about the server selected for each client
(Source IP address) in each farm, and it allows AppDirector to select a
server for a new session.
[...]
In the Regular mode, AppDirector maintains Layer 3 persistency. In this mode,
each entry is identified by the following parameters:
• Layer 4 Policy VIP Address
• Client IP Address
• Destination TCP/UDP Port Used from the Client to the Server"

Em uma captura de tela de uma janela de definição de servidor na página Aplicativo Básico , a caixa de limite de conexão do servidor é vista ao lado da caixa de limite de largura de banda.

Então, dependendo da configuração, mas para os fins desta resposta, uma 'conexão' conforme definida na Tabela do Cliente e uma 'sessão' conforme definida por você basicamente acabam sendo a mesma coisa. E um limite para esse efeito pode ser imposto por objeto de servidor em um farm.

Como o AppDirector diferencia entre servidores físicos e servidores de farm, seria possível definir dois servidores de farm mapeados para o objeto de servidor físico do Apache, um com um limite de conexão baixo.

No entanto, o Apache também precisa atender chamadas de ambos os objetos do servidor do farm, por exemplo, sendo chamado em duas portas ou endereços IP separados - um sendo usado por cada combinação (servidor do farm / farm). A questão então se torna: você pode definir dois pontos de entrada do servidor de aplicativos? ou seja, você pode equipar seu aplicativo front end Apache (/ vhost?) para responder em duas portas ou endereços IP (um por farm)? Isso é um pouco de trabalho de adivinhação, já que não desejo gastar muito tempo com o manual, mas tenho certeza de que você poderia resolver isso com bastante elegância ao realmente olhar a GUI do AppDirector e o Apache.

Definir o limite de conexão é um pouco peculiar. De servidores físicos, limite de conexão p.140:

"Connection Limit

Maximum number of Client Table entries that can run simultaneously on 
the physical server. This depends on the farm’s Sessions mode (see 
Sessions Modes, page 150). When the limit is reached, new requests are 
no longer directed to this server. All open sessions are continued.

When the Connection Limit parameter is configured to 0 (default), this 
mechanism is disabled for this physical server and there is no user 
number limit.

Note: When configuring the physical server, ensure that the Connection 
Limit in the farm servers with the same Server Name is lower than or 
equal to the Connection Limit in the physical server. Total number of 
active sessions that run simultaneously on the farm servers must not 
be higher than the Connection Limit value defined on the physical server."

Portanto, seria necessário definir um limite de conexão muito alto (com uma ampla margem para o número máximo possível por meio de sua base de usuários) para o servidor de farm irrestrito "padrão" e definir o limite de conexão para o servidor de farm "conectado" como baixo como você precisa. A definição do servidor físico precisaria ter a soma dos dois como seu Limite de conexão, como condição prévia para ativar o limite de sessão desejado.


Você também tem este requisito em sua pergunta:

After the specified session limit has been reached, the next user should be
directed to a custom error page.

Isso é chamado de 'Nenhuma Página de Serviço HTTP' no Guia do Usuário, p.134:

When all servers belonging to a farm cannot be used for a specific
session, AppDirector can reply to a Web request (destined to port 80)
with a simple Web page, indicating that the service is currently not
available. Servers that cannot be used for a session include servers
in Not In Service or in No New Sessions mode. No HTTP Service Page is
configured for each farm. Each Web page is limited to 1K of HTML code.

Para a parte de monitoramento, não fiz uma pesquisa completa, mas eis o que penso:

track the current number of sessions for monitoring purposes

O AppDirector parece ter MIBs. Provavelmente, é difícil encontrar o OID certo, como normalmente é, mas é possível encaixá-lo na sua ferramenta de escolha.

whitelist the monitoring server (which is issuing queries to the webapp
periodically) and exempt it from the limit.

Este poderia exigir algum pensamento criativo. Supondo que o AppDirector não inclua um modelo para isso imediatamente, que tal:

  • URIs fora do farm "conectado" não seriam afetados pelo limite de sessões. Portanto, monitore, é o mesmo servidor de qualquer maneira.
  • Use as verificações de integridade do AppDirector; elas provavelmente não serão contabilizadas no limite de sessões que você impõe. Encontre uma maneira de passar alertas para o servidor de monitoramento :-)
  • Configure um terceiro farm, através do qual você passa nas verificações de saúde. Confuso, mas funcionaria.
ErikE
fonte
1
Até agora, descobri que o módulo mod_security2 é capaz de lidar com a sessão de maneira muito semelhante à especificada - secure.jwall.org/blog/2009/01/08/1231374852674.html . Vou fazer mais algumas pesquisas sobre sua ideia de 2 fazendas, se tal implementação fosse possível, certamente simplificaria as coisas.
The-wabbit 4/13
Resposta do suporte técnico da Radware: "No AD, só podemos limitar a largura de banda por farm. [...] [A] O método para limitar o número total de sessões em um farm não está disponível no momento". Então é mod_security então.
the-wabbit
Ok, isso foi inesperado. A menos que eu tenha perdido alguma coisa, ainda acho que fechar a fazenda através de uma verificação de saúde com falha seria uma solução mais limpa. Sua descoberta sobre mod_security é muito interessante, independentemente.
ErikE
Possivelmente, embora o suporte tenha sido um pouco restrito na interpretação da pergunta, parece que é possível um limite de sessão no nível do servidor no AppDirector (para o qual certamente há alguma lógica). Eu pesquisei vários links no Google, aqui está um: kb.radware.com/questions/2829/…
ErikE
O artigo da Radware KB é sobre o LinkProof - um acelerador de WAN. Não tenho idéia de qual software está sendo executado e se existiriam recursos semelhantes para o AppDirector. BTW: O código de manipulação de sessões certamente faz parte do conjunto de recursos do AppDirector - ele possui uma tabela de sessões com a aparência exata do que eu esperaria. Mas, aparentemente, não há como impor um limite ao número de sessões - apenas às conexões. O máximo que pude tirar disso é limitar o número de acessos em uma determinada página (por exemplo, a página de login) por unidade de tempo, como "o outro" Eric sugeriu.
the-wabbit
0

Se o AppDirector não puder ajudá-lo, aqui está outra abordagem que exigirá um pouco de codificação. Eu resolveria o problema da seguinte maneira:

  • Em um loop, continue lendo o arquivo de log do apache (e reabra-o no logrotate)
  • Quando um usuário visitar qualquer página (não apenas o login), adicione-a a uma lista de permissões do iptables
  • Quando um usuário efetua logout ou após inatividade (mantenha os cronômetros das sessões ativas!), Remova-os da lista de permissões
  • Se a lista de permissões estiver cheia, redirecione todo o tráfego que não estiver na lista de permissões para uma porta especial
  • Execute um vhost simples nessa porta com seu erro personalizado

Representar graficamente o número de sessões se torna tão simples quanto representar graficamente o comprimento da cadeia iptables. O servidor de monitoramento pode simplesmente estar sempre na lista de permissões.

Dennis Kaarsemaker
fonte