Implementar el aislamiento de aplicaciones usando la unidad NGINX

Autor original: Artem Konev - Redactor técnico senior

Enlace original: Implementar el aislamiento de aplicaciones usando la unidad NGINX

Fuente de reimpresión: sitio web oficial chino de NGINX

La única comunidad china oficial de NGINX, toda en nginx.org.cn 


 

Uno de los últimos desarrollos en el conjunto de características de la Unidad NGINX es la compatibilidad con el aislamiento de aplicaciones, introducido en la versión 1.11.0 e implementado a través de espacios de nombres de Linux.
 
Repasemos brevemente el espacio de nombres de Linux : es esencialmente un mecanismo del kernel que admite que un grupo de procesos comparta varios recursos del sistema por separado de los recursos compartidos por otros grupos de procesos. El kernel garantiza que los procesos en un espacio de nombres solo accedan a los recursos asignados a ese espacio de nombres. Aunque los procesos en dos espacios de nombres diferentes pueden compartir algunos recursos, otros recursos son "invisibles" para un proceso en el otro espacio de nombres. Los tipos de recursos que se pueden aislar en un espacio de nombres varían según el sistema operativo e incluyen ID de proceso y usuario, entidades de comunicación entre procesos, puntos de montaje en el sistema de archivos, objetos de red, etc.
 
¿Suena un poco aburrido? Quizás sea así, especialmente si no conoces la tecnología del sistema operativo. Pero los espacios de nombres son uno de los factores clave detrás de la revolución de la contenedorización, y aislar los procesos de aplicaciones dentro de una única instancia de sistema operativo habilita los mecanismos críticos de seguridad y escalamiento necesarios para ejecutar aplicaciones en contenedores.

idea

Ahora que hemos establecido que los espacios de nombres pueden ser algo bueno, ¿qué hace NGINX Unit con ellos? Antes de seguir explicando, primero introduzcamos brevemente la información de fondo relevante y comprendamos los propios pensamientos de Tiago:
 
"Estoy investigando mejores formas de monitorear e interceptar efectivamente el tráfico de mi aplicación. En mi tiempo libre, he estado observando los aspectos internos de la Unidad NGINX y pensé que el aislamiento del proceso podría ser una buena opción. Sin embargo, no estoy seguro "Sin embargo, si es el escenario óptimo. Anteriormente, estaba pensando en eBPF y analizando cómo redirige los paquetes a nivel del kernel, pero luego tuve una idea diferente. Dado que la Unidad NGINX ejecuta y administra aplicaciones de una manera similar a un tiempo de ejecución de contenedor, entonces si ¿Qué pasaría si Unit agregara soporte de aislamiento de aplicaciones y lo usara en lugar del tiempo de ejecución? Esta idea coincide con una de las ideas futuras del equipo de NGINX Unit.
En el clúster, el tiempo de ejecución del contenedor inicia y detiene la aplicación, por lo que sabemos todo lo que se ejecuta en el clúster. La arquitectura de la Unidad NGINX no solo hace lo mismo, sino que también implementa el monitoreo e interceptación del tráfico de forma predeterminada: la única forma de llegar a la aplicación es a través del modelo de memoria compartida de la Unidad NGINX. En particular, incluso podemos aislar la red, similar a omitir la configuración de la interfaz dentro del contenedor, pero la aplicación aún puede comunicarse con el mundo exterior compartiendo memoria con la unidad NGINX sin encontrar ningún ataque de red costoso. "

Configuración

Desde una perspectiva de configuración, todo comienza con el nuevo objeto de aislamiento, que define la configuración relacionada con el espacio de nombres en el objeto de la aplicación.
 

Las opciones de espacio de nombres en el objeto de aislamiento dependen del sistema porque los tipos de recursos que se pueden aislar en un espacio de nombres varían según el sistema operativo. A continuación se muestra un ejemplo básico de cómo crear un ID de usuario independiente y un espacio de nombres de punto de montaje para su aplicación:

{
   "applications": {  
      "isolation_app": {  
         "type": "external",
         "executable": "/tmp/go-app",
         "isolation": {  
            "namespaces": {  
               "credential": true,
               "mount": "true"
            }
         }
      }
   }
}
Actualmente, la unidad NGINX admite la configuración de 6 de los 7 tipos de aislamiento de espacios de nombres admitidos por el kernel de Linux. Las opciones de configuración correspondientes son cgroup, credencial, pid, montaje, red y uname. El último tipo ipc aún no es compatible.
 
De forma predeterminada, todos los tipos de aislamiento están deshabilitados (opción configurada en falso), lo que significa que la aplicación reside en el espacio de nombres de la Unidad NGINX. Cuando habilita un tipo de aislamiento específico para una aplicación configurando su opción en verdadero, la Unidad NGINX crea un espacio de nombres separado de ese tipo para la aplicación. Por ejemplo, una aplicación puede estar en el mismo espacio de nombres que una unidad NGINX, además de tener su propio espacio de nombres de montaje o credenciales independiente.
 
Para obtener más detalles sobre las opciones en el objeto de aislamiento, consulte la documentación de la Unidad NGINX .
 
Nota: Al momento de escribir este artículo, todas las aplicaciones deben usar el mismo espacio de nombres ipc que la unidad NGINX; este es un requisito del mecanismo de memoria compartida. Puede agregar la opción ipc a la configuración, pero su configuración no tiene ningún efecto. Este requisito puede cambiar en versiones futuras.
 

Mapeo de ID de usuario y grupo

 
El aislamiento de aplicaciones en NGINX Unit incluye soporte para mapeo UID y GID, que se puede configurar si el aislamiento de credenciales está habilitado (lo que significa que su aplicación se ejecuta en un espacio de nombres de credenciales separado). Puede asignar una serie de ID en el espacio de nombres de la aplicación (al que llamamos "espacio de nombres del contenedor") al espacio de nombres de credenciales del proceso principal de la aplicación (al que llamamos "espacio de nombres del host"). Rangos de ID de la misma longitud.
 
Por ejemplo, suponga que tiene una aplicación ejecutándose con credenciales de usuario sin privilegios y habilita el aislamiento de credenciales para crear un espacio de nombres de contenedor para la aplicación. La unidad NGINX le permite asignar el UID de un usuario sin privilegios en el espacio de nombres del host al UID 0 (raíz) en el espacio de nombres del contenedor. Por diseño, cualquier UID con un valor de 0 en un espacio de nombres tiene permisos completos en ese espacio de nombres, pero sus permisos para asignar el UID correspondiente en el espacio de nombres del host aún son limitados. Por lo tanto, la aplicación parece tener capacidades de raíz, pero sólo para los recursos dentro de su espacio de nombres. Lo mismo ocurre con el mapeo GID.
 

Aquí, asignamos los 10 valores del rango UID que comienzan desde UID 500 en el espacio de nombres del host a los valores del rango UID que comienzan desde UID 0 en el espacio de nombres del contenedor (host: 500-509, contenedor: 0-9). De manera similar, asignamos los 20 valores de rango GID que comienzan desde GID 1000 en el espacio de nombres del host a los valores de rango que comienzan desde GID 0 en el espacio de nombres del contenedor (host: 1000-1019, contenedor: 0-19):

{
   "applications": {  
      "isolation_app": {  
         "type": "external",
         "executable": "/bin/app",
         "isolation": {  
            "namespaces": {  
               "credential": true
            },
            "uidmap": [  
               {  
                  "container": 0,
                  "host": 500,
                  "size": 10
               }
            ],
            "gidmap": [  
               {  
                  "container": 0,
                  "host": 1000,
                  "size": 20
               }
            ]
         }
      }
   }
}

 

 
Si no crea una asignación explícita de UID y GID, de forma predeterminada, el UID actualmente efectivo (EUID) del proceso de la Unidad NGINX sin privilegios en el espacio de nombres del host se asigna al UID raíz en el espacio de nombres del contenedor. Tenga en cuenta también que la asignación UID/GID solo está disponible si el sistema operativo host admite espacios de nombres de usuario. Dicho esto, pasemos a comprender el impacto del aislamiento de aplicaciones en las aplicaciones que se ejecutan en la Unidad NGINX.

Primeros pasos: aislamiento de aplicaciones básicas

Comencemos con lo básico y comprendamos cómo se comporta esta característica en tiempo de ejecución. Para hacer esto, tomaremos una aplicación Go de nuestro repositorio oficial (ejecútela al probar nuevas versiones):
Este código responde a la solicitud con una lista con formato JSON de procesos de aplicación e ID de espacios de nombres, enumerando el contenido del directorio /proc/self/ns/. A continuación configuramos la aplicación en la Unidad NGINX, ignorando el objeto de aislamiento por ahora:
 
{  
   "listeners": {  
      "*:8080": {  
         "pass": "applications/go-app"
      }
   },
   "applications": {  
      "go-app": {  
         "type": "external",
         "executable": "/tmp/go-app"
      }
   }
}

Respuesta HTTP de la instancia de aplicación en ejecución:

$ curl -X GET http://localhost:8080

{  
   "PID": 5778,
   "UID": 65534,
   "GID": 65534,
   "NS": {  
      "USER": 4026531837,
      "PID": 4026531836,
      "IPC": 4026531839,
      "CGROUP": 4026531835,
      "UTS": 4026531838,
      "MNT": 4026531840,
      "NET": 4026531992
   }
}
Ahora agregamos el objeto de aislamiento para habilitar el aislamiento de la aplicación. El mecanismo de aislamiento debe reiniciar la aplicación para que surta efecto. La Unidad NGINX realizará esta tarea entre bastidores, por lo que las actualizaciones son muy transparentes desde la perspectiva del usuario final.
{  
   "listeners": {  
      "*:8080": {  
         "pass": "applications/go-app"
      }
   },
   "applications": {  
      "go-app": {  
         "type": "external",
         "user": "root",
         "executable": "/tmp/go-app",
         "isolation": {  
            "namespaces": {  
               "cgroup": true,
               "credential": true,
               "mount": true,
               "network": true,
               "pid": true,
               "uname": true
            },
            "uidmap": [  
               {  
                  "host": 1000,
                  "container": 0,
                  "size": 1000
               }
            ],
            "gidmap": [  
               {  
                  "host": 1000,
                  "container": 0,
                  "size": 1000
               }
            ]
         }
      }
   }
}
Tenga en cuenta que la opción de usuario está configurada como root. Esta configuración es necesaria para habilitar la asignación a UID/GID 0 en el espacio de nombres del contenedor.
 
Emitimos el comando nuevamente:
$ curl -X GET http://localhost:8080

{  
   "PID": 1,
   "UID": 0,
   "GID": 0,
   "NS": {  
      "USER": 4026532180,
      "PID": 4026532184,
      "IPC": 4026531839,
      "CGROUP": 4026532185,
      "UTS": 4026532183,
      "MNT": 4026532181,
      "NET": 4026532187
   }
}
Ahora tenemos el aislamiento de aplicaciones habilitado y los ID del espacio de nombres han cambiado; ahora son ID en el espacio de nombres del contenedor, no en el espacio de nombres del host. Lo único que se mantiene sin cambios es el IPC, por los motivos mencionados anteriormente .

Sumérgete más profundamente: aislamiento de aplicaciones web

Para obtener una comprensión más profunda, exploremos el impacto real del aislamiento de aplicaciones en la red, que es muy importante para las aplicaciones web. Nuestra herramienta preferida para esto es nsenter, que funciona en muchas distribuciones de sistemas operativos compatibles con NGINX Unit. Esta utilidad nos permite ejecutar comandos arbitrarios dentro del espacio de nombres del proceso y la usaremos para demostrar los cambios causados ​​por diferentes configuraciones en el objeto de aislamiento de la misma aplicación Go configurada anteriormente. Primero, descubrimos el PID del host.
 
Para obtener más detalles sobre el código, consulte el sitio web oficial de la comunidad NGINX.
 
Después de determinar el PID, podemos ingresar al espacio de nombres del contenedor y ver su composición interna.
 
Tenga en cuenta que solo está disponible la interfaz loopback; sin embargo, la aplicación es totalmente capaz de manejar solicitudes HTTP externas a través de la unidad NGINX. A continuación, eliminaremos la opción de red de la lista de espacios de nombres configurados para ver la configuración final de la interfaz de red para la aplicación con el aislamiento de red deshabilitado.
 
Luego repetimos los mismos pasos anteriores.
 
También hay procesos de aplicación que todavía utilizan la interfaz de la Unidad NGINX (eth0) al iniciarse.
 

La única comunidad china oficial de NGINX, toda en nginx.org.cn
Más información técnica relacionada con NGINX, preguntas y respuestas interactivas, series de cursos y recursos para eventos: Sitio web oficial de la comunidad de código abierto | Cuenta oficial de WeChat
IntelliJ IDEA 2023.3 y JetBrains Family Bucket actualización anual de la versión principal nuevo concepto "programación defensiva": conviértase en un trabajo estable GitHub.com ejecuta más de 1200 hosts MySQL, ¿cómo actualizar sin problemas a 8.0? El equipo Web3 de Stephen Chow lanzará una aplicación independiente el próximo mes ¿ Se eliminará Firefox? Visual Studio Code 1.85 lanzado, ventana flotante La CISA de EE. UU. recomienda abandonar C/C++ para eliminar las vulnerabilidades de seguridad de la memoria Yu Chengdong: Huawei lanzará productos disruptivos el próximo año y reescribirá la historia de la industria TIOBE Diciembre: se espera que C# se convierta en el lenguaje de programación del año Un artículo escrito por Lei Jun hace 30 años: "Principio y diseño del sistema experto de determinación de virus informáticos"
{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/5246775/blog/10109984
Recomendado
Clasificación