NGINX, además de utilizarse como servidor Web estático o dinámico, dispone de otras características desarrolladas como la mayoría de servidores Web. Ofrece la funcionalidad de realizar Proxy inverso o también llamado servidor de paso. Además, esta función permite poder configurar un escenario de balanceo de carga para distribuir el tráfico para la disponibilidad, escalabilidad y rendimiento.
Un servidor de Proxy inverso es el que recibe las peticiones generalmente de clientes Web, este servidor recupera y sirve los recursos de uno o más servidores. En este artículo te enseñamos cómo realizar Proxy inverso con NGINX utilizando un único servidor Web Apache con FastCGI para la interconexión y así poder atender más peticiones simultáneas.
¿Qué es y cómo funciona el Proxy inverso?
Un servidor de paso o Proxy no genera contenido ni aloja datos, en su lugar el contenido se obtiene de los servidores Backend, que normalmente tienen conexión directa con redes internas. Por ejemplo, en un escenario Web, cuando un servidor Proxy recibe tráfico de un cliente realiza la petición a uno de estos servidores Backend para gestionarla, generar el contenido, proporcionarle una respuesta y entonces el servidor Proxy reenvía la respuesta al cliente.
Hay múltiples razones para la implementación de esta función, entre ellas, seguridad, alta disponibilidad, balanceo de carga y centralización de autorización. Normalmente en estas implementaciones en las que la arquitectura y el diseño de la infraestructura de los servidores Backend suelen estar aislados/protegidos del exterior (DMZ); la única conexión debería ser con el servidor Proxy (qué recibe y proporciona la respuesta al cliente).
Instalación y configuración de servidor Web (Apache)
Primero, actualiza los repositorios y paquetes:
# apt update && apt upgrade -yDespués, instala apache y PHP:
# apt install apache2 php-fpm php-curl php-dompdf php-mbstring php-imagick php-zip php-gd -yNormalmente se utiliza el módulo fcgi del propio repositorio de Ubuntu, pero se encuentra desactualizado:
# apt show libapache2-mod-fcgidPor lo tanto, puedes utilizar FastCGI con una versión más actualizada que se encuentra disponible en el repositorio GitHub de FastCGI-Archives. Para ello, primero ejecuta el siguiente comando para instalar unos paquetes necesarios:
# apt install unzip build-essential apache2-dev gcc make m4 autoconf automake libtool -yLuego descarga el código comprimido:
# cd /tmp/ && wget https://github.com/FastCGI-Archives/fcgi2/archive/refs/heads/master.zipDescomprímelo y accede al directorio:
# unzip master.zip && cd fcgi2-master/Configúralo:
# ./autogen.sh && ./configureE instálalo:
# make && make installPosteriormente, descarga también el módulo de rpaf para las cabeceras:
# cd /tmp/ && wget https://github.com/gnif/mod_rpaf/archive/stable.zipLuego, descomprímelo, accede al directorio descomprimido e instálalo también:
# unzip stable.zip && cd mod_rpaf-stable && make && make installPara cargarlo, crea el fichero:
# vi /etc/apache2/mods-available/rpaf.loadCon el siguiente contenido:
LoadModule rpaf_module /usr/lib/apache2/modules/mod_rpaf.soTambién crea otro fichero de nuevo para la configuración:
# vi /etc/apache2/mods-available/rpaf.confCon este contenido (IMPORTANTE: Modificar la dirección IP):
<IfModule mod_rpaf.c>
RPAF_Enable On
RPAF_Header X-Real-Ip
RPAF_ProxyIPs DIRECCION_IP
RPAF_SetHostName On
RPAF_SetHTTPS On
RPAF_SetPort On
</IfModule>Ahora actívalos y también los siguientes módulos:
# a2enconf php7.4-fpm && a2enmod rpaf actions proxy_fcgi setenvif cache cache_disk expires headersDespués, modifica el puerto por defecto de Apache del 80 al 8080:
# vi /etc/apache2/ports.confY también desactiva site por defecto:
# a2dissite 000-defaultLuego copia el fichero site por defecto (modifica la salida del ejemplo):
# cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/ejemplo.es.confEdita fichero site copiado con un editor de texto:
# vi /etc/apache2/sites-available/ejemplo.es.confPara modificar el puerto modifica "<VirtualHost *:80>" a "<VirtualHost *:8080>" y cambia el valor de ServerName por el FQDN en cuestión:
<VirtualHost *:8080>
ServerName ejemplo.es
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html/
CacheQuickHandler off
CacheLock on
CacheLockPath /tmp/
CacheIgnoreHeaders Set-Cookie
<Location />
CacheEnable disk
CacheHeader on
CacheDefaultExpire 800
CacheMaxExpire 64000
CacheIgnoreNoLastMod On
ExpiresActive on
ExpiresDefault A300
</Location>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Guarda los cambios realizados, sal del editor y luego activa el site:
# a2ensite ejemplo.es.confComprueba que la configuración es correcta del servicio Apache:
# apachectl -tY en caso positivo, recarga la configuración realizando un reinicio del servicio Apache:
# systemctl restart apache2Luego puedes comprobar que esté escuchando por el puerto modificado:
# ss -tlpn sport :8080Y también crear un fichero de información de PHP para realizar una prueba para comprobar el FastCGI:
# echo "<?php phpinfo(); ?>" | tee /var/www/html/info.phpInstalación y configuración de Proxy Inverso con NGINX
Primero instala NGINX y Certbot para adquirir un certificado SSL con Let's Encrypt:
# apt install nginx python3-certbot-nginxPosteriormente, crea el directorio para la cache de NGINX:
# mkdir -p /var/lib/nginx/cache && chown www-data /var/lib/nginx/cache && chmod 700 /var/lib/nginx/cacheElimina el site por defecto:
# rm /etc/nginx/sites-enabled/defaultCrea el fichero para el site que utilizarás (modifica el ejemplo):
# vi /etc/nginx/sites-available/ejemplo.esCon el siguiente contenido (modifica el server_name de ejemplo):
proxy_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=nginx_cache:8m max_size=50m;
proxy_cache_key "$scheme$request_method$host$request_uri$is_args$args";
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
server {
listen 80;
server_name ejemplo.es;
location / {
proxy_pass http://[::1]:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache nginx_cache;
proxy_cache_bypass $http_upgrade;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 16 16k;
proxy_busy_buffers_size 32k;
proxy_max_temp_file_size 0;
proxy_temp_file_write_size 32k;
gzip on;
gzip_min_length 1000;
gzip_comp_level 5;
gzip_proxied any;
gzip_vary on;
gzip_types
text/css
text/javascript
text/xml
text/plain
text/x-component
application/javascript
application/json
application/xml
application/rss+xml
font/truetype
font/opentype
application/vnd.ms-fontobject
image/svg+xml;
add_header X-Proxy-Cache $upstream_cache_status;
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Cache-Status $upstream_cache_status;
add_header X-Powered-By 'Clouding';
}
location ~ /\.ht {
deny all;
}
}Crea un enlace simbólico del sitio disponible en el directorio de sitios activos:
# ln -s /etc/nginx/sites-available/ejemplo.es /etc/nginx/sites-enabled/ejemplo.esFinalmente, reinicia el servicio NGINX:
# systemctl restart nginx.serviceAunque posteriormente, también puedes utilizar Certbot que anteriormente has instalado para adquirir el certificado y configurar automáticamente nginx:
# certbot --nginx --redirect -d ejemplo.esAdicionalmente, si tienes problemas de contenido mixto puedes modificar la configuración de Apache. Para ello edita el fichero de configuración:
# vi /etc/apache2/apache2.confY añade al final:
<IfModule mod_setenvif.c>
SetEnvIf X-Forwarded-Proto "^https$" HTTPS
</IfModule>Prueba de rendimiento
Como puedes comprobar con la siguiente prueba, un servidor Plesk con la misma configuración contra un servidor configurado con estas características ofrece un mejor tiempo de respuestas.
Servidor Plesk con Proxy NGINX (cache habilitada) con PHP 7.4 servido por FastCGI con Apache:
Running 30s test @ https://plesk.ejemplo.es/info.php
12 threads and 50 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 87.18ms 93.88ms 1.49s 95.08%
Req/Sec 51.35 32.85 646.00 96.83%
17578 requests in 30.07s, 1.70GB read
Socket errors: connect 0, read 0, write 0, timeout 33
Requests/sec: 584.66
Transfer/sec: 57.87MBServidor configurado mediante este artículo:
Running 30s test @ https://proxy.ejemplo.es/info.php
12 threads and 50 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 59.98ms 27.89ms 1.17s 96.40%
Req/Sec 66.73 12.59 150.00 60.93%
24035 requests in 30.10s, 1.70GB read
Requests/sec: 798.56
Transfer/sec: 57.78MBPrueba realizada con la siguiente configuración PHP en ambos servidores:
pm.max.children 26
pm.start_servers 0
pm.min_spare_servers 2
pm.max_spare_servers 8¿Lo has probado? ¡Déjanos tus comentarios! 🙂