Comment limiter le nombre de sessions?

8

J'ai besoin d'un moyen de suivre et de limiter les sessions Web à une application Web. Une "session" est définie de manière lâche comme le seul utilisateur parcourant les pages de ladite application Web. Je pense que cela peut être traduit en:

  • une session est définie comme un tuple <clientIP,vHost>alternativement comme <clientIP,serverIP,serverPort>ou <cookie,vHost>, selon la couche et les données disponibles
  • une session démarre après que l'utilisateur a envoyé des données d'authentification à un URI de connexion défini
  • une session se termine après que l'utilisateur a atteint l'URI de déconnexion défini
  • une session se termine si un délai spécifié a expiré après que le client a demandé le dernier objet

Une fois la limite de session spécifiée atteinte, l'utilisateur suivant doit être dirigé vers une page d'erreur personnalisée. J'ai également besoin d'un moyen de suivre le nombre actuel de sessions à des fins de surveillance et de pouvoir mettre sur liste blanche le serveur de surveillance (qui émet périodiquement des requêtes à la webapp) et l'exempter de la limite.

Avec quoi je peux travailler:

  • RadWare AppDirector où l'application Web a sa propre batterie de serveurs définie et s'exécute en mode proxy inverse
  • Apache 2.2
  • SLES 11 SP2

Je préférerais ne pas impliquer de serveur proxy supplémentaire, mais je le considérerais s'il ne reste aucune autre option.

La raison derrière tout cela est que l'application Web susmentionnée est facilement surchargée et commence à refuser les demandes de manière irrégulière, énervant les utilisateurs qui perdent (généralement) des données d'entrée de formulaire dans le processus. En spécifiant une limite où une condition de surcharge est moins probable, nous espérons créer une condition de défaillance bien définie où les utilisateurs seront invités à revenir plus tard si la charge est susceptible de monter en flèche.

Edit : l'application Web est une implémentation à 3 niveaux, le premier niveau (couche de présentation, implémenté en tant que code CGI dans un Apache vHost) étant plutôt simpliste et apparemment limité à la gestion des erreurs de base et à l'équilibrage de la demande entre les serveurs d'applications. Il n'impose aucune charge significative aux serveurs Web sur lesquels il s'exécute - c'est pourquoi nous l'exécutons en mode de basculement simple (pas d'équilibrage de charge) dans la batterie AppDirector, qui est censé simplifier quelque peu les choses.

Tout ce qui dépasse ce point est fondamentalement une boîte noire pour nous - au niveau des données, nous avons une base de données MSSQL, mais il est presque impossible d'obtenir des informations significatives sur la structure de la table auprès du fournisseur. Les serveurs d'applications sont de source fermée, le fournisseur a utilisé un cadre plutôt complet pour la mise en œuvre, mais semble incapable de répondre à des questions liées au fonctionnement encore moins complexes.

le-wabbit
la source
Pouvez-vous fournir des détails généraux sur l'application Web? Est-ce la même chose sur chaque vHost? Ou n'avez-vous pas fourni les détails, car vous souhaitez peut-être une solution indépendante de l'application Web? Est-ce une application Web propriétaire?
lsmooth
Une fois la connexion fermée, en raison de l'inactivité, quelqu'un peut-il reprendre une session à l'aide du cookie de session (si le délai d'expiration de l'application n'a pas été atteint)?
manjiki
@jijix c'est un cas frontière qui est considéré comme assez rare pour ne pas s'en soucier s'il ajoute à la complexité de l'implémentation. En dehors de cela, je pense qu'il pourrait mieux être spécifié comme «rétablir la session sans vérifier par rapport aux limites de session» .
le-wabbit
Je le fais habituellement en comptant les URL "typiques" dans le httpd-access-log. Quel est le nombre approximatif de concurrents dont nous parlons ici? Peut-être qu'une limite de thread peut aider ici sur le côté httpd?
Nils
Je sais que HAProxy peut limiter le nombre de connexions. Mais vous demandez quelque chose d'un peu différent ...
Matt

Réponses:

5

Le problème que vous essayez en fin de compte de résoudre concerne la capacité de l'application - et c'est là que vous devriez résoudre le problème. Aucun des composants que vous mentionnez n'a quoi que ce soit à voir avec la gestion de session pour une application HTTP.

Il y a quelques astuces que vous pouvez appliquer avec le module récent dans iptables ou en utilisant fail2ban dans le sens inverse de l'objectif pour lequel il a été conçu - mais ces deux nécessitent une compréhension très détaillée des outils et du domaine du problème. Vous pouvez mettre en œuvre le contrôle d'accès au niveau de ces composants , mais conduit par des informations d'état de l'application publiée sur le nombre de sessions.

J'ai également besoin d'un moyen de suivre le nombre actuel de sessions à des fins de surveillance

En supposant, pour le moment, que l'application est une boîte noire sans possibilité de modification / instrumentation (ce qui est hautement improbable), vous pouvez obtenir ces informations de vos journaux apache en incluant le cookie de session - filtrez ou supprimez les journaux pour maintenir un liste des cookies actifs - et supprimez les entrées de la liste lorsqu'elles coïncident avec l'URL de déconnexion ou n'ont pas été vues pour le TTL.

symcbean
la source
Oubliez mes questions ci-dessus, c'est exactement ce que je voulais en venir.
lsmooth
A vous sûr que RadWare AppDirector ne peut pas résoudre ce problème au moins en traitement prolongé? - le contrôle de session est demandé pour éviter une surcharge de nœud qui peut être obtenue par d'autres moyens.
Veniamin
Non , je ne suis pas sûr - comme je l' ai dit ci - dessus , vous pouvez truquer la gestion des sessions ailleurs dans la pile - mais son beaucoup, BEAUCOUP plus difficile de le faire au mauvais endroit. Il est beaucoup plus facile de résoudre le problème là où il se produit.
symcbean
Si vous considérez que le bon endroit pour la gestion de session est un module intégré dans l'application ou ailleurs sur une base par nœud, il n'est pas clair comment le faire fonctionner avec l'équilibrage de charge au niveau AppDirector.
Veniamin
L'idée d'utiliser les journaux apache pour le suivi de session a un certain mérite. Pour le reste - vous savez que je n'ai pas écrit l'application et que j'ai peu (voire pas) d'influence sur le développement futur. Ce n'était pas ma décision de le mettre en place, mon autorité est limitée à l'infrastructure dans laquelle il s'exécute. prendre beaucoup de temps. Donc mon travail actuel est de trouver un mode de fonctionnement "aussi bon que possible".
le-wabbit
1

Ce n'est pas exactement ce que vous demandez, mais j'ai déjà fait ce qui suit avec les équilibreurs de charge F5:

  • Comptez le nombre de demandes de publication sur la page de connexion.
  • Retarder les utilisateurs si les connexions par seconde dépassent une première limite
  • Envoyer les utilisateurs vers une page de maintenance si les connexions par seconde dépassent une deuxième limite

Le site Web étant parfois soumis à une forte charge (courses de chevaux), cela a aidé.


la source
Merci pour l'idée, je dois vérifier avec nos gars AppDirector si nous pourrions implémenter quelque chose de similaire.
le-wabbit
@ syneticon-dj: si vous devez vérifier si vous pouvez implémenter quelque chose comme ça (qui ne résout pas réellement le problème, BTW) et que vous ne pouvez pas réparer l'application, alors vous êtes vraiment dans un tas de problèmes. À la réflexion, je peux penser à au moins 2 autres façons de résoudre le problème - mais elles sont à la fois techniquement exigeantes - et mises en œuvre de manière incorrecte aggraveront le problème plutôt que de l'améliorer. Vous avez besoin de plus d'aide que vous n'en aurez ici.
symcbean
@symcbean Rien que je puisse faire ne résoudra le problème, qui est le manque de qualification au sein du personnel de développement et de support du vendeur et la décision prise d'utiliser cette application dans l'ignorance de celle-ci. Si vous avez d'autres idées, je serai heureux d'en entendre parler. La «demande» n'est pas un problème tant qu'elle n'ajoute pas à la complexité des opérations quotidiennes.
le-wabbit
1

Ce problème peut être résolu à la fois en utilisant RadWare AppDirector et (pour être complet) probablement également en utilisant Apache mod_security selon votre excellente conclusion dans le commentaire ci-dessous.

Pour une solution AppDirector, je pense qu'il est possible de créer deux batteries de serveurs mappant vers le (s) même (s) serveur (s) backend. Ces exploitations peuvent appliquer différents critères et conditions d'exploitation. Une batterie serait la "valeur par défaut" et l'autre répondrait aux URI: s que vous définissez comme étant "une session". Ce dernier obtiendrait une limite au nombre de sessions qu'il accepte dans l'équilibreur de charge.

Je vais désormais remplacer votre terme "session" par "connecté" pour deux raisons:

  • Il évite toute ambiguïté car il définit clairement l'état souhaité dans lequel l'utilisateur est authentifié.
  • Le Guide de l'utilisateur et l'interface graphique AppDirector redéfinit le terme «connexion» pour avoir une signification à toutes fins pratiques identique à «session», voir ci-dessous. Cela ajoute une confusion que nous essayons d'éviter.

Il est également possible d'afficher une page désolée si la batterie de serveurs «connectée» a atteint la limite de connexion choisie.

Avant de commencer, je dois clairement déclarer que je n'ai aucune expérience de fonctionnement du produit AppDirector, mais que j'administre quotidiennement un équilibreur de charge concurrent et légèrement moins avancé. Le produit que j'utilise peut faire ce scénario dès le départ. J'ai trouvé des informations dans le Guide de l'utilisateur AppDirector et la documentation en ligne disponible qui suggère que la même chose est vraie pour AppDirector. Cependant, bien que les concepts soient similaires, la terminologie est différente. Je fais simplement un acte quand à Rome en ce qui concerne le libellé, en espérant avoir les choses correctes sans être trop évidemment un crétin ignorant.

Le plus grand obstacle était d'avoir accès à un manuel, qui n'est disponible que si l'on est un client actif. Grâce à quelques recherches sur Google, il a été possible de trouver une ancienne version qui, je l'espère, n'est pas trop obsolète, j'ai également trouvé quelques articles de la base de connaissances et ce lien: Radware AppDirector - Configuration: Application de base .

Voici une ébauche de solution, telle qu'interprétée principalement par le guide de l'utilisateur:

L'entrée du client dans l'équilibreur de charge se fait via un VIP qui est utilisé pour connecter à la fois les sessions "par défaut" et les "sessions connectées". Ceci est réalisé grâce à une politique L4 selon p.99 dans le Guide de l'utilisateur:

"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.

La politique L4 peut être liée aux politiques L7 qui sont utilisées pour sélectionner une batterie de serveurs appropriée. Le processus de stratégie L7 est décrit ainsi dans le Guide de l'utilisateur 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."

Les méthodes disponibles pour définir un comportement L7 sont décrites à la p.106, dont vous pouvez choisir une méthode appropriée pour choisir le routage vers votre batterie de serveurs "connectée" plutôt que vers la batterie de serveurs "par défaut":

"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."

Comme le montre le lien de l' application de base , on pourrait par exemple créer une stratégie L7 évaluant les modèles d'URI pour le routage vers différentes batteries. Les modèles d'URI constitués «^ / login? = True» et «^ / login» peuvent être acheminés vers votre batterie de serveurs «connectée». Le modèle composé '^ / logout' (et tous les autres URI: s) pourrait également être routé vers une batterie de serveurs "par défaut".

Une batterie de serveurs est définie par le Guide de l'utilisateur p.121 ainsi: "Une batterie de serveurs AppDirector est un groupe de serveurs en réseau qui fournissent le même service [...] Un serveur qui fournit plusieurs services peut être utilisé dans plusieurs batteries de serveurs."

Un serveur est en outre différencié en séparant la définition d'un serveur principal en deux couches, la couche objet «Physical Server» qui représente l'adresse IP d'un serveur et la couche objet «Farm Server» qui représente les services exécutés sur un ou plusieurs serveurs physiques. .

Selon le «Guide de l'utilisateur AppDirector», la limitation de session sur une batterie de serveurs peut être effectuée pour chaque objet Farm Server défini pour une batterie de serveurs (ainsi que par d'autres moyens) en plus de chaque objet Physical Server. Ceci est décrit entre autres à la 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."

La table client et son «mode régulier» sont définis à la 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"

Dans une capture d'écran d'une fenêtre de définition de serveur sur la page Application de base , la zone de limite de connexion au serveur apparaît juste à côté de la zone de limite de bande passante.

Donc, un peu en fonction de la configuration, mais pour les besoins de cette réponse, une «connexion» telle que définie via la table client et une «session» telle que définie par vous finissent essentiellement par être la même chose. Et une limite à cet effet peut être imposée par objet serveur dans une batterie de serveurs.

Comme AppDirector fait la différence entre les serveurs physiques et les serveurs de batterie de serveurs, il serait possible de définir deux serveurs de batterie de serveurs mappant à votre objet serveur physique Apache, l'un ayant une limite de connexion faible.

Cependant, Apache doit également répondre aux appels des deux objets serveur de batterie de serveurs, par exemple en étant appelé sur deux ports ou adresses IP distincts - un étant utilisé par chaque combo (batterie de serveurs / batterie de serveurs). La question devient alors: êtes-vous capable de définir deux points d'entrée de serveur d'applications? c'est-à-dire êtes-vous en mesure d'équiper votre application frontale Apache (/ vhost?) pour répondre sur deux ports ou adresses IP (une par batterie)? C'est à travers un peu de devinettes car je ne souhaite pas passer trop de temps avec le manuel, mais je suis sûr que vous pourriez résoudre ce problème assez élégamment en regardant l'interface graphique AppDirector et Apache.

La définition de la limite de connexion est un peu bizarre. Depuis les serveurs physiques, limite de connexion 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."

Vous devez donc définir une limite de connexion très élevée (avec une large marge au nombre maximum possible via votre base d'utilisateurs) pour le serveur de ferme "par défaut" sans restriction, et définir la limite de connexion pour le serveur de ferme "connecté" comme aussi bas que vous devez. La définition de serveur physique devrait avoir la somme des deux comme limite de connexion, comme condition préalable à l'activation de la limite de session souhaitée.


Vous avez également cette exigence dans votre question:

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

C'est ce qu'on appelle une «page sans service HTTP» dans le Guide de l'utilisateur, 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.

Pour la partie suivi je n'ai pas fait de recherche approfondie mais voici ce que je pense:

track the current number of sessions for monitoring purposes

AppDirector semble avoir des MIB. Probablement une douleur pour trouver le bon OID comme il est habituellement, mais vous pouvez probablement le snmp à votre outil de choix.

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

Celui-ci pourrait nécessiter une réflexion créative. En supposant que AppDirector n'inclut pas de modèle pour cela dès la sortie de la boîte, que diriez-vous:

  • Les URI en dehors de la batterie de serveurs "connecté" ne seraient pas affectés par la limite de session. Surveillez donc, c'est le même serveur (s) backend de toute façon.
  • Utilisez plutôt les contrôles de santé AppDirector, ils ne compteront probablement pas dans la limite de session que vous imposez. Trouvez un moyen de transmettre des alertes à votre serveur de surveillance :-)
  • Configurez une troisième batterie de serveurs, à travers laquelle vous passez des tests de santé. Désordonné, mais cela fonctionnerait.
ErikE
la source
1
Jusqu'à présent, j'ai trouvé que le module mod_security2 est capable de gérer la session d'une manière qui ressemble beaucoup à ce que j'ai spécifié - secure.jwall.org/blog/2009/01/08/1231374852674.html . Je vais faire quelques recherches supplémentaires sur votre idée de 2 fermes, si une telle mise en œuvre était possible, cela simplifierait certainement les choses.
le-wabbit
Réponse du support technique Radware: "Dans AD, nous ne pouvons limiter la bande passante par batterie de serveurs. [...] [Une] méthode pour limiter le nombre total de sessions sur une batterie de serveurs n'est actuellement pas disponible." Il s'agit donc de mod_security.
le-wabbit
Ok, c'était inattendu. Sauf si j'ai raté quelque chose, je pense toujours que la fermeture de la ferme par un bilan de santé défaillant serait une solution plus propre. Votre conclusion sur mod_security est très intéressante malgré tout.
ErikE
Bien que le support ait été un peu étroit dans l'interprétation de la question, il semble qu'une limite de session au niveau du serveur dans AppDirector soit possible (à laquelle il y a certainement une certaine logique). J'ai googlé plusieurs liens, en voici un: kb.radware.com/questions/2829/…
ErikE
L'article de Radware KB concerne LinkProof - un accélérateur WAN. Je n'ai aucune idée de quel logiciel il exécute et si des installations similaires existeraient pour AppDirector. BTW: code de gestion de session sûrement est une partie de l'ensemble des fonctionnalités de AppDirector - il dispose d' une table de session qui ressemble exactement ce que j'attendre à regarder. Mais apparemment, il n'y a aucun moyen d'imposer une limite sur le nombre de sessions - juste sur les connexions. Le maximum que je puisse en tirer est de limiter le nombre de visites sur une page donnée (par exemple la page de connexion) par unité de temps, comme "l'autre" suggéra Eric.
le-wabbit
0

Si AppDirector ne peut pas vous aider, voici une autre approche qui nécessitera un peu de codage. J'attaquerais le problème comme suit:

  • En boucle, continuez à lire le fichier journal d'apache (et rouvrez-le sur logrotate)
  • Lorsqu'un utilisateur visite une page (et pas seulement une connexion), ajoutez-le à une liste blanche iptables
  • Lorsqu'un utilisateur se déconnecte ou après une inactivité (alors gardez les minuteurs pour les sessions actives!), Supprimez-les de la liste blanche
  • Si la liste blanche est pleine, redirigez tout le trafic non mis en liste blanche vers un port spécial
  • Exécutez un vhost simple sur ce port avec votre erreur personnalisée

La représentation graphique du nombre de sessions devient aussi simple que la représentation graphique de la longueur de la chaîne iptables. Le serveur de surveillance peut simplement être toujours sur liste blanche.

Dennis Kaarsemaker
la source