Se habla mucho en estos momentos en torno al Sistema de Nombres de Dominio (DNS) y se proponen cambios masivos para un protocolo de 36 años de antigüedad . El servicio de nombres de Internet, que tiene sus orígenes en ARPANET , nunca ha tenido problemas de compatibilidad con versiones anteriores desde su inicio. Pero nuevas propuestas para cambiar el mecanismo de transporte del DNS podrían estar a punto de cambiar eso.
En esta publicación, analizo dos tecnologías emergentes para proteger DNS, DNS sobre TLS (DoT) y DNS sobre HTTPS (DoH), y muestro cómo implementarlas utilizando NGINX Open Source y NGINX Plus.
[ Editor : esta publicación es una de varias que exploran casos de uso del módulo JavaScript de NGINX. Para obtener una lista completa, consulte Casos de uso del módulo JavaScript NGINX .
El código en esta publicación se actualiza para usar la directiva js_import
, que reemplaza la directiva js_include
obsoleta en NGINX Plus R23<.htmla> y versiones posteriores. Para obtener más información, consulte la documentación de referencia del módulo JavaScript de NGINX : la sección Configuración de ejemplo muestra la sintaxis correcta para la configuración de NGINX y los archivos JavaScript.]
DNS fue el segundo intento de crear un servicio de nombres para la Internet temprana de la Agencia de Proyectos de Investigación Avanzada (ARPA); el primero fue el protocolo de servidor de nombres de Internet publicado por John Postel en 1979 como IEN-116. . El DNS fue diseñado para ser jerárquico y proporcionar una estructura para que los nombres de host se descentralicen en zonas y sean administrados por muchas autoridades separadas. Las primeras RFC para DNS se publicaron en 1983 (RFC882 y883 ), y si bien han tenido varias extensiones a lo largo de los años, un cliente escrito según los estándares definidos entonces todavía funcionaría hoy.
Entonces ¿por qué cambiar el protocolo ahora? Funciona claramente como está previsto, lo que justifica la confianza de sus autores, que estaban tan seguros de tener razón que no incluyeron un número de versión en el paquete DNS (no puedo pensar en muchos otros protocolos que puedan hacer esa afirmación). El DNS fue concebido en una época más inocente, cuando la mayoría de los protocolos eran en texto claro y a menudo en código ASCII de 7 bits , pero la Internet de hoy es un lugar mucho más aterrador que ARPANET de los años 1980. Hoy en día, la mayoría de los protocolos han adoptado la seguridad de la capa de transporte (TLS) para fines de cifrado y verificación. Los críticos del DNS sostienen que ya es hora de incorporar algunas protecciones de seguridad adicionales.
Así, de la misma forma que el DNS fue el segundo intento de proporcionar un protocolo de servicio de nombres para Internet, el DNS sobre TLS (DoT) y el DNS sobre HTTPS (DoH) están surgiendo como segundos intentos de asegurar el protocolo DNS. El primer intento fue una extensión conocida como DNSSEC , y aunque la mayoría de los dominios de nivel superior (TLD) utilizan DNSSEC, nunca tuvo la intención de cifrar los datos transportados en los paquetes DNS; solo proporciona verificación de que los datos no fueron manipulados. DoT y DoH son extensiones de protocolo que envuelven el DNS dentro de un túnel TLS y, si se adoptan, pondrán fin a 36 años de compatibilidad con versiones anteriores.
Creo que DoT se considera en gran medida una extensión sensata. La Autoridad de Números Asignados de Internet (IANA) ya le ha asignado su propio número de puerto (TCP/853) y simplemente envuelve los paquetes DNS TCP dentro de un túnel cifrado con TLS. Muchos protocolos han hecho esto antes: HTTPS es HTTP dentro de un túnel TLS, y SMTPS, IMAPS y LDAPS son versiones seguras de esos protocolos. DNS siempre ha utilizado UDP (o TCP en ciertos casos) como protocolo de transporte, por lo que agregar el contenedor TLS no es un cambio importante.
El DoH, por otro lado, es un poco más controvertido. DoH toma un paquete DNS y lo envuelve dentro de una solicitud HTTP GET
o POST
, que luego se envía mediante HTTP/2 o superior a través de una conexión HTTPS. A todos los efectos, esto parece ser igual que cualquier otra conexión HTTPS y es imposible para las empresas o proveedores de servicios ver qué solicitudes se están realizando. Mozilla y otros partidarios dicen que esta práctica aumenta la privacidad de los usuarios al mantener privados de miradas indiscretas los sitios que visitan.
Pero eso no es del todo cierto. Los críticos de DoH señalan que no es exactamente el Tor del DNS porque cuando el navegador finalmente realiza la conexión con el host que ha buscado mediante DoH, la solicitud casi con certeza utilizará la extensión SNI ( Server Name Indication ) TLS, que incluye el nombre del host y se envía en texto sin cifrar. Además, si el navegador intenta validar el certificado del servidor utilizando el Protocolo de estado de certificado en línea (OSCP), es muy probable que ese proceso también se realice en texto sin cifrar. Por lo tanto, cualquier persona con la capacidad de monitorear búsquedas de DNS también tiene la capacidad de leer el SNI en la conexión o el nombre del certificado en la validación de OCSP.
Para muchas personas, el mayor problema con DoH es que los proveedores de navegadores eligen de forma predeterminada los servidores DNS a los que se envían las solicitudes DoH realizadas por sus usuarios (en el caso de los usuarios de Firefox en EE. UU., por ejemplo, los servidores DNS pertenecen a Cloudflare ). El operador de los servidores DNS puede ver la dirección IP del usuario y los nombres de dominio de los sitios a los que realiza solicitudes. Puede que esto no parezca mucho, pero los investigadores de la Universidad de Illinois descubrieron que es posible deducir qué sitios web ha visitado una persona simplemente con las direcciones de destino de las solicitudes de elementos de una página web, la llamada huella digital de carga de página. Esa información puede luego utilizarse para “elaborar un perfil del usuario y orientarlo a fines publicitarios”.
DoT y DoH no son intrínsecamente malos, y existen casos de uso en los que aumentan la privacidad del usuario. Sin embargo, existe un consenso creciente de que un servicio DoH público y centralizado es malo para la privacidad del usuario, y recomendamos evitar usarlo a toda costa.
En cualquier caso, es probable que para sus sitios y aplicaciones usted administre sus propias zonas DNS: algunas públicas, algunas privadas y algunas con un horizonte dividido. En algún momento es posible que decidas que quieres ejecutar tu propio servicio DoT o DoH. Aquí es donde NGINX puede ayudar.
Las mejoras de privacidad proporcionadas por DoT ofrecen algunas grandes ventajas para la seguridad del DNS, pero ¿qué sucede si su servidor DNS actual no ofrece soporte para DoT? NGINX puede ayudar aquí proporcionando una puerta de enlace entre DoT y el DNS estándar.
O tal vez le guste el potencial de DoH para romper el firewall en los casos en que el puerto DoT pueda estar bloqueado. Nuevamente NGINX puede ayudar al proporcionar una puerta de enlace DoH a DoT/DNS .
El módulo NGINX Stream (TCP/UDP) admite la terminación SSL, por lo que es realmente sencillo configurar un servicio DoT. Puede crear una puerta de enlace DoT simple con solo unas pocas líneas de configuración NGINX.
Necesita un bloque ascendente
para sus servidores DNS y un bloque de servidor
para la terminación TLS:
Por supuesto, también podemos ir en la otra dirección y reenviar las solicitudes DNS entrantes a un servidor DoT ascendente. Sin embargo, esto es menos útil porque la mayor parte del tráfico DNS es UDP y NGINX solo puede traducir entre DoT y otros servicios TCP, como DNS basado en TCP.
En comparación con una puerta de enlace DoT, la configuración de una puerta de enlace DoH simple es un poco más compleja. Necesitamos un servicio HTTPS y un servicio Stream, y usamos código JavaScript y el módulo JavaScript NGINX<.htmla> (njs) para traducir entre los dos protocolos. La configuración más sencilla es:
Esta configuración realiza la cantidad mínima de procesamiento necesaria para enviar el paquete al servicio DNS. Este caso de uso supone que el servidor DNS ascendente realiza otras funciones de filtrado, registro o seguridad.
El script JavaScript utilizado en esta configuración ( nginx_stream.js ) incluye varios archivos de módulo de biblioteca DNS. Dentro del módulo dns.js , la variable dns_decode_level
establece cuánto procesamiento se realiza en los paquetes DNS. El procesamiento de paquetes DNS obviamente perjudica el rendimiento. Si está utilizando una configuración como la anterior, configure dns_decode_level
en0
.
Aquí en NGINX somos bastante buenos en HTTP, por lo que creemos que usar NGINX solo como una puerta de enlace DoH simple es una oportunidad desperdiciada.
El código JavaScript utilizado aquí se puede configurar para realizar una decodificación total o parcial de los paquetes DNS. Esto nos permite crear un caché de contenido HTTP para las consultas DoH con encabezados Expires y Cache-Control
configurados en función de los TTL mínimos de las respuestas DNS.
A continuación se muestra un ejemplo más completo, con optimización de conexión adicional y soporte para almacenamiento en caché y registro de contenido:
Si tiene una suscripción a NGINX Plus, puede combinar los ejemplos anteriores con algunas de las funciones más avanzadas de NGINX Plus, como verificaciones de estado activas y alta disponibilidad, o incluso usar la API de purga de caché para administrar las respuestas DoH en caché.
También es posible utilizar el almacén de clave-valor NGINX Plus para crear un sistema de filtrado DNS que proteja a los usuarios de dominios maliciosos al devolver una respuesta DNS que impida eficazmente el acceso a ellos. Administra el contenido del almacén de clave-valor de forma dinámica con la API RESTful NGINX Plus .
Definimos dos categorías de dominios maliciosos: “bloqueados” y “agujero negro”. El sistema de filtrado de DNS maneja una consulta DNS sobre un dominio de forma diferente según su categoría:
NXDOMAIN
(que indica que el dominio no existe)A
de 0.0.0.0 en respuesta a solicitudes de registros A
, o un único registro AAAA
de :: en respuesta a solicitudes de registros AAAA
(IPv6); para otros tipos de registros, devuelve una respuesta que contiene cero respuestas.Cuando nuestro filtro DNS recibe una solicitud, primero busca una clave que coincida exactamente con el FQDN consultado. Si encuentra uno, “depura” (bloquea o bloquea) la solicitud según lo especificado por el valor asociado. Si no hay una coincidencia exacta, busca el nombre de dominio en dos listas (una de dominios bloqueados y otra de dominios bloqueados) y depura la solicitud de la forma adecuada si hay una coincidencia.
Si el dominio consultado no es malicioso, el sistema lo reenvía a un servidor DNS de Google para su procesamiento regular.
Definimos los dominios que consideramos maliciosos en dos tipos de entradas en el almacén de clave-valor NGINX Plus:
bloqueado
o agujero negro
blocking_domains
y blackholed_domains
, cada una asignada a una lista de dominios en formato de valores separados por comas (CSV) La siguiente configuración para el almacén de valores clave va en el contexto del flujo
. La directiva keyval_zone
asigna un bloque de memoria para el almacén de clave-valor, llamado dns_config . La primera directiva keyval
carga cualquier par clave-valor FQDN coincidente que se haya establecido, mientras que la segunda y la tercera definen las dos listas de dominios:
Luego podemos usar la API NGINX Plus para asignar el valor bloqueado
o agujero negro
a cualquier clave FQDN que queramos eliminar explícitamente, o modificar la lista con formato CSV asociada con la clave bloqueado_dominios
o agujero negro_dominios
. Podemos modificar o eliminar FQDN exactos, o modificar el conjunto de dominios en cualquiera de las listas, en cualquier momento y el filtro DNS se actualiza instantáneamente con los cambios.
La siguiente configuración carga la variable $dns_response
, que se completa con una directiva js_preread
en los bloques de servidor
definidos en Configuración de los servidores que escuchan consultas DNS a continuación. Cuando el código JavaScript invocado determina que es necesario limpiar la solicitud, establece la variable como bloqueada
o en agujero negro
según corresponda.
Usamos una directiva de mapa
para asignar el valor de la variable $dns_response
a la variable $upstream_pool
, controlando así cuál de los grupos ascendentes en Definición de servidores ascendentes a continuación maneja la solicitud. Las consultas para dominios no maliciosos se reenvían al servidor DNS predeterminado de Google, mientras que las consultas para dominios bloqueados o bloqueados son manejadas por el servidor ascendente para esas categorías.
Esta configuración define los grupos bloqueados
, de agujero negro
y de Google
de servidores ascendentes, que manejan solicitudes de dominios bloqueados, de agujero negro y no maliciosos respectivamente.
Aquí definimos los servidores en el contexto de transmisión
que escuchan solicitudes DNS entrantes. La directiva js_preread
invoca el código Javascript que decodifica el paquete DNS, recupera el nombre de dominio del campo NOMBRE
del paquete y busca el dominio en el almacén de clave-valor. Si el nombre de dominio coincide con una clave FQDN o está dentro de la zona de uno de los dominios en la lista blocking_domains
o blackhole_domains
, se elimina. De lo contrario, termina enviándose al servidor DNS de Google para su resolución.
Eso es casi todo: solo necesitamos agregar nuestro bloque de servidor
final, que responde a las consultas con la respuesta bloqueada o en agujero negro.
Tenga en cuenta que los servidores de este bloque son casi idénticos a los servidores DNS reales justo encima de ellos; la principal diferencia es que estos servidores envían un paquete de respuesta al cliente en lugar de reenviar la solicitud a un grupo ascendente de servidores DNS. Nuestro código JavaScript detecta cuándo se ejecuta desde el puerto 9953 o 9853 y, en lugar de establecer un indicador para indicar que el paquete debe bloquearse, completa $dns_response
con el paquete de respuesta real. Eso es todo lo que hay que hacer.
Por supuesto, también podríamos haber aplicado este filtrado a los servicios DoT y DoH, pero utilizamos DNS estándar para simplificar las cosas. La fusión del filtrado DNS con la puerta de enlace DoH se deja como ejercicio para el lector.
Anteriormente hemos utilizado la API NGINX Plus para agregar entradas para dos FQDN y algunos dominios a las dos listas de dominios:
$ curl -s http://localhost:8080/api/5/stream/keyvals/dns_config | jq { "www.algún.malo.host": "bloqueado", "www.algún.otro.host": "agujero negro", "dominios_bloqueados": "bar.com,baz.com", "dominios_agujero negro": "foo.com,nginx.com" }
Entonces, cuando solicitamos la resolución de www.foo.com (un host dentro del dominio bloqueado foo.com ), obtenemos un registro A
con la dirección IP 0.0.0.0:
$ dig @localhost www.foo.com ; <<>> DiG 9.11.3-1ubuntu1.9-Ubuntu <<>> @localhost www.foo.com ; (1 servidor encontrado) ;; opciones globales: +mcd ;; Obtuve la respuesta: ;; ->>HEADER,,- código de operación: CONSULTA, estado: NO ERROR, id: 58558 ;; banderas: qr aa rd ad; CONSULTA: 1, RESPUESTA: 1. AUTORIDAD: 0, ADICIONAL: 0 ;; ADVERTENCIA: recursión solicitada pero no disponible ;; SECCIÓN DE PREGUNTAS: ; www.foo.com. EN UNA SECCIÓN DE RESPUESTAS: www.foo.com. 300 EN A 0.0.0.0 ;; Tiempo de consulta: 0 mseg ;; SERVIDOR: 172.0.0.1#53(126.0.0.1) ;; CUANDO: Lun 2 Dic 14:31:35 UTC 2019 ;; TAMAÑO DEL MSG recibido: 45
Los archivos para DOH y DOT están disponibles en mi repositorio de GitHub :
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.