¿Cómo limitar el número de sesiones?


8

Necesito una forma de rastrear y limitar las sesiones web a una aplicación web. Una "sesión" se define libremente como el usuario único que navega por las páginas de dicha aplicación web. Creo que se puede traducir a:

  • una sesión se define como una tupla o <clientIP,vHost>como , dependiendo de la capa y los datos disponibles<clientIP,serverIP,serverPort><cookie,vHost>
  • una sesión comienza después de que el usuario haya enviado datos de autenticación a un URI de inicio de sesión definido
  • una sesión finaliza después de que el usuario haya alcanzado el URI de cierre de sesión definido
  • una sesión finaliza si un tiempo de espera especificado ha expirado después de que el cliente haya solicitado el último objeto

Una vez alcanzado el límite de sesión especificado, el siguiente usuario debe ser dirigido a una página de error personalizada. También necesito una forma de rastrear el número actual de sesiones para fines de monitoreo y la capacidad de incluir en la lista blanca el servidor de monitoreo (que está emitiendo consultas a la aplicación web periódicamente) y eximirlo del límite.

Con qué puedo trabajar:

  • RadWare AppDirector donde la aplicación web tiene una granja definida y se ejecuta en modo proxy inverso
  • Apache 2.2
  • SLES 11 SP2

Preferiría no involucrar un servidor proxy adicional, aunque lo consideraría si no quedan otras opciones.

La razón detrás de todo esto es que la aplicación web mencionada anteriormente se sobrecarga fácilmente y comienza a rechazar solicitudes de forma errática, molestando a los usuarios que trabajan (por lo general) pierden datos de ingreso de formularios en el proceso. Al especificar un límite en el que es menos probable una condición de sobrecarga, esperamos crear una condición de falla bien definida en la que a los usuarios se les diga que regresen más tarde si es probable que la carga aumente.

Editar : la aplicación web es una implementación de 3 niveles con el primer nivel (capa de presentación, implementado como código CGI en un Apache vHost) que es bastante simplista y aparentemente limitado al manejo de errores básicos y al equilibrio de carga de solicitudes entre los servidores de aplicaciones. No impone ninguna carga significativa en los servidores web en los que se ejecuta, es por eso que lo estamos ejecutando en modo de conmutación por error simple (sin equilibrio de carga) en la granja AppDirector, que se supone que simplifica las cosas.

Todo lo que está más allá de este punto es básicamente un cuadro negro para nosotros: en el nivel de datos tenemos una base de datos MSSQL, pero es casi imposible obtener información significativa sobre la estructura de la tabla del proveedor. Los servidores de aplicaciones son de código cerrado, el proveedor ha utilizado un marco bastante completo para la implementación, pero parece incapaz de responder incluso preguntas menos complejas relacionadas con la operación.


¿Puede proporcionar detalles generales sobre la aplicación web? ¿Es lo mismo en cada vHost? ¿O no proporcionó los detalles, porque tal vez desee una solución que sea independiente de la aplicación web? ¿Es una aplicación web propietaria?
lsmooth

Después de cerrar la conexión, debido a la inactividad, ¿alguien puede reanudar una sesión utilizando la cookie de sesión (si no se ha alcanzado el tiempo de espera de la aplicación)?
manjiki

@jijix, este es un caso fronterizo que se considera lo suficientemente raro como para no molestarse si se agrega a la complejidad de la implementación. Aparte de eso, creo que podría especificarse mejor como "restablecer la sesión sin verificar los límites de la sesión" .
the-wabbit

Normalmente hago esto contando las URL "típicas" en el httpd-access-log. ¿Cuál es el número aproximado aproximado del que estamos hablando aquí? ¿Quizás un límite de hilo puede ayudar aquí en el lado httpd?
Nils

Sé que HAProxy puede limitar el número de conexiones. Pero estás preguntando algo un poco diferente ...
Matt

Respuestas:


5

El problema que en última instancia está tratando de resolver es con la capacidad de la aplicación, y ahí es donde debería resolver el problema. Ninguno de los componentes que menciona tiene algo que ver con la administración de sesiones para una aplicación HTTP.

Hay algunos trucos que puede aplicar con el módulo reciente en iptables o usando fail2ban de manera opuesta al propósito para el que fue diseñado, pero ambos requieren una comprensión muy detallada de las herramientas y el dominio del problema. Puede implementar el control de acceso a nivel de estos componentes pero impulsado por la información de estado publicada de la aplicación sobre el número de sesiones.

También necesito una forma de rastrear el número actual de sesiones para fines de monitoreo

Suponiendo, por el momento, que la aplicación es un recuadro negro sin posibilidad de modificación / instrumentación (lo cual es muy improbable), puede obtener esta información de sus registros de apache incluyendo el cookie de sesión - filtrar o seguir los registros para mantener un lista de cookies activas, y elimine las entradas de la lista cuando coincidan con la URL de cierre de sesión o no se hayan visto para el TTL.


Olvide mis preguntas anteriores, esto es exactamente a lo que estaba llegando.
lsmooth

¿Está seguro de que RadWare AppDirector no puede resolver este problema al menos en un tratamiento prolongado? - se solicita el control de sesión para evitar la sobrecarga de nodos que se puede lograr por otros medios.
Veniamin

No, no estoy seguro, como dije anteriormente, puedes evitar la administración de la sesión en otra parte de la pila, pero es mucho, mucho más difícil hacerlo en el lugar equivocado. Solucionar el problema donde está ocurriendo el problema es mucho más fácil.
symcbean

Si considera que el lugar adecuado para la administración de la sesión es un módulo integrado en la aplicación o en otro lugar por nodo, no está claro cómo hacerlo funcionar junto con el equilibrio de carga a nivel de AppDirector.
Veniamin

La idea de usar los registros de apache para el seguimiento de la sesión tiene algún mérito. En cuanto al resto, ya sabes que no he escrito la aplicación y tengo poca (si es que alguna) influencia en el desarrollo posterior. No fue mi decisión ponerlo en práctica, mi autoridad se limita a la infraestructura en la que se ejecuta. El punto de que la aplicación es subóptima se ha dejado claro a la administración, pero incluso si esto pudiera cambiar algo, cualquier cambio podría tomar una cantidad de tiempo significativa Así que mi trabajo actual es encontrar un modo de operación "tan bueno como sea posible".
the-wabbit

1

Esto no es exactamente lo que está pidiendo, pero ya he hecho lo siguiente con los equilibradores de carga F5:

  • Cuente el número de solicitudes de publicación en la página de inicio de sesión.
  • Retrasar a los usuarios si los inicios de sesión por segundo superan el primer límite
  • Enviar a los usuarios a una página de mantenimiento si los inicios de sesión por segundo están por encima de un segundo límite

Como el sitio web a veces estaba bajo una gran carga (carreras de caballos), ayudó.


Gracias por la idea, tengo que consultar con nuestros chicos de AppDirector si podemos implementar algo similar.
the-wabbit

@ syneticon-dj: si necesita verificar si puede implementar algo como esto (que en realidad no resuelve el problema, por cierto) y no puede solucionar la aplicación, entonces realmente está en un montón de problemas. Al reflexionar, puedo pensar en al menos 2 formas adicionales de resolver el problema, pero ambas son técnicamente exigentes, y su implementación incorrecta hará que el problema sea peor que mejor. Necesita más ayuda de la que obtendrá aquí.
symcbean

@symcbean Nada de lo que pueda hacer resolverá el problema, que es la falta de calificación dentro del personal de desarrollo y soporte del proveedor y la decisión de usar esta aplicación en ignorancia del mismo. Si tiene otras ideas, me alegrará saber de ellas. "Exigir" no es un problema siempre que no aumente la complejidad en las operaciones diarias.
the-wabbit

1

Este problema se puede resolver usando RadWare AppDirector y (para completar) probablemente también usando Apache mod_security según su excelente hallazgo en el comentario a continuación.

Para una solución AppDirector, creo que es posible crear dos granjas asignadas a los mismos servidores de fondo. Estas granjas pueden tener diferentes criterios y condiciones de operación aplicadas a ellas. Una granja sería la "predeterminada" y la otra respondería a los URI: s que usted define como "una sesión". Este último obtendría un límite en la cantidad de sesiones que acepta en el equilibrador de carga.

De ahora en adelante, voy a sustituir su término de "sesión" por "conectado" por dos razones:

  • Evita la ambigüedad, ya que define claramente el estado deseado en que el usuario está autenticado.
  • La Guía del usuario y la GUI de AppDirector redefine el término "conexión" para que tenga un significado para todos los fines prácticos idénticos a "sesión", ver más abajo. Esto agrega confusión que tratamos de evitar.

También es posible mostrar una página de disculpas si la granja "iniciada" ha alcanzado el límite de conexión elegido.

Antes de llegar al cómo, debo decir claramente que no tengo experiencia operativa con el producto AppDirector, pero administro diariamente un equilibrador de carga competitivo y un poco menos avanzado. El producto que uso puede hacer este escenario de inmediato. He encontrado información a través de la Guía del usuario de AppDirector y qué documentación en línea está disponible, lo que sugiere que lo mismo es cierto para AppDirector. Sin embargo, si bien los conceptos son similares, la terminología es diferente. Simplemente estoy haciendo un acto cuando estoy en Roma con respecto a la redacción, con la esperanza de hacerlo bien sin ser obviamente un imbécil despistado.

El mayor obstáculo fue obtener acceso a un manual, que no está disponible a menos que uno sea un cliente activo. A través de algunas búsquedas en Google fue posible encontrar una versión anterior que espero no esté demasiado desactualizada, también encontré un par de artículos de la base de conocimiento y este enlace: Radware AppDirector - Configuración: Aplicación básica .

Aquí hay un borrador de solución, interpretado principalmente a través de la Guía del usuario:

La entrada del cliente al equilibrador de carga se realiza a través de un VIP que se utiliza para conectar las sesiones "predeterminadas" y las "sesiones conectadas". Esto se logra a través de una política L4 según p.99 en la Guía del usuario:

"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 política L4 se puede vincular a las políticas L7 que se utilizan para seleccionar una granja adecuada. El proceso de la política L7 se describe así en la Guía del usuario 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."

Los métodos disponibles para definir un comportamiento L7 se describen en la p.106, de los cuales puede elegir un método adecuado para elegir el enrutamiento a su granja "iniciada" en lugar de la granja "predeterminada":

"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 se ve en el enlace de la Aplicación básica , se podría crear, por ejemplo, una política L7 que evalúe los patrones de URI para el enrutamiento a diferentes granjas. Los patrones de URI creados '^ / login? = True' y '^ / loginin' se pueden enrutar a su granja de servidores "iniciada sesión". El patrón inventado '^ / logout' (y todos los demás URI: s) podrían enrutarse de manera similar a una granja "predeterminada".

La Guía del usuario, p. 121, define una granja de servidores de la siguiente manera: "Una granja de AppDirector es un grupo de servidores en red que proporcionan el mismo servicio. Un servidor que proporciona múltiples servicios puede utilizarse en varias granjas".

Un servidor se diferencia aún más mediante la separación de la definición de un servidor de fondo en dos capas, la capa de objeto 'Servidor físico' que representa la dirección IP de un servidor y la capa de objeto 'Servidor agrícola' que representa los servicios que se ejecutan en uno o más Servidores físicos .

La limitación de sesión en una granja de servidores se puede realizar de acuerdo con la 'Guía del usuario de AppDirector' por cada objeto del servidor de granja definido para una granja (así como a través de otros medios) además de por objeto del servidor físico. Esto se describe entre otros lugares en 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 tabla de clientes y su 'modo regular' se definen en 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"

En una captura de pantalla de una ventana de definición de servidor en la página de Aplicación Básica , el cuadro de límite de conexión del servidor se ve justo al lado del cuadro de límite de ancho de banda.

Por lo tanto, depende un poco de la configuración, pero a los fines de esta respuesta, una 'conexión' definida a través de la Tabla del cliente y una 'sesión' definida por usted esencialmente terminan siendo lo mismo. Y se puede imponer un límite a ese efecto por objeto de servidor en una granja.

Como AppDirector distingue entre servidores físicos y servidores de granja, sería posible definir dos servidores de granja de mapeo a su objeto de servidor físico Apache, uno con un límite de conexión bajo.

Sin embargo, Apache también necesita responder llamadas de ambos objetos del servidor de la granja de servidores, por ejemplo, a través de dos puertos o direcciones IP separados, uno usado por cada combo (granja / servidor de granja). La pregunta es: ¿puede definir dos puntos de entrada del servidor de aplicaciones? es decir, ¿puede equipar su aplicación front-end Apache (/ vhost?) para responder en dos puertos o direcciones IP (una por granja)? Esto es a través de un poco de trabajo de conjetura, ya que no deseo pasar demasiado tiempo con el manual, pero estoy seguro de que podría resolverlo de manera bastante elegante cuando realmente mire la GUI de AppDirector y el Apache.

Establecer el límite de conexión tiene un pequeño capricho. Desde servidores físicos, límite de conexión 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."

Por lo tanto, deberá definir un Límite de conexión muy alto (con un amplio margen hasta el número máximo posible a través de su base de usuarios) para el servidor de granja "predeterminado" sin restricciones, y establecer el Límite de conexión para el servidor de granja "conectado" como bajo como tienes que hacerlo. La definición del servidor físico necesitaría tener la suma de los dos como su límite de conexión, como condición previa para activar el límite de sesión deseado.


También tiene este requisito en su pregunta:

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

Esto se denomina 'No hay página de servicio HTTP' en la Guía del usuario, 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 la parte de monitoreo no he hecho una investigación exhaustiva, pero esto es lo que pienso:

track the current number of sessions for monitoring purposes

AppDirector parece tener MIB. Probablemente sea una molestia encontrar el OID correcto, como suele ser, pero probablemente pueda usarlo con la herramienta que elija.

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

Este podría requerir un poco de pensamiento creativo. Suponiendo que AppDirector no incluya una plantilla para esto de inmediato, ¿qué tal si:

  • Los URI fuera de la granja "iniciada" no se verían afectados por el límite de sesión. Así que vigile, es el mismo servidor (s) de fondo de todos modos.
  • Utilice las comprobaciones de estado de AppDirector en su lugar, es probable que no cuenten para el límite de sesión que impone. Sin embargo, encuentre una forma de pasar alertas a su servidor de monitoreo :-)
  • Configure una tercera granja, a través de la cual pasa los controles de salud. Desordenado, pero funcionaría.

1
Hasta ahora, he descubierto que el módulo mod_security2 es capaz de manejar la sesión de una manera muy similar a lo que he especificado: secure.jwall.org/blog/2009/01/08/1231374852674.html . Voy a investigar un poco más sobre su idea de 2 granjas, si tal implementación fuera posible, ciertamente simplificaría las cosas.
the-wabbit

Respuesta del soporte técnico de Radware: "En AD solo podemos limitar el ancho de banda por granja. [...] El método [...] para limitar el número total de sesiones en una granja no está disponible actualmente". Entonces es mod_security entonces.
the-wabbit

Ok, eso fue inesperado. Sin embargo, a menos que me haya perdido algo, sigo pensando que cerrar la granja mediante un control de salud fallido sería una solución más limpia. Sin embargo, su hallazgo en mod_security es muy interesante.
ErikE

Posiblemente, aunque el soporte fue un poco limitado al interpretar la pregunta, parece que es posible un límite de sesión en el nivel del servidor en AppDirector (para lo cual ciertamente hay algo de lógica). Busqué en Google varios enlaces, aquí hay uno: kb.radware.com/questions/2829/…
ErikE

El artículo de Radware KB trata sobre LinkProof, un acelerador WAN. No tengo idea de qué software está ejecutando y si existirían instalaciones similares para AppDirector. Por cierto: el código de manejo de sesión seguramente es parte del conjunto de características de AppDirector: tiene una tabla de sesión que se ve exactamente como yo esperaría que se vea. Pero aparentemente, no hay forma de imponer un límite en el número de sesiones, solo en las conexiones. Lo máximo que podría obtener es limitar el número de visitas en una página determinada (por ejemplo, la página de inicio de sesión) por unidad de tiempo como sugirió Eric "el otro".
the-wabbit

0

Si AppDirector no puede ayudarlo, aquí hay otro enfoque que requerirá un poco de codificación. Abordaría el problema de la siguiente manera:

  • En un bucle, siga leyendo el archivo de registro de apache (y vuelva a abrirlo en logrotate)
  • Cuando un usuario visita cualquier página (no solo inicio de sesión), agréguela a una lista blanca de iptables
  • Cuando un usuario cierra la sesión, o después de la inactividad (¡así que mantenga los temporizadores para las sesiones activas!), Elimínelos de la lista blanca
  • Si la lista blanca está llena, redirija todo el tráfico que no esté en la lista blanca a un puerto especial
  • Ejecute un vhost simple en ese puerto con su error personalizado

Graficar el número de sesiones se vuelve tan simple como graficar la longitud de la cadena de iptables. El servidor de monitoreo simplemente puede estar siempre en la lista blanca.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.