Información blog

Linux, tutoriales, noticias, sistemas, redes y seguridad informática, entre otras cosas.

viernes, 8 de abril de 2016

Cómo cambiar la duración de las conexiones inactivas en Linux

Las redes no siempre son sencillas de configurar y mantener; en éstas pueden fluir miles de millones de datos que no siempre podemos controlar; ya sea porque las aplicaciones que generan dicho tráfico no se pueden modificar o debido a que que la red no ha sido configurada por nosotros... Es por eso que a veces tenemos la mala suerte de encontrarnos con configuraciones inadecuadas de red o tráfico de paquetes de red no deseados que, de un modo u otro, hacen que las conexiones hacia nuestro servidor, no sean tan óptimas como nos gustaría. Una de las peores cosas que nos pueden ocurrir es que una conexión se quede establecida entre un equipo y nuestro servidor, pero que no fluyan datos por ésta, manteniendo un puerto de escucha ocupado en nuestro servidor (con su respectivo consumo de memoria) y pudiendo llegar a saturar éste en caso de tener muchas conexiones de este tipo. En ocasiones como estas, uno de los factores más determinantes que pueden ayudarnos a evitar conflictos como éstos. Es el concepto keepalive.

Portada_conexiones_inactivas

Keepalive se encarga de comprobar si una conexión se mantiene activa o no. Para ello lo que hace es calcular el tiempo que transcurre desde el último paquete de datos recibido, con lo que si pasan una serie de segundos (previamente establecidos), el servidor intentará reconectar con el otro equipo un número determinado de veces cada X segundos... La cuestión está en que aunque la desconexión es realizada por el servidor, este tarda mucho en realizarla por "culpa" de los valores por defecto que tiene establecidos; valores que en entornos ideales no dan problemas, pero que en otros en cambio son más perjudiciales que beneficiosos.

Los valores que se encargan de establecer el "tiempo de vida" son tcp_keepalive_time, tcp_keepalive_intvl, tcp_keepalive_probes. La combinación de esos tres valores son las que consiguen que tengamos un tiempo de desconexión determinado, pero es importante saber diferencias las funciones de cada uno de éstos, pues son completamente diferentes los unos de los otros:

  • tcp_keepalive_time: Establece el tiempo necesario que tiene que pasar sin recibir paquetes desde el otro equipo para empezar a mandar paquetes "keep alive"; paquete que en caso de que el otro lado estuviese activo/online recibiría respuesta. El valor por defecto son 7200 segundos (2 horas).
  • tcp_keepalive_intvl: El intervalo de tiempo entre cada envío de paquetes "keep alive"(independientemente de que la conexión esté " viva o muerta"). El valor por defecto son 75 segundos.
  • tcp_keepalive_probes: Establece el número de paquetes "keep alive" sin respuesta necesarios para considerar que una conexión está "muerta".  El valor por defecto son 9 intentos.

Teniendo en cuenta todos estos valores veríamos que el total de tiempo que tendría que transcurrir para considerar una conexión completamente muerta sería de: 2 horas + (75 segundos * 9 intentos /60 segundos) = 2 horas, 11 minutos y 25 segundos... En definitiva; mucho tiempo; demasiado en algunos casos.

Para modificar estos valores podemos hacerlo o bien directamente para la sesión actual (que al reiniciar el equipo volverían a tener sus valores originales) o a nivel de kernel en sysctl para hacer los cambios persistentes... Esto es debido a que estos valores están almacenados en ficheros separados con el mismo nombre dentro del directorio virtual /proc/sys/net/ipv4/, así que estaríamos hablando de valores que afectarían directamente al núcleo del sistema. Es importante saber que, si bien se está efectuando un cambio sobre parámetros ipv4; estos parámetros en concreto también afectan a ipv6, con lo que no estaríamos dejando ningún cabo suelto. Si deseásemos hacer que el tiempo sin recibir paquetes fuese de 10 minutos (600 segundos) y que tras dicho intervalo de tiempo hiciese un máximo de 10 intentos fallidos cada 60 segundos, tendríamos dos formas de hacerlo.

La primera y más rudimentaria sería modificando los ficheros correspondientes a mano para que únicamente fuesen válidos hasta el próximo reinicio; esto se haría mediante estos tres comandos:

  1. echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time
  2. echo 60 > /proc/sys/net/ipv4/tcp_keepalive_intvl
  3. echo 10 > /proc/sys/net/ipv4/tcp_keepalive_probes

La solución es perfectamente válida, pero la verdad es que es algo chapucera, ya que rara vez se aplican estos cambios de forma temporal; y menos cuando dicha temporalidad depende de evitar reiniciar el equipo... Es por ello que es mucho más eficiente aplicar los cambios de forma permanente introduciendo los parámetros en /etc/sysctl.conf.

  1. echo 'net.ipv4.tcp_keepalive_time = 600' >> /etc/sysctl.conf
  2. echo 'net.ipv4.tcp_keepalive_intvl = 60' >> /etc/sysctl.conf
  3. echo 'net.ipv4.tcp_keepalive_probes = 10' >> /etc/sysctl.conf
  4. sysctl -p

Con esto sí que tendríamos los cambios aplicados de forma permanente, haciendo que nuestras conexiones estuviesen mucho menos tiempo "muertas". Si quisiésemos añadir más flexibilidad a estas reglas o ser más restrictivos con estas conexiones, solamente habría que jugar con estos parámetros hasta conseguir el balance ideal.

Espero que os haya resultado útil.

Saludos.

4 comentarios :

  1. Hola. ¿Sabes si configurar un keepalive_time de 60 segundos es una locura? La verdad que no vemos alguna contra más que un incremento en el tráfico de la red, pero de mensajes pequeños. ¿qué te parece?

    ResponderEliminar
    Respuestas
    1. Hola buenas.

      Todo depende de las necesidades particulares que tengas... Pero si ves que para tu caso en particular es adecuado, no lo veo del todo mal. Has de tener en cuenta que con este parámetro estarías mandando bastantes mensajes keepalive, especialmente si las conexiones son realizadas a servicios tales como apache2.

      Saludos.

      Eliminar
  2. Hola Ivan, un gusto. Cuales serian los valores recomendables para estos parametros en un linux RedHat? Esto funcinaria para disminuir el numero de conexiones que quedan en estado CLOSE_WAIT por altas cadencias de conexion?

    ResponderEliminar
    Respuestas
    1. Buenas Vielman.

      Los valores recomendados son genericos para todas las distribuciones y se trataría de un valor que dependería más de los niveles de "carga" o las interacciones del servidor que la distribución en sí. Con respecto a las conexiones CLOSE_WAIT esto debería ayudar y es uno de los motivos por los cuales conviene jugar con estos valores, si bien es cierto que cuando hay una conexión CLOSE_WAIT muerta, puede deberse en muchos casos a un error en la programación o en la comunicación.

      Si como dices, es un sitio con una alta cadencia de conexiones, como una web; lo ideal es comenzar primero con la optimización del servicio relacionado con dichas conexiones antes de pasar a modificar dichos valores, ya que generalmente hay muchos servicios que no están correctamente optimizados.

      Eliminar