Servicios Linux escuchando por el mismo puerto
Cuando leí sobre la nueva funcionalidad introducida en el núcleo de Linux en su versión 3.9 me acordé de la entrada HTTPS, SSH y OpenVPN en un mismo puerto, ¿magia? en SecurityByDefault aunque son cosas distintas.
Como decía en la versión del núcleo de Linux 3.9, se introdujo una nueva característica relacionada con los Sockets, la cual permite poner a más de un servicio o demonio escuchando por el mismo puerto. Esto se consigue a través de una nueva opción llamada SO_REUSEPORT. Los parches para esta nueva funcionalidad fueron implementados por Tom Herbert, un ingeniero de Google.
Algunos de los argumentos que Tom Herbert puso sobre la mesa para implementar esta característica fueron:
- En la forma tradicional en al que un servicio procesa conexiones, es entrando en un bucle sin fin e ir creando hilos (threads) para procesar cada petición. Por lo visto Herbert tiene situaciones en las que tiene que lidiar con 40000 peticiones por segundo, y ese único punto de entrada se acaba convirtiendo en un cuello de botella.
- De nuevo, con el método tradicional multihilo, la carga de trabajo entre los hilos que están esperando peticiones no está balanceada. Es decir, que hay varios hilos que reciben casi todo el trabajo, mientras que otros pasan la mayor parte de su tiempo esperando y como consecuencia de ello, no se aprovechan todos los procesadores del sistema de una forma optimizada.
- El primer servicio que empiece a escuchar por el puerto X, debe establecer la opción SO_REUSEPORT. Si esto no ocurre, ningún otro servicio podrá escuchar por dicho puerto.
- Los servicios que compartan puerto, deben tener un User ID efectivo y éste debe ser el mismo que el primer servicio que abrió el puerto. Con esto se consigue evitar el secuestro de puertos. De otra forma, un usuario malo malísimo, podría poner a escuchar algún servicio malicioso por un puerto con un servicio legítimo.
Vamos a usar el siguiente script escrito en Ruby:
La línea 10 es la clave. Ahí es donde decimos que queremos compartir el puerto. Todo lo que nuestro servicio va a hacer es repetir lo que el cliente le mande, con el prefijo “Version 1” en este caso. Por lo tanto si arrancamos 2 servicios y nos conectamos al puerto 5555 varias veces:
Otra de las bondades de esta nueva opción es que podemos agregar nuevos servicios en cualquier momento. Digamos que hemos arreglado un error en nuestro script y queremos ponerlo a escuchar. Vamos a modificar la salida del script a: “Version 2”, más lo que nos mande el cliente:
Como vemos, ahora tenemos corriendo dos servicios “Version 1” y un servicio “Version 2”. De esta forma podemos tener nuestro servicio corriendo sin coste en el tiempo de despliego (deployment), con lo cual nunca dejamos de dar servicio. Una vez que tengamos corriendo nuestro nueva versión, podemos ir cerrando las “Versiones 1” e ir dejando levantando “Versiones 2”.
Creo que es una característica que da mucho juego. Como nota final decir que aunque esto haya llegado a Linux recientemente, es una característica que los sistemas BSD desde hace años.
Fuentes http://freeprogrammersblog.vhex.net/post/linux-39-introdued-new-way-of-writing-socket-servers/2 https://lwn.net/Articles/542629/
Buscar
Entradas Recientes
- Posts
- Reemplazando la bateria del AirTag
- OpenExpo Europe décima edición, 18 de mayo: El Epicentro de la Innovación y la Transformación Digital
- Docker Init
- Kubernetes para profesionales
- Agenda: OpenExpo Europe 2022 llega el 30 de junio en formato presencial
- Libro 'Manual de la Resilencia', de Alejandro Corletti, toda una referencia para la gestión de la seguridad en nuestros sistemas
- Mujeres hackers en ElevenPaths Radio
- Creando certificados X.509 caducados
- Generador de imágenes Docker para infosec