2021-10-17 17:25 (Ultima actualización: 2023-05-23 18:42)
Nginx: Autenticación de usuarios mediante certificados SSL
NGINX nos da la posibilidad de utilizar certificados de usuario para autenticar sitios web, incluso sitios que se están interceptando mediante proxy. Ésta es una alternativa muy interesante para proteger sitios web que no dispongan de mecanismos de autenticación adecuados u obsoletos, como por ejemplo la autenticación básica HTTP.
Para esta configuración necesitamos tener accesible a NGINX un certificado CA que será contra el que se validen los certificados de usuario. Además los usuarios habrán de tener instalados en sus navegadores y equipos sus certificados de usuario firmados por la CA anterior.
Creación de la CA
Clave privada
openssl genrsa -des3 -out ca.key 4096
Certificado
openssl req -new -x509 -days 365 -key ca.key -out ca.crt
Creación del certificado cliente
Clave privada
openssl genrsa -des3 -out user.key 4096
Petición de certificado
openssl req -new -key user.key -out user.csr
Firma del certificado por la CA
openssl x509 -req -days 365 -in user.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out user.crt
Empaquetando certificado y clave
openssl pkcs12 -export -out user.pfx -inkey user.key -in user.crt -certfile ca.crt
Este fichero, user.pfx será el que cada usuario instale en su navegador para autenticarse contra el servidor o el proxy
Configuración de NGINX
server {
listen 80;
server_name server.example.com;
return 301 https://server.example.com$request_uri;
}
server {
listen 443 ssl;
ssl_certificate /usr/local/etc/ssl/fullchain.pem;
ssl_certificate_key /usr/local/etc/ssl/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_client_certificate /usr/local/etc/nginx/ca.crt;
ssl_verify_client optional;
server_name server.example.com;
location / {
if ($ssl_client_verify != SUCCESS) {
return 403;
}
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;
# Fix the "reverse proxy broken" error.
proxy_pass http://localhost:8080;
proxy_read_timeout 90;
# Web sockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect http://localhost:8080 https://server.example.com;
}
}
Esta configuración redirige HTTP a HTTPS por una parte, y por otra ya en HTTPS realiza la validación del certificado cliente, retornando un código de estado 403 NOT FOUND, si el certificado no se presenta, o no es válido.
Nota: En este caso el servidor es un **proxy** ya que el servidor destino no dispone de HTTPS, así que es ésta instancia de **NGINX** la que realiza el **SSL offload** y además se encarga de la validación de usuario que comentamos.