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
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Proxy inverso | un servidor que pasa las peticiones a la aplicación que tiene detrás | |
| Upstream | la aplicación a la que un proxy pasa las peticiones | |
| Balanceo de carga | repartir las peticiones entre varios servidores | |
| 502 | el estado que dice que el proxy no recibió respuesta de la aplicación | Bad Gateway |
| X-Forwarded-For | una cabecera que lleva la dirección del visitante real | |
| Recarga | hacer 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
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
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
docker exec web nginx -tSe 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
docker exec web nginx -s reloadSe 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
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
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
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.conf | Lo 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 Host | El 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
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
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
docker logs web 2>&1 | grep -F "Connection refused" | tail -n 1Se 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
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
for i in 1 2 3 4; do curl -s http://web:8080/; doneSe 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
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.