Tanto el software de código abierto NGINX como NGINX Plus son muy seguros y confiables como servidores web, servidores proxy inversos y cachés para su contenido. Para obtener protección adicional contra el acceso de clientes no autorizados, puede usar directivas del módulo Secure Link para exigir que los clientes incluyan una cadena hash específica en la URL del activo que están solicitando.
En esta publicación de blog, analizaremos cómo configurar los dos métodos implementados en el módulo Enlace seguro. Los fragmentos de configuración de muestra protegen los archivos HTML y de listas de reproducción multimedia, pero se pueden aplicar a cualquier tipo de URL HTTP. Los métodos se aplican tanto a NGINX como a NGINX Plus, pero por razones de brevedad nos referiremos solo a NGINX Plus en el resto del blog.
El módulo Secure Link verifica la validez de un recurso solicitado comparando una cadena codificada en la URL de la solicitud HTTP con la cadena que calcula para esa solicitud. Si un enlace tiene una vida útil limitada y el tiempo ha expirado, el enlace se considera obsoleto. El estado de estas comprobaciones se captura en la variable $secure_link
y se utiliza para controlar el flujo de procesamiento.
Como se mencionó, el módulo proporciona dos métodos. Sólo se puede configurar uno de ellos en un contexto http
, servidor
o ubicación
determinado.
El primer modo, y más simple, se habilita mediante la directiva secure_link_secret
. La cadena codificada es un hash MD5 calculado sobre la concatenación de dos cadenas de texto: la parte final de la URL y una palabra secreta definida en la configuración de NGINX Plus. (Para obtener detalles específicos sobre la primera cadena de texto, consulte Uso de URL seguras básicas ).
Para acceder al recurso protegido, el cliente debe incluir el hash justo después del prefijo de la URL, que es una cadena arbitraria sin barras. En esta URL de ejemplo, el prefijo es videos y el recurso protegido es el archivo bunny.m3u8 :
/videos/80e2dfecb5f54513ad4e2e6217d36fd4/hls/bunny.m3u8
Un caso de uso para este método es cuando un usuario carga una imagen o un documento a un servidor para compartir, pero desea evitar que cualquiera que conozca el nombre del archivo acceda a él hasta que se publique el enlace oficial.
El segundo método, más flexible, está habilitado por las directivas secure_link
y secure_link_md5
. Aquí la cadena codificada es un hash MD5 de variables definidas en el archivo de configuración NGINX Plus. Lo más común es incluir la variable $remote_addr
para restringir el acceso a una dirección IP de cliente en particular, pero se pueden usar otros valores, por ejemplo $http_user_agent
, que captura el encabezado User-Agent
y, por lo tanto, restringe el acceso a ciertos navegadores.
Opcionalmente, puede especificar una fecha de expiración después de la cual la URL ya no funcionará incluso si el hash es correcto.
El cliente debe agregar el argumento md5 a la URL de solicitud para especificar el hash. Si se incluye una fecha de vencimiento en la cadena codificada, el cliente también debe agregar el argumento de vencimiento para especificar la fecha, como en esta URL de ejemplo para solicitar el archivo protegido pricelist.html :
/files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740
El módulo Secure Link está incluido en los binarios NGINX de código abierto prediseñados de nginx.org , los paquetes NGINX proporcionados por los proveedores de sistemas operativos y en NGINX Plus . No se incluye de forma predeterminada cuando se compila NGINX desde la fuente; habilítelo incluyendo el argumento --with-http_secure_link_module
en el comando de configuración
.
La forma más básica de proteger las URL es con la directiva secure_link_secret
. En el siguiente fragmento de muestra, protegemos un archivo de lista de reproducción de medios de transmisión en vivo HTTP (HLS) llamado /bunny.m3u8 . Se almacena en el directorio /opt/secure/hls , pero se expone a los clientes que utilizan una URL que comienza con el prefijo videos .
servidor {
escuchar 80;
nombre_del_servidor demostración_de_enlace_seguro;
ubicación /videos {
secreto_de_enlace_seguro enigma;
si ($enlace_seguro = "") { devolver 403; }
reescribir ^ /seguro/$enlace_seguro;
}
ubicación /seguro {
interno;
raíz /opt;
}
}
Con esta configuración, para acceder al archivo /opt/secure/hls/bunny.m3u8 los clientes deben presentar la siguiente URL:
/videos/80e2dfecb5f54513ad4e2e6217d36fd4/hls/bunny.m3u8
La cadena con hash viene justo después del prefijo, que es una cadena arbitraria sin barras (aquí, videos ).
El hash se calcula en una cadena de texto que concatena dos elementos:
secure_link_secret
, aquí enigma
.Si la URL de solicitud del cliente no tiene el hash correcto, NGINX Plus establece la variable $secure_link
en la cadena vacía. El si
La prueba falla y NGINX Plus devuelve el 403
Prohibido
Código de estado en la respuesta HTTP.
De lo contrario (lo que significa que el hash es correcto), la directiva de reescritura
reescribe la URL; en nuestro ejemplo, /secure/hls/bunny.m3u8 (la variable $secure_link
captura la parte de la URL que sigue al hash). Las URL que comienzan con /secure son manejadas por el segundo bloque de ubicación
. La directiva raíz
en ese bloque establece /opt como el directorio raíz para los archivos solicitados y la directiva interna
especifica que el bloque se usa solo para solicitudes generadas internamente.
Para obtener el hash MD5 en formato hexadecimal que el cliente debe incluir en la URL, ejecutamos el comando openssl
md5
con la opción -hex
:
# echo -n 'hls/bunny.m3u8enigma' | openssl md5 -hex (entrada estándar)= 80e2dfecb5f54513ad4e2e6217d36fd4
Para obtener una discusión sobre cómo generar hashes mediante programación, consulte Generación del hash mediante programación .
Los siguientes comandos curl
de muestra muestran cómo responde el servidor a diferentes URL seguras.
Si la URL incluye el hash MD5 correcto, la respuesta es200
DE ACUERDO
:
# curl -I http://demo-de-enlace-seguro/videos/80e2dfecb5f54513ad4e2e6217d36fd4/hls/bunny.m3u8 | head -n 1 HTTP/1.1 200 OK
Si el hash MD5 es incorrecto, la respuesta es403
Prohibido
:
# curl -I http://demo-de-enlace-seguro/videos/2c5e80de986b6fc80dd33e16cf824123/hls/bunny.m3u8 | head -n 1 HTTP/1.1 403 Prohibido
Si el hash de bunny.m3u8 se utiliza para un archivo diferente, la respuesta también es403
Prohibido
:
# curl -I http://demo-de-enlace-seguro/videos/80e2dfecb5f54513ad4e2e6217d36fd4/hs/oven.m3u8 | head -n 1 HTTP/1.1 403 Prohibido
El método más flexible para proteger URL utiliza las directivas secure_link
y secure_link_md5
. En este ejemplo, los usamos para permitir el acceso al archivo /var/www/files/pricelist.html solo desde clientes en la dirección IP 192.168.33.14 y solo hasta el 31 de diciembre de 2016.
Nuestro servidor virtual escucha en el puerto 80 y maneja todas las solicitudes HTTP seguras bajo el bloque de ubicación
/ archivos
, donde la directiva raíz
establece / var / www como el directorio raíz para los archivos solicitados.
La directiva secure_link
define dos variables que capturan argumentos en la URL de la solicitud: $arg_md5
se establece en el valor del argumento md5 y $arg_expires
en el valor del argumento expires .
La directiva secure_link_md5
define la expresión que se codifica para generar el valor MD5 para la solicitud; durante el procesamiento de la URL, el codificado se compara con el valor de $arg_md5
. La expresión de muestra aquí incluye el tiempo de expiración transcurrido en la solicitud (capturado en la variable $secure_link_expires
), la URL ( $uri
), la dirección IP del cliente ( $remote_addr
) y la palabra enigma
.
servidor {
escuchar 80;
nombre_del_servidor_demo_de_enlace_seguro;
ubicación /archivos {
raíz /var/www;
enlace_seguro $arg_md5,$arg_expires;
enlace_seguro_md5 "$enlace_seguro_expires$uri$dirección_remota enigma";
si ($enlace_seguro = "") { devolver 403; }
si ($enlace_seguro = "0") { devolver 410; }
}
}
Con esta configuración, para acceder a /var/www/files/pricelist.html , un cliente con dirección IP 192.168.33.14 debe enviar esta URL de solicitud antes del sábado 31 de diciembre de 2016 a las 23:59:00 UTC :
/files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740
Si el hash en la URL enviada por el cliente (capturado en la variable $arg_md5
) no coincide con el hash calculado a partir de la directiva secure_link_md5
, NGINX Plus establece la variable $secure_link
en la cadena vacía. La prueba if
falla y NGINX Plus devuelve el403
Código de estado prohibido
en la respuesta HTTP.
Si los hashes coinciden pero el enlace ha expirado, NGINX Plus establece el $enlace seguro
variable a 0
;de nuevo el si
La prueba falla, pero esta vez NGINX Plus devuelve el resultado. 410
Desaparecido
Código de estado en la respuesta HTTP.
Ahora veamos cómo un cliente calcula los argumentos md5 y caduca para incluirlos en la URL.
El primer paso es determinar el equivalente en tiempo Unix de la fecha de expiración, porque ese valor está incluido en la expresión hash en forma de la variable $secure_link_expires
. Para obtener la hora Unix (la cantidad de segundos desde Epoch (1970-01-01 00:00:00 UTC)) , utilizamos el comando date
con la opción -d
y el especificador de formato +%s
.
En nuestro ejemplo, configuramos el tiempo de expiración en sábado 31 de diciembre de 2016 a las 23:59:00 UTC , por lo que el comando es:
# fecha -d "2016-12-31 23:59" +%s1483228740
El cliente incluye este valor como el argumento expires=1483228740 en la URL de la solicitud.
Ahora ejecutamos la cadena definida por la directiva secure_link_md5
– $secure_link_expires$uri$remote_addr
enigma
– a través de tres comandos:
openssl
md5
con la opción -binary
genera el hash MD5 en formato binario.openssl
base64
aplica codificación Base64 al valor hash.tr
reemplazan el signo más ( +
) con el guion ( -
) y la barra ( /
) con el guión bajo ( _
), y eliminan el signo igual ( =
) del valor codificado.Para nuestro ejemplo, el comando completo es:
# echo -n '1483228740/files/pricelist.html192.168.33.14 enigma' | openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d = AUEnXC7T-Tfv9WLsWbf-mw
El cliente incluye este valor como argumento md5=AUEnXC7T-Tfv9WLsWbf-mw en la URL de la solicitud.
Si su servidor web NGINX Plus sirve contenido dinámico desde un servidor de aplicação , tanto NGINX Plus como el servidor de aplicação deben usar la misma URL segura. Puede generar el hash para el argumento md5 en la URL mediante programación. La siguiente función Node.js genera un hash que coincide con el definido en el fragmento de configuración de NGINX Plus anterior. Toma un tiempo de expiración, una URL, una dirección IP del cliente y una palabra secreta como argumentos y devuelve el hash MD5 en formato binario codificado en Base64.
var crypto = require("crypto");
función generateSecurePathHash(caduca, url, ip_del_cliente, secreto) {
if (!caduca || !url || !ip_del_cliente || !secreto) {
devuelve indefinido;
}
var entrada = caduca + url + ip_del_cliente + " " + secreto;
var binaryHash = crypto.createHash("md5").update(input).digest();
var valorbase64 = new Buffer(binaryHash).toString('base64');
devuelve valorbase64.replace(/=/g, '').replace(/+/g, '-').replace(///g, '_');
}
Para calcular el hash de nuestro ejemplo actual, pasamos estos argumentos:
generateSecurePathHash(nueva fecha('12/31/2016 23:59:00').getTime()), '/files/pricelist.html', “192.168.33.14”, "enigma");
Los siguientes comandos curl
de muestra muestran cómo responde el servidor a las URL seguras.
Si un cliente con la dirección IP 192.168.33.14 incluye el hash MD5 y el tiempo de expiración correctos, la respuesta es200
DE ACUERDO
:
# curl -I --interface "192.168.33.14" 'http://demo-de-enlace-seguro/archivos/lista-de-precios.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740' | head -n 1 HTTP/1.1 200 OK
Si un cliente con una dirección IP diferente envía la misma URL, la respuesta es403
Prohibido
:
# curl -I --interface "192.168.33.33" 'http://secure-link-demo/files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740' | head -n 1 HTTP/1.1 403 Prohibido
Si el valor hash del argumento md5 es incorrecto, la respuesta es403
Prohibido
:
# curl -I --interface "192.168.33.14" 'http://secure-link-demo/files/pricelist.html?md5=qeUNjiY2FTIVMaXUsxG-7w&expires=1483228740' | head -n 1 HTTP/1.1 403 Prohibido
Si la URL ha expirado (la fecha representada por el argumento de expiración es del pasado), la respuesta es410
Desaparecido
:
# curl -I --interface "192.168.33.14" 'http://secure-link-demo/files/pricelist.html?md5=Z2rNva2InyVcRTlhqAkT4Q&expires=1467417540' | head -n 1 HTTP/1.1 410 Ignorado
Aquí hay otro ejemplo de una URL segura con fecha de vencimiento, utilizada para proteger tanto la lista de reproducción de un recurso multimedia como los archivos de segmento.
Una diferencia con el ejemplo anterior es que aquí agregamos un bloque de configuración de mapa
para eliminar la extensión de la lista de reproducción (archivo .m3u8 ) y de los segmentos HLS (archivos .ts ) mientras capturamos el nombre del archivo en la variable $file_name
, que se pasa a la directiva secure_link_md5
. Esto sirve para proteger las solicitudes de los segmentos .ts individuales así como de la lista de reproducción.
Otra diferencia con el primer ejemplo es que incluimos la variable $http_user_agent
(que captura el encabezado User-Agent
) en la directiva secure_link_md5
, para restringir el acceso a clientes en navegadores web específicos (por ejemplo, para que la URL funcione en Safari pero no en Chrome o Firefox).
map $uri $nombre_archivo {
predeterminado ninguno;
"~*/s/(?<nombre>.*).m3u8" $nombre;
"~*/s/(?<nombre>.*).ts" $nombre;
}
servidor {
escuchar 80;
nombre_servidor secure-link-demo;
ubicación /s {
raíz /opt;
enlace_seguro $arg_md5,$arg_expires;
enlace_seguro_md5 "$enlace_seguro_expires$nombre_archivo$http_user_agent enigma";
si ($enlace_seguro = "") { devolver 403; }
si ($enlace_seguro = "0") { devolver 410; }
}
}
El módulo Secure Link de NGINX le permite proteger archivos contra acceso no autorizado agregando datos codificados como el hash de una parte específica de la URL. Agregar un tiempo de expiración también limita el tiempo de validez de los enlaces, para una seguridad aún mayor.
Para probar NGINX Plus, comience hoy su prueba gratuita de 30 días o contáctenos para analizar sus casos de uso.
"Esta publicación de blog puede hacer referencia a productos que ya no están disponibles o que ya no reciben soporte. Para obtener la información más actualizada sobre los productos y soluciones F5 NGINX disponibles, explore nuestra familia de productos NGINX . NGINX ahora es parte de F5. Todos los enlaces anteriores de NGINX.com redirigirán a contenido similar de NGINX en F5.com.