Skip to content

Nginx

El concepto de proxy inverso, en pocas palabras, permite el enrutamiento de direcciones publicas a direcciones (y puertos) definidas por servicios internos en una máquina, brindando seguridad y organización de las aplicaciones o servicios. Nginx no sólo aplica este concepto, sino tambien otros aspectos como el de balanceador de carga y manejo de SSL para protocolo https.

Para la plataforma OnMind se ha usado para orientar los servicios modulares en sus origenes. Veamos a continuación aspectos claves sobre esta tecnología.

Instalación de Nginx (para proxy inverso/reverso)

Con Nginx, OnMind simplifica su implementación de seguridad acogiendo el acompañamiento y la buena práctica de un proxy reverso, dejando la aplicacion aparentemente para uso interno de la máquina (localhost) y exponiéndola de modo encaminado (sin publicar los puertos), así también se puede dejar la configuración de certificados de seguridad a Nginx (actividad correspondiente a la administración de infraestructura). Incluso se posibilitaría crecimiento horizontal usando Nginx Plus (Nginx+).

Para instalar en Linux Ubuntu/Debian ejecutamos:

bash
sudo apt update
sudo apt install -y nginx

De modo semejante, instalar Nginx en Amazon Linux 2 es muy sencillo, usando los extras proporcionados se ejecutarían los siguiente comandos:

bash
sudo amazon-linux-extras install -y nginx1.12
sudo systemctl start nginx

Podemos revisar que se encuentre expuesto el servicio abriendo en nuestro equipo un navegador y consultando el dominio o IP de la máquina. Para habilitar inicio de Nginx cuando reinicie el sistema, ejecutamos:

bash
sudo systemctl enable nginx

Configuración inicial de Nginx con autofirmado (self-signed)

Dado que requerimos usar protocolo https, de modo provisional (mientras se obtiene o adquiere certificado, actividad correspondiente a la administración de infraestructura), podemos hacer lo siguiente:

bash
sudo mkdir -p /etc/nginx/snippets
sudo mkdir /etc/ssl/private
sudo chmod 700 /etc/ssl/private
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx.key -out /etc/ssl/certs/nginx.crt
sudo mkdir -p /etc/nginx/snippets
sudo cp /etc/nginx/nginx.conf /etc/nginx/snippets/bakup_nginx.conf

Usualmente, el comando sudo openssl req pide 7 datos para generar el certificado (Country Name, State, Locality Name, Organization Name, Organizational Unit Name, Common Name, Email Address).

Adicionalmente, y aunque toma minutos, procedemos a crear DH (Diffie-Hellman) fuerte así:

bash
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Procedemos a editar o crear archivo para ssl en Nginx de la siguiente manera:

bash
sudo vi /etc/nginx/conf.d/ssl.conf

Luego incluimos las siguientes líneas con la respectiva referencia de auto-firmado (recuerda asignar el servidor respectivo), así:

nginx
server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    server_name localhost;

    ssl_certificate /etc/ssl/certs/nginx.crt;
    ssl_certificate_key /etc/ssl/private/nginx.key;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
}

Las líneas que se relacionan con llaves las dejaremos luego dentro de un archivo de configuracion o "snippet" (/etc/nginx/snippets/self-signed.conf).

Podemos crear otro “snippet” con parámetros para SSL, por ejemplo:

bash
sudo vi /etc/nginx/snippets/ssl-params.conf

Luego incluimos la siguiente configuración de ejemplo para sitio seguro:

nginx
#server_tokens off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_prefer_server_ciphers on;
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";

Adicionalmente, tomando como ejemplo OnMind, crearemos también un archivo específico de configuración, así:

bash
sudo vi /etc/nginx/snippets/onmind.conf

Y colocamos el contenido de configuración de los servicios respectivos, por ejemplo:

nginx
    location /go/ {
        proxy_pass http://127.0.0.1:9999/;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_ssl_session_reuse off;
        proxy_redirect off;
    }

    location /box { proxy_pass http://127.0.0.1:9999/box; }

    location /web { proxy_pass http://127.0.0.1:9999/web; }

Nótese que en el ejemplo anterior, la primera ruta tiene una configuración detallada para la traducción de puertos con proxy inverso mientras las últimas rutas tienen una configuración más simple dado que sólo redirijen a otra ruta.

Incluimos invocación de "snippets" en archivo de configuración de Nginx (/etc/nginx/conf.d/ssl.conf) quedando así:

nginx
server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    server_name localhost;

    include snippets/self-signed.conf;
    include snippets/ssl-params.conf;
    include snippets/onmind.conf;

    root /opt/web;

    error_page 404 =200 /index.html;

    location / {
    }
}

Para un servidor en producción, esto debería cambiar asociando los certificados adquiridos. Veamos el siguiente ejemplo:

nginx
server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    server_name example.com www.example.com;

    include snippets/well-signed.conf;
    include snippets/ssl-params.conf;
    include snippets/onmind.conf;

    error_page 404 =200 /index.html;

    location / {
        root /opt/web;
        index index.html;
    }

    location ^~ /.well-known/ {
        allow all;
    }
}

Nótese que ahora se incluye el archivo well-signed.conf, este debe contener la líneas para reportar la variable ssl_certificate y ssl_certificate_key con los rutas respectivas.

En el archivo de configuración de Nginx (/etc/nginx/nginx.conf) podríamos modificar la primera linea (que corresponde a la variable user) asignando root en lugar de cualquier otro usuario (nginx, www-data). Se edita y reinicia el servicio, por ejemplo:

bash
sudo vi /etc/nginx/nginx.conf
sudo systemctl restart nginx

Dado lo anterior, también se ejecuta lo siguiente:

bash
sudo mkdir -p /opt/web
sudo chown -R appadmin:root /opt/web
sudo chmod -R 755 /opt/web
echo "<html><head><meta http-equiv=\"refresh\" content=\"0; URL='/net/portal'\" /></head></html>" > /opt/web/index.html

El usuario appadmin representa un superusario distinto a root, orientado a la aplicación. La línea con el comando echo crea el archivo index.html para Nginx, redirigiéndose a la página de bienvenida. También se podría haber creado una regla en el archivo ssl.conf, incorporando al inicio del archivo las siguientes líneas:

nginx
server {
    listen 80;
    server_name localhost;
    return 301 https://$host$request_uri;
}

Debe tenerse presente que en un entorno de producción, la linea correspondiente a la variable server_name del archivo ssl.conf deberá modificarse para que en lugar de localhost se asigne el dominio respectivo (o una IP).

Finalmente, se verifica que todo esté correcto y se reinicia el servicio con los comandos siguientes:

bash
sudo nginx -t
sudo systemctl restart nginx