Tutorial de NGINX: protege las aplicaciones de Kubernetes frente a la inyección SQL

NGINX | 22 de marzo de 2022

Este tutorial es uno de los cuatro que ponen en práctica conceptos de «Microservicios de marzo de 2022: redes de Kubernetes»:

¿Quieres una guía detallada sobre cómo usar NGINX para aún más casos de uso de redes en Kubernetes? Descarga gratis nuestro eBook, «Gestión del tráfico de Kubernetes con NGINX: guía práctica».

Trabajas en el departamento de TI de una conocida tienda local que vende una gran variedad de productos, desde almohadas hasta bicicletas. Están a punto de lanzar su primera tienda online, pero antes de hacerla pública pidieron a un experto en seguridad que realizara una prueba de penetración del sitio. Por desgracia, el experto en seguridad encontró un problema: la tienda online es vulnerable a la inyección de SQL. El experto pudo aprovechar esta vulnerabilidad para obtener información confidencial de la base de datos, incluidos nombres de usuario y contraseñas.

Tu equipo ha recurrido a ti —el ingeniero de Kubernetes— para salvar la situación. Por suerte, sabes que la inyección SQL (al igual que otras vulnerabilidades) puede mitigarse mediante las herramientas de gestión del tráfico de Kubernetes. Ya has implementado un controlador Ingress para exponer la aplicación y, con una única configuración, puedes garantizar que la vulnerabilidad no pueda explotarse. Ahora, la tienda online puede lanzarse a tiempo. ¡Buen trabajo!

Descripción general del laboratorio y el tutorial

Este blog complementa el laboratorio de la unidad 3 de Microservices March 2022 – «Patrón de seguridad de microservicios en Kubernetes», en el que se muestra cómo utilizar NGINX y NGINX Ingress Controller para bloquear la inyección de código SQL.

Para seguir el tutorial, necesitas un equipo con:

  • 2 CPU o más
  • 2 GB de memoria libre
  • 20 GB de espacio libre en disco
  • Conexión a Internet
  • Gestor de contenedores o máquinas virtuales, como Docker, Hyperkit, Hyper-V, KVM, Parallels, Podman, VirtualBox o VMware Fusion/Workstation
  • minikube instalado
  • Helm instalado
  • Una configuración que permita abrir una ventana del navegador. Si no es posible, tendrás que averiguar cómo acceder a los servicios pertinentes mediante un navegador.

Para sacar el máximo partido al laboratorio y al tutorial, le recomendamos que, antes de empezar:

 

Este tutorial utiliza estas tecnologías:

Las instrucciones de cada reto incluyen el texto completo de los archivos YAML utilizados para configurar las aplicaciones. También puedes copiar el texto de nuestro repositorio de GitHub. Junto al texto de cada archivo YAML se proporciona un enlace a GitHub.

Este tutorial incluye cuatro desafíos:

  1. Desplegar un clúster y una aplicación vulnerable
  2. Hackea la aplicación
  3. Usar un contenedor sidecar de NGINX para bloquear determinadas solicitudes
  4. Configurar NGINX Ingress Controller para filtrar solicitudes

Desafío 1: Desplegar un clúster y una aplicación vulnerable

En este reto, desplegarás un clúster de minikube e instalarás Podinfo como aplicación de ejemplo con vulnerabilidades de seguridad.

Crear un clúster de Minikube

Despliega un clúster de minikube. Tras unos segundos, aparecerá un mensaje que confirma que el despliegue se ha realizado correctamente.

$ minikube start 
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

Instalar la aplicación vulnerable

Aquí desplegarás una sencilla aplicación de comercio electrónico que consta de dos microservicios:

  • Una base de datos MariaDB
  • Un microservicio PHP que se conecta a la base de datos y recupera datos

Sigue estos pasos:

  1. Con el editor de texto que prefiera, cree un archivo YAML llamado 1-app.yaml con el siguiente contenido (o cópielo de GitHub).
apiVersion: apps/v1 kind: Deployment 
metadata: 
  name: app 
spec: 
  selector: 
    matchLabels: 
      app: app 
  template: 
    metadata: 
      labels: 
        app: app 
    spec: 
      containers: 
        - name: app 
          image: f5devcentral/microservicesmarch:1.0.3 
          ports: 
            - containerPort: 80 
          env: 
            - name: MYSQL_USER 
              value: dan 
            - name: MYSQL_PASSWORD 
              value: dan 
            - name: MYSQL_DATABASE 
              value: sqlitraining 
            - name: DATABASE_HOSTNAME 
              value: db.default.svc.cluster.local 
--- 
apiVersion: v1 
kind: Service 
metadata: 
  name: app 
spec: 
  ports: 
    - port: 80 
      targetPort: 80 
      nodePort: 30001 
  selector: 
    app: app 
  type: NodePort 
--- 
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: db 
spec: 
  selector: 
    matchLabels: 
      app: db 
  template: 
    metadata: 
      labels: 
        app: db 
    spec: 
      containers: 
        - name: db 
          image: mariadb:10.3.32-focal 
          ports: 
            - containerPort: 3306 
          env: 
            - name: MYSQL_ROOT_PASSWORD 
              value: root 
            - name: MYSQL_USER 
              value: dan 
            - name: MYSQL_PASSWORD 
              value: dan 
            - name: MYSQL_DATABASE 
              value: sqlitraining 

--- 
apiVersion: v1 
kind: Service 
metadata: 
  name: db 
spec: 
  ports: 
    - port: 3306 
      targetPort: 3306 
  selector: 
    app: db 
  1. Despliega la aplicación y la API:
$ kubectl apply -f 1-app.yaml deployment.apps/app created 
service/app created 
deployment.apps/db created 
service/db created 
  1. Confirma que los pods de Podinfo se hayan desplegado, tal como indica el valor «Running» en la columna «STATUS». Pueden tardar entre 30 y 40 segundos en desplegarse por completo, así que espera hasta que el estado de ambos pods sea «Running» antes de continuar con el siguiente paso (vuelve a ejecutar el comando si es necesario).
$ kubectl get podsNAME                  READY   STATUS    RESTARTS   AGE 
app-d65d9b879-b65f2   1/1     Running   0          37s 
db-7bbcdc75c-q2kt5    1/1     Running   0          37s 
  1. Abre la aplicación en tu navegador:
$ minikube service app|-----------|------|-------------|--------------| 
| NAMESPACE | NAME | TARGET PORT |     URL      | 
|-----------|------|-------------|--------------| 
| default   | app  |             | No node port | 
|-----------|------|-------------|--------------| 
😿  service default/app has no node port 
🏃  Starting tunnel for service app. 
|-----------|------|-------------|------------------------| 
| NAMESPACE | NAME | TARGET PORT |          URL           | 
|-----------|------|-------------|------------------------| 
| default   | app  |             | http://127.0.0.1:55446 | 
|-----------|------|-------------|------------------------| 
🎉  Opening service default/app in default browser... 

Desafío 2: Hackea la aplicación

La aplicación de ejemplo es bastante básica. Incluye una página de inicio con una lista de artículos (por ejemplo, almohadas) y varias páginas de productos con información como la descripción y el precio. Los datos se almacenan en la base de datos MariaDB. Cada vez que se solicita una página, se ejecuta una consulta SQL en la base de datos.

  • Para la página de inicio, se recuperan todos los artículos de la base de datos.
  • Para una página de producto, el artículo se obtiene por su ID.

Al abrir la página del producto almohadas, puede que observes que la URL termina en /product/1. El 1 es el ID del producto. Para evitar la inserción directa de código malicioso en la consulta SQL, se recomienda sanear los datos introducidos por el usuario antes de reenviar las solicitudes a los servicios de backend. Pero ¿qué ocurre si la aplicación no está configurada correctamente y los datos introducidos no se escapan antes de insertarlos en la consulta SQL a la base de datos?

Explotación 1

Para comprobar si la aplicación escapa correctamente los datos de entrada, haz una prueba sencilla cambiando el ID por uno que no exista en la base de datos.

Cambia manualmente el último elemento de la URL de 1 a -1. El mensaje de error Invalid product id "-1" indica que el ID del producto no se está escapando; en su lugar, la cadena se inserta directamente en la consulta. ¡Eso no es bueno, a menos que seas un hacker!

Supongamos que la consulta a la base de datos es algo así:

SELECT * FROM some_table WHERE id = "1"

Para aprovechar la vulnerabilidad causada por no escapar la entrada, sustituye 1 por -1" <malicious_query> -- // de modo que:

  • Las comillas (") después de -1 completan la primera consulta.
  • Puedes añadir tu propia consulta maliciosa después de las comillas.
  • La secuencia -- // descarta el resto de la consulta.

Así, por ejemplo, si cambia el último elemento de la URL por ‑1" o 1 -- //, la consulta resultante es:

SELECT * FROM some_table WHERE id = "-1" OR 1 -- //" 
                                     -------------- 
                                     ^ injected ^ 

Esto selecciona todas las filas de la base de datos, lo cual resulta útil en un ataque. Para comprobar si este es el caso, cambia el final de la URL a ‑1". El mensaje de error resultante proporciona más información útil sobre la base de datos:

Fatal error: Uncaught mysqli_sql_exception: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '"-1""' at line 1 in /var/www/html/product.php:23 Stack trace: #0 /var/www/html/product.php(23): mysqli->query('SELECT * FROM p...') #1 {main} thrown in /var/www/html/product.php on line 23

Ahora puedes empezar a manipular el código inyectado para intentar ordenar los resultados de la base de datos por ID:

-1" OR 1 ORDER BY id DESC -- //

El resultado es la página de producto del último artículo de la base de datos.

Explotación 2

Obligar a la base de datos a ordenar los resultados es interesante, pero no resulta especialmente útil si tu objetivo es hackear el sistema. Merece mucho más la pena intentar extraer nombres de usuario y contraseñas de la base de datos.

Es razonable suponer que en la base de datos hay una tabla de usuarios con nombres de usuario y contraseñas. Pero ¿cómo puedes ampliar tu acceso desde la tabla de productos hasta la tabla de usuarios?

La respuesta consiste en inyectar código como este:

-1" UNION SELECT * FROM users -- //

donde

  • ‑1" fuerza a que la primera consulta devuelva un conjunto vacío.
  • UNION fuerza la unión de dos tablas de la base de datos; en este caso, products y users, lo que permite obtener información (contraseñas) que no se encuentra en la tabla original (products).
  • SELECT * FROM users selecciona todas las filas de la tabla users.
  • La secuencia -- // descarta todo lo que aparece después de la consulta maliciosa.

Al modificar la URL para que termine con el código inyectado, aparece un nuevo mensaje de error:

Fatal error: Uncaught mysqli_sql_exception: The used SELECT statements have a different number of columns in /var/www/html/product.php:23 Stack trace: #0 /var/www/html/product.php(23): mysqli->query('SELECT * FROM p...') #1 {main} thrown in /var/www/html/product.php on line 23

Este mensaje revela que las tablas products y users no tienen el mismo número de columnas, por lo que no se puede ejecutar la instrucción UNION. Sin embargo, puedes averiguar el número de columnas mediante ensayo y error, añadiendo columnas (nombres de campos) de una en una como parámetros de la instrucción SELECT. Una buena opción para el nombre de un campo de una tabla users es password, así que prueba con ese:

# select 1 column-1" UNION SELECT password FROM users; -- //
# select 2 columns 
-1" UNION SELECT password,password FROM users; -- //
# select 3 columns 
-1" UNION SELECT password,password,password FROM users; -- /
# select 4 columns 
-1" UNION SELECT password,password,password,password FROM users; -- //
# select 5 columns
-1" UNION SELECT password,password,password,password,password FROM users; -- //

La última consulta se ejecuta correctamente (lo que indica que hay cinco columnas en la tabla users) y se muestra la contraseña de un usuario:

En este punto, no sabes qué nombre de usuario corresponde a esta contraseña. Pero, como conoces el número de columnas de la tabla users, puedes usar los mismos tipos de consulta que antes para obtener esa información. Supongamos que el nombre del campo relevante es username. Y resulta que es correcto: la siguiente consulta obtiene tanto el nombre de usuario como la contraseña de la tabla users. Lo cual está muy bien... ¡a menos que esta aplicación esté alojada en tu infraestructura!

-1" UNION SELECT username,username,password,password,username FROM users where id=1 -- //

Desafío 3: Usa un contenedor sidecar de NGINX para bloquear determinadas solicitudes

Está claro que el desarrollador de la aplicación de la tienda online debe prestar más atención a la validación y limpieza de los datos introducidos por los usuarios (por ejemplo, mediante consultas parametrizadas), pero, como ingeniero de Kubernetes, también puedes ayudar a evitar las inyecciones SQL impidiendo que el ataque llegue a la aplicación. De este modo, el hecho de que la aplicación sea vulnerable tiene menos importancia.

Hay muchas formas de proteger tus aplicaciones. Durante el resto de este laboratorio, nos centraremos en dos:

  • En este reto, se inserta un contenedor sidecar en el pod para que actúe como proxy de todo el tráfico y rechace cualquier solicitud que contenga UNION en la URL. Primero, hay que desplegar NGINX Open Source como sidecar y, después, comprobar si filtra las consultas maliciosas. Nota: Esta técnica se utiliza únicamente con fines ilustrativos. En la práctica, desplegar proxies manualmente como sidecars no es la mejor solución (se explicará más adelante).
  • En el Reto 4, utilizamos NGINX Ingress Controller para filtrar todo el tráfico que entra en el clúster.

Implementar NGINX Open Source como sidecar

  1. Cree un archivo YAML llamado 2-app-sidecar.yaml con el siguiente contenido (o cópielo de GitHub). Entre los aspectos importantes de la configuración se incluyen:
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: app 
spec: 
  selector: 
    matchLabels: 
      app: app 
  template: 
    metadata: 
      labels: 
        app: app 
    spec: 
      containers: 
        - name: app 
          image: f5devcentral/microservicesmarch:1.0.3 
          ports: 
            - containerPort: 80 
          env: 
            - name: MYSQL_USER 
              value: dan 
            - name: MYSQL_PASSWORD 
              value: dan 
            - name: MYSQL_DATABASE 
              value: sqlitraining 
            - name: DATABASE_HOSTNAME 
              value: db.default.svc.cluster.local 
        - name: proxy # <-- sidecar 
          image: "nginx" 
          ports: 
            - containerPort: 8080 
          volumeMounts: 
            - mountPath: /etc/nginx 
              name: nginx-config 
      volumes: 
        - name: nginx-config 
          configMap: 
            name: sidecar 
--- 
apiVersion: v1 
kind: Service 
metadata: 
  name: app 
spec: 
  ports: 
    - port: 80 
      targetPort: 8080 # <-- the traffic is routed to the proxy 
      nodePort: 30001 
  selector: 
    app: app 
  type: NodePort 
--- 
apiVersion: v1 
kind: ConfigMap 
metadata: 
  name: sidecar 
data: 
  nginx.conf: |- 
    events {} 
    http { 
      server { 
        listen 8080 default_server; 
        listen [::]:8080 default_server; 

        location ~* "(\'|\")(.*)(drop|insert|md5|select|union)" { 
            deny all; 
        } 

        location / { 
            proxy_pass http://localhost:80/; 
        } 
      } 
    } 
--- 
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: db 
spec: 
  selector: 
    matchLabels: 
      app: db 
  template: 
    metadata: 
      labels: 
        app: db 
    spec: 
      containers: 
        - name: db 
          image: mariadb:10.3.32-focal 
          ports: 
            - containerPort: 3306 
          env: 
            - name: MYSQL_ROOT_PASSWORD 
              value: root 
            - name: MYSQL_USER 
              value: dan 
            - name: MYSQL_PASSWORD 
              value: dan 
            - name: MYSQL_DATABASE 
              value: sqlitraining 

--- 
apiVersion: v1 
kind: Service 
metadata: 
  name: db 
spec: 
  ports: 
    - port: 3306 
      targetPort: 3306 
  selector: 
    app: db
  • Se inicia un contenedor sidecar que ejecuta NGINX Open Source en el puerto 8080.
  • NGINX reenvía todo el tráfico a la aplicación.
  • Se deniega cualquier solicitud que incluya (entre otras cadenas de caracteres) SELECT o UNION (consulte el primer bloque location de la sección ConfigMap).
  • El servicio de la aplicación dirige primero todo el tráfico al contenedor de NGINX.
  1. Despliega el sidecar:
$ kubectl apply -f 2-app-sidecar.yaml deployment.apps/app configured 
service/app configured 
configmap/sidecar created 
deployment.apps/db unchanged 
service/db unchanged 

Probar el sidecar como filtro

Comprueba si el sidecar está filtrando el tráfico volviendo a la aplicación e intentando de nuevo la inyección SQL. ¡NGINX bloquea la solicitud antes de que llegue a la aplicación!

-1" UNION SELECT username,username,password,password,username FROM users where id=1 -- // 

Desafío 4: Configurar el controlador de Ingress de NGINX para filtrar solicitudes

Proteger tu aplicación como en el Reto 3 resulta interesante como experiencia educativa, pero no lo recomendamos para entornos de producción porque:

  • No es una solución de seguridad completa.
  • No es escalable (no se puede aplicar fácilmente esta protección a varias aplicaciones).
  • Actualizarlo es complicado e ineficiente.

Una solución mucho mejor es utilizar NGINX Ingress Controller para extender la misma protección a todas tus aplicaciones. Los controladores de Ingress permiten centralizar todo tipo de funciones de seguridad, desde el bloqueo de solicitudes, como hace un firewall de aplicaciones web (WAF), hasta la autenticación y la autorización.

En este reto, desplegarás NGINX Ingress Controller, configurarás el enrutamiento del tráfico, y comprobarás que el filtro bloquea la inyección SQL.

Implementar NGINX Ingress Controller

La forma más rápida de instalar NGINX Ingress Controller es mediante Helm.

  1. Añada el repositorio de NGINX a Helm:
$ helm repo add nginx-stable https://helm.nginx.com/stable 
  1. Descargue e instale el controlador basado en NGINX Open Source NGINX Ingress Controller, cuyo mantenimiento corre a cargo de F5 NGINX. Tenga en cuenta el parámetro enableSnippets=true: los fragmentos se utilizan para configurar NGINX de modo que bloquee la inyección de SQL. La última línea de la salida confirma que la instalación se ha realizado correctamente.
$ helm install main nginx-stable/nginx-ingress \ --set controller.watchIngressWithoutClass=true --set controller.service.type=NodePort \ --set controller.service.httpPort.nodePort=30005 \ --set controller.enableSnippets=true
NAME: main  
LAST DEPLOYED: Day Mon DD hh:mm:ss YYYY  
NAMESPACE: default  
STATUS: deployed  
REVISION: 1  
TEST SUITE: None  
NOTES: The NGINX Ingress Controller has been installed.  
  1. Confirme que el pod de NGINX Ingress Controller se haya desplegado, tal como indica el valor «Running» en la columna «STATUS».
$ kubectl get pods   NAME                                READY   STATUS  ...
main-nginx-ingress-779b74bb8b-mtdkr 1/1     Running ...

      ... RESTARTS   AGE 
      ... 0          18s

Dirige el tráfico a tu aplicación

  1. Cree un archivo YAML llamado 3-ingress.yaml con el siguiente contenido (o cópielo de GitHub). Este archivo define el manifiesto de Ingress necesario para dirigir el tráfico a la aplicación (esta vez, sin pasar por el proxy sidecar). Observe el bloque annotations: en el que se utiliza un fragmento para personalizar la configuración del controlador de Ingress de NGINX con el mismo bloque location que en la definición del ConfigMap del reto 3: rechaza cualquier solicitud que incluya (entre otras cadenas de caracteres) SELECT o UNION.
apiVersion: v1 kind: Service 
metadata: 
  name: app-without-sidecar 
spec: 
  ports: 
    - port: 80 
      targetPort: 80 
  selector: 
    app: app 
--- 
apiVersion: networking.k8s.io/v1 
kind: Ingress 
metadata: 
  name: entry 
  annotations: 
    nginx.org/server-snippets: | 
      location ~* "(\'|\")(.*)(drop|insert|md5|select|union)" { 
          deny all; 
      } 
spec: 
  ingressClassName: nginx 
  rules: 
    - host: "example.com" 
      http: 
        paths: 
          - backend: 
              service: 
                name: app-without-sidecar 
                port: 
                  number: 80 
            path: / 
            pathType: Prefix 
  1. Despliega el recurso Ingress:
$ kubectl apply -f 3-ingress.yaml service/app-without-sidecar created 
ingress.networking.k8s.io/entry created 

Verificar el funcionamiento del filtro

  1. Inicia un contenedor desechable de BusyBox para enviar una solicitud al pod del controlador de Ingress de NGINX con el nombre de host correcto.
$ kubectl run -ti --rm=true busybox --image=busybox$ wget --header="Host: example.com" -qO- main-nginx-ingress 
<!DOCTYPE html> 
<html lang="en"> 

<head> 
# ...
  1. Intenta realizar la inyección SQL. El código de estado 403 Prohibido confirma que NGINX bloquea el ataque. 
$ wget --header="Host: example.com" -qO- 'main-nginx-ingress/product/-1"%20UNION%20SELECT%20username,username,password,password,username%20FROM%20users%20where%2 0id=1%20--%20//' 
wget: server returned error: HTTP/1.1 403 Forbidden 

Próximos pasos

Kubernetes no es seguro de forma predeterminada. Un controlador Ingress puede mitigar las vulnerabilidades de inyección SQL (y muchas otras). Sin embargo, tenga en cuenta que la funcionalidad similar a la de un WAF que acaba de implementar con NGINX Ingress Controller no sustituye a un WAF real ni a un diseño seguro de las aplicaciones. Un hacker experimentado aún puede conseguir que el ataque UNION funcione con unos pequeños cambios en el código. Para obtener más información sobre este tema, consulte Guía de inyección SQL (SQLi) para pentesters.

Dicho esto, un controlador de Ingress sigue siendo una herramienta potente para centralizar la mayor parte de la seguridad, lo que permite mejorar la eficiencia y la protección, incluidos casos de uso de autenticación y autorización centralizadas (mTLS, inicio de sesión único) e incluso un WAF robusto como F5 NGINX App Protect WAF.

La complejidad de sus aplicaciones y su arquitectura puede requerir un control más granular. Si su organización necesita un modelo de confianza cero y cifrado de extremo a extremo, considere una malla de servicios gratuita para siempre como F5 NGINX Service Mesh para controlar la comunicación entre los servicios del clúster de Kubernetes (tráfico este-oeste). Analizamos las mallas de servicios en la Unidad 4, Estrategias avanzadas de implementación de Kubernetes.

Para obtener más información sobre cómo obtener e implementar NGINX Open Source, visite nginx.org.

Para probar NGINX Ingress Controller basado en NGINX Plus con NGINX App Protect, inicie hoy mismo su prueba gratuita de 30 días o póngase en contacto con nosotros para hablar sobre sus casos de uso.

Para probar NGINX Ingress Controller basado en NGINX Open Source, consulta Versiones de NGINX Ingress Controller en nuestro repositorio de GitHub o descarga un contenedor precompilado de DockerHub.


Compartir

Artículos relacionados del blog

Únete a F5 NGINX en AppWorld 2024
NGINX | 04/01/2024

Únete a F5 NGINX en AppWorld 2024

Descubre las numerosas razones para asistir al evento insignia de F5, que incluirá un emocionante anuncio sobre la cartera de productos NGINX.

Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source
NGINX | 26/09/2023

Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source

La función de diccionario compartido permite configurar NGINX sin necesidad de reiniciarlo al renovar los certificados SSL/TLS.

Exposición de APIs en Kubernetes
NGINX | 10/03/2022

Exposición de APIs en Kubernetes

La unidad 2 de Microservices March 2022 se centra en cómo exponer tus API en Kubernetes. Aquí tienes enlaces a los recursos que necesitas: la retransmisión en directo del 14 de marzo, artículos de blog y otros recursos de preparación, y el laboratorio práctico «Protege las API de Kubernetes mediante la limitación de solicitudes».

NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto
NGINX | 23/08/2021

NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto

Hoy, en NGINX Sprint 2.0, anunciamos cómo respaldaremos nuestra visión del futuro de las aplicaciones modernas con una mayor presencia en la comunidad de código abierto, incluida la participación en el proyecto comunitario Kubernetes, nuevos proyectos de software de código abierto y la arquitectura de referencia para aplicaciones modernas.

Presentamos NGINX Plus R22
NGINX | 09/06/2020

Presentamos NGINX Plus R22

NGINX Plus R22 incorpora nuevas funcionalidades, como la compatibilidad con OCSP para verificar la revocación de certificados en TLS mutuo, el uso de varios proveedores de identidad OIDC en una configuración, el seguimiento en tiempo real de la limitación de solicitudes y conexiones en el panel de NGINX Plus y mejoras en NGINX JavaScript.

Presentamos NGINX Plus R17
NGINX | 11/12/2018

Presentamos NGINX Plus R17

NGINX Plus R17 incorpora compatibilidad con la limitación de velocidad en dos fases y con TLS 1.3, la versión más reciente del protocolo Transport Layer Security. La configuración de OpenID Connect es más sencilla y NGINX ModSecurity WAF es el doble de rápido que antes. También se ha actualizado el módulo JavaScript de NGINX.