¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Un proxy inverso delante de una aplicación

Después de esta lección: Puedo poner nginx delante de una aplicación y decir qué ve la aplicación.

Lección de 55 min13 comandosLaboratorio de refuerzo de un servidor web: corrige una configuración débil de nginx y compruébala con curl

Una sola puerta para tres aplicaciones

Un proxy inverso es un servidor que recibe las peticiones de los visitantes y las pasa a la aplicación que tiene detrás. Sirve para tener una sola puerta hacia varias aplicaciones.

Una empresa tiene una tienda, un blog y una herramienta interna, cada una en su propio puerto. Ninguna debería dar la cara a internet por sí sola. Una puerta única recibe a cada visitante, lo pasa al programa correcto y escribe un solo registro. Esta lección construye esa puerta con nginx.

Al final de esta lección

Nota

Puedo poner nginx delante de una aplicación y decir qué ve la aplicación.

Palabras clave

PalabraQué significaEjemplo
Proxy inversoun servidor que pasa las peticiones a la aplicación que tiene detrás
Upstreamla aplicación a la que un proxy pasa las peticiones
Balanceo de cargarepartir las peticiones entre varios servidores
502el estado que dice que el proxy no recibió respuesta de la aplicaciónBad Gateway
X-Forwarded-Foruna cabecera que lleva la dirección del visitante real
Recargahacer que un servidor en marcha vuelva a leer su configuración

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Un proxy inverso responde por la aplicación

Un visitante habla con el proxy inverso. El proxy pregunta a la aplicación, el upstream, y devuelve la respuesta. El visitante nunca conoce a la aplicación.

Aquí la aplicación está hecha con el propio nginx, en 127.0.0.1 puerto 9000, al que solo llega esta máquina. El proxy está en el puerto 8080. Cada uno usa un fichero.

Escribe la aplicación en el puerto 9000

Comando
docker exec web sh -c "printf '%s\n' 'server {' '  listen 127.0.0.1:9000;' '  location / { return 200 \"servidor de la app: host=\$host reenviado=\$http_x_forwarded_for desde=\$remote_addr\n\"; }' '}' > /etc/nginx/conf.d/app.conf"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el proxy en el puerto 8080

Comando
docker exec web sh -c "printf '%s\n' 'server {' '  listen 8080;' '  location / {' '    proxy_pass http://127.0.0.1:9000;' '    proxy_set_header Host \$host;' '    proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;' '  }' '}' > /etc/nginx/conf.d/proxy.conf"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Prueba la configuración antes de usarla

Comando
docker exec web nginx -t

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Recarga nginx para que lea los ficheros nuevos

Comando
docker exec web nginx -s reload

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Pregunta a través del proxy

Comando
curl -s http://web:8080/

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Pregunta directamente a la aplicación, sin el proxy

Comando
curl -sS -m 2 http://web:9000/; echo "codigo de salida $?"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Las cabeceras dicen quién pide

La aplicación vio al proxy como remitente. Para saber quién pidió de verdad, el proxy escribe la dirección del visitante en la cabecera X-Forwarded-For.

También pasa el nombre que el visitante escribió, en la cabecera Host. Sin esa línea, nginx envía en su lugar el nombre del upstream.

Envía una petición con un remitente falso

Comando
curl -s -H 'X-Forwarded-For: 203.0.113.9' http://web:8080/

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Un error frecuente

Advertencia

Mucha gente cree que la primera dirección de X-Forwarded-For es siempre el visitante real. Un visitante puede escribir esa cabecera él mismo. Fíate solo de la dirección que añadió tu propio proxy, la última de la lista.

Ejemplo resuelto: lo que el proxy pasa

Línea de proxy.confLo que aprende la aplicación
proxy_set_header Host $host;El nombre que escribió el visitante, aquí web
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;La dirección del visitante añadida al final de la lista
sin línea HostEl nombre del upstream, como grupo

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Una aplicación caída da un 502

Si el upstream no responde, el proxy no puede traer la página. Responde 502, Bad Gateway: el proxy está bien, la aplicación que tiene detrás no.

Dos aplicaciones tras un mismo nombre son balanceo de carga. nginx les da las peticiones por turnos, así que una puede caer y la otra sigue respondiendo.

Apunta el proxy a un puerto muerto

Comando
docker exec web sh -c "printf '%s\n' 'server {' '  listen 8080;' '  location / { proxy_pass http://127.0.0.1:9009; }' '}' > /etc/nginx/conf.d/proxy.conf && nginx -t && nginx -s reload"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Pregunta por el proxy y lee el estado

Comando
curl -s -i http://web:8080/

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Lee lo que nginx escribió del fallo

Comando
docker logs web 2>&1 | grep -F "Connection refused" | tail -n 1

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Pon dos aplicaciones tras un nombre

Comando
docker exec web sh -c "printf '%s\n' 'upstream grupo {' '  zone grupo 64k;' '  server 127.0.0.1:9000;' '  server 127.0.0.1:9001;' '}' 'server {' '  listen 127.0.0.1:9001;' '  location / { return 200 \"segundo servidor de la app\n\"; }' '}' > /etc/nginx/conf.d/pool.conf && sed -i 's#127.0.0.1:9009#grupo#' /etc/nginx/conf.d/proxy.conf && nginx -t && nginx -s reload"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Pregunta cuatro veces y mira los turnos

Comando
for i in 1 2 3 4; do curl -s http://web:8080/; done

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Borra los tres ficheros y recarga

Comando
docker exec web sh -c "rm -f /etc/nginx/conf.d/app.conf /etc/nginx/conf.d/proxy.conf /etc/nginx/conf.d/pool.conf; nginx -s reload"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Para ir más lejos: la respuesta host=grupo

Mira otra vez las cuatro respuestas. Un tipo de respuesta dice host=grupo y no host=web.

¿Qué fila de la tabla de cabeceras lo explica? Escribe la única línea que añadirías al bloque location del proxy para que la aplicación vuelva a decir host=web.