
Laboratorio de investigación en seguridad: reproducción de CVE-2025-61584 (GHSA-9g7x-737f-5xpc) — inyección de comandos a través de github.head_ref en el flujo de trabajo pull_request_target (.github/workflows/pr.yml)
Artefacto de investigación automatizado — no es el proyecto original.
Este repositorio es un laboratorio desechable construido por un sistema automatizado para una tesis de maestría en Université Laval sobre la reproducción de vulnerabilidades publicadas en flujos de trabajo de GitHub Actions. Es una instantánea verbatim de
serverless-dns/serverless-dnsen el commitb0b1a1538aeb1991b5bc13dfe4e18e686913b12e(2025-04-26), redistribuida bajo la licencia de ese proyecto, cuyo archivo se incluye sin cambios en esta instantánea.El proyecto original no está involucrado, nunca es el objetivo, y la vulnerabilidad estudiada aquí ya es pública. Cada secreto y variable en este repositorio es un valor ficticio generado aleatoriamente — no hay ninguna credencial real presente. Las referencias de acciones y las imágenes de ejecutores están fijadas a lo que resolvieron el 2025-04-26; consulte
pinning.mden la salida del sistema para cada cambio realizado en la instantánea.Preguntas u objeciones: [email protected]
serverless-dns es un resolutor DNS-over-HTTPS (DoH) y DNS-over-TLS (DoT) stub, serverless y de bloqueo de contenido estilo Pi-Hole. Funciona listo para usar en , , y . Los niveles gratuitos de todos estos servicios deberían ser suficientes para cubrir el tráfico DNS de 10 a 20 dispositivos al mes.
RethinkDNS ejecuta serverless-dns en producción en estos endpoints:
| Plataforma en la nube | Ubicaciones de servidores | Protocolo | Dominio | Uso |
|---|---|---|---|---|
| ⛅ Cloudflare Workers | 280+ (ping) | DoH | sky.rethinkdns.com | configurar |
| 🦕 Deno Deploy | 30+ (ping) | DoH | beta privada | |
| ⏱️ Fastly Compute@Edge | 80+ (ping) | DoH | beta privada | |
| 🪂 Fly.io | 30+ (ping) | DoH y DoT | max.rethinkdns.com | configurar |
El procesamiento del lado del servidor toma de 0 milisegundos (ms) a 2ms (mediana), y la latencia de extremo a extremo (varía según las regiones y redes) está entre 10ms y 30ms (mediana).
El resolutor Rethink DNS en Fly.io está patrocinado por FOSS United.
Cloudflare Workers es la plataforma más fácil para configurar serverless-dns:
Para instrucciones paso a paso, consulte:
| Plataforma | Dificultad | Runtime | Documentación |
|---|---|---|---|
| ⛅ Cloudflare | Fácil | v8 Isolates | Alojamiento en Cloudflare Workers |
| 🦕 Deno.com | Moderada | Deno Isolates | Alojamiento en Deno.com |
| ⏱️ Fastly Compute@Edge | Fácil | Fastly JS | Alojamiento en Fastly Compute@Edge |
| 🪂 Fly.io | Difícil | Node MicroVM | Alojamiento en Fly.io |
Para configurar listas de bloqueo, visite https://<my-domain>.tld/configure desde su navegador (debería cargar algo similar a la página configure de RethinkDNS).
Para ayuda o asistencia, no dude en abrir un issue o enviar un parche.
Código:
# navegar al directorio de trabajo
cd /my/work/dir
# clonar este repositorio
git clone https://github.com/serverless-dns/serverless-dns.git
# navegar a serverless-dns
cd ./serverless-dns
Node:
# instalar node v22+ mediante nvm, si es necesario
# https://github.com/nvm-sh/nvm#installing-and-updating
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
nvm install --lts
# descargar dependencias
npm i
# (opcional) actualizar dependencias
npm update
# ejecutar serverless-dns en node
./run n
# ejecutar un perfilador clinicjs.org
./run n [cpu|fn|mem]
Deno:
# instalar deno.land v2+
# https://github.com/denoland/deno/#install
curl -fsSL https://deno.land/install.sh | sh
# ejecutar serverless-dns en deno
./run d
Fastly:
# instalar node v22+ mediante nvm, si es necesario
# instalar la CLI de Fastly
# https://developer.fastly.com/learning/tools/cli
# ejecutar serverless-dns en Fastly Compute@Edge
./run f
Wrangler:
# instalar Cloudflare Workers (cli) también conocido como Wrangler
# https://developers.cloudflare.com/workers/cli-wrangler/install-update
npm i wrangler --save-dev
# ejecutar serverless-dns en Cloudflare Workers (cli)
# Asegúrese de configurar Wrangler primero:
# https://developers.cloudflare.com/workers/cli-wrangler/authentication
./run w
# perfilar wrangler con Chrome DevTools
# blog.cloudflare.com/profiling-your-workers-with-wrangler
Los commits en este repositorio aplican la guía de estilo JavaScript de Google (ref: .eslintrc.cjs).
Un hook de git pre-commit ejecuta el linter (eslint) y el formateador (prettier) en archivos .js. Use git commit --no-verify
para omitir este hook.
Las pull requests también se verifican por violaciones de estilo de código y se corrigen automáticamente cuando es posible.
Configure env.js si necesita ajustar los valores predeterminados.
Para Cloudflare Workers, configure las variables de entorno en wrangler.toml, en su lugar.
Para Fastly Compute@Edge, configure las variables de entorno en fastly.toml, en su lugar.
serverless-dns admite autenticación con un token portador alfanumérico tanto para DoH como para DoT. Para un token, msg-key (secreto), agregue la salida de hex(hmac-sha256(msg-key|domain.tld), msg) a la variable de entorno ACCESS_KEYS en formato csv. Nota: msg actualmente está fijado a sdns-public-auth-info.
msg-key al final del blockstamp, así:
1:1:4AIggAABEGAgAA:<msg-key> (aquí, 1 es la versión, 1:4AIggAABEGAgAA
es el blockstamp, <msg-key> es el secreto de autenticación, y : es el delimitador).msg-key al final del SNI (nombre de dominio) que contiene el blockstamp:
1-4abcbaaaaeigaiaa-<msg-key> (aquí 1 es la versión, 4abcbaaaaeigaiaa
es el blockstamp, <msg-key> es el secreto de autenticación, y - es el delimitador).Si la intención es usar autenticación también con DoT, mantenga msg-key más corto (8 a 24 caracteres), ya que los subdominios solo pueden tener 63 caracteres en total.
Puede generar las claves de acceso para su fork desde max.rethinkdns.com, así:
msgkey="ShortAlphanumericSecret"
domain="my-serverless-dns-domain.tld"
curl 'https://max.rethinkdns.com/genaccesskey?key='"$msgkey"'&dom='"$domain"
# salida
# {"accesskey":["my-serverless-dns-domain.tld|deadbeefd3adb33fa2bb33fd3eadf084beef3b152beefdead49bbb2b33fdead83d3adbeefdeadb33f"],"context":"sdns-public-auth-info"}
serverless-dns puede configurarse para subir registros mediante Cloudflare Logpush.
CF_ACCOUNT_ID=<hex-cloudflare-account-id>
CF_API_KEY=<api-key-with-logs-edit-permission-at-account-level>
R2_BUCKET=<r2-bucket-name>
R2_ACCESS_KEY=<r2-access-key-for-the-bucket>
R2_SECRET_KEY=<r2-secret-key-with-read-write-permissions>
# opcional, configure un filtro para que solo los registros de este worker se envíen; pero si
# no necesita un filtro en el nombre del Worker (script-name), edite el campo "filter" a continuación en consecuencia.
SCRIPT_NAME=<name-of-the-worker-as-in-wrangler-toml>
# para más opciones, ref: developers.cloudflare.com/logs/get-started/api-configuration
# API de Logpush con cURL: developers.cloudflare.com/logs/tutorials/examples/example-logpush-curl
# Campos disponibles de Logpull: developers.cloudflare.com/logs/reference/log-fields/account/workers_trace_events
curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/logpush/jobs" \
-H "Authorization: Bearer ${CF_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{
"name": "dns-logpush",
"logpull_options": "fields=EventTimestampMs,Outcome,Logs,ScriptName×tamps=rfc3339",
"destination_conf": "r2://'"$R2_BUCKET"'/{DATE}?access-key-id='"${R2_ACCESS_KEY}"'&secret-access-key='"${R2_SECRET_KEY}"'&account-id='"{$CF_ACCOUNT_ID}"',
"dataset": "workers_trace_events",
"filter": "{\"where\":{\"and\":[{\"key\":\"ScriptName\",\"operator\":\"contains\",\"value\":\"'"${SCRIPT_NAME}"'\"},{\"key\":\"Outcome\",\"operator\":\"eq\",\"value\":\"ok\"}]}}",
"enabled": true,
"frequency": "low"
}'
logpush = true en wrangler.toml, lo que habilita Logpush.LOG_LEVEL = "logpush", que eleva el nivel de registro para que solo se emitan registros de solicitudes y errores.LOGPUSH_SRC = "csv,of,subdomains", lo que hace que log-pusher.js emita registros de solicitudes solo si el hostname de Workers contiene uno de los subdominios.Los registros publicados en R2 se pueden recuperar usando R2 Workers, la API de R2 o la API de Logpush.
Workers Analytics, si está habilitado, se envía contra una clave de registro, lid, que si no se especifica se establece al hostname del despliegue serverless con los puntos, ., reemplazados por guiones bajos, _. La autenticación debe configurarse al consultar Analytics mediante la API que devuelve un json; ej: https://max.rethinkdns.com/1:<optional-stamp>:<msg-key>/analytics?t=<time-interval-in-mins>&f=<field-name>. Los fields posibles son ip (ip del cliente), qname (nombre de la consulta DNS), region (región del resolutor), qtype (tipo de consulta DNS), dom (dominios de nivel superior), ansip (ips de respuesta DNS) y cc (códigos de país de las ips de respuesta).
La captura de registros y las analíticas aún no están implementadas para Fly y Deno Deploy.
Deno Deploy (nube) y Deno (el runtime) no exponen la misma superficie de API (por ejemplo, Deno Deploy solo admite listeners de servidor HTTP/S; mientras que Deno admite TCP/UDP/TLS sin procesar además de HTTP simple y HTTP/S).
Excepto en Node, serverless-dns usa upstreams DoH definidos por variables de entorno, CF_DNS_RESOLVER_URL / CF_DNS_RESOLVER_URL_2.
En Node, el upstream DNS predeterminado es 1.1.1.2 (ref) o el resolutor DNS recursivo en fdaa::3 cuando se ejecuta en Fly.io.
Los puntos de entrada para Node y Deno son src/server-node.js y src/server-deno.ts respectivamente,
y ambos escuchan conexiones TCP-over-TLS y HTTP/S; mientras que el punto de entrada para Cloudflare Workers, que solo escucha sobre HTTP (cli) o
sobre HTTP/S (prod), es src/server-workers.js; y para Fastly es src/server-fastly.js.
Las configuraciones locales (no prod) en Node, los archivos key (privada) y cert (cadena pública), por defecto, se leen de
rutas definidas en variables de entorno, TLS_KEY_PATH y TLS_CRT_PATH.
Mientras que para la configuración de prod en Node (en Fly.io), TLS_OFFLOAD debe establecerse en true o key y cert deben estar
codificados en base64 en la variable de entorno TLS_CERTKEY (ref), así:
# O BIEN: descargar tls a fly.io y establecer tls_offload en true
TLS_OFFLOAD="true"
# O: representación base64 tanto de key (privada) como de cert (cadena pública)
TLS_CERTKEY="KEY=b64_key_content\nCRT=b64_cert_content"
Para Deno, los archivos key y cert se leen de rutas definidas en variables de entorno, TLS_KEY_PATH y TLS_CRT_PATH (ref).
La puesta en marcha del proceso es diferente para cada uno de estos runtimes: Para Node, src/core/node/config.js gobierna la puesta en marcha;
mientras que para Deno, es src/core/deno/config.ts, y para Workers es src/core/workers/config.js.
src/system.js pub-sub coordina la fase de puesta en marcha entre varios módulos.
En Node y Deno, el caché DNS en proceso está respaldado por @serverless-dns/lfu-cache; Cloudflare Workers está respaldado tanto por Cache Web API como por
cachés lfu en proceso. Para deshabilitar el caché por completo en las tres plataformas, establezca la variable de entorno PROFILE_DNS_RESOLVES=true.
Cloudflare Workers y Deno Deploy son efímeros, es decir, el "proceso" que atiende las solicitudes de los clientes no es de larga duración, y de hecho, dos solicitudes consecutivas pueden ser atendidas por dos isolates ("procesos") diferentes. Fastly Compute@Edge también es efímero pero no usa isolates; en su lugar, Fastly crea y destruye un sandbox de wasmtime para cada solicitud. El resolutor en Fly.io, que ejecuta Node, está respaldado por VMs persistentes y por lo tanto es de mayor duración, como los entornos tradicionales "serverfull".
Para Deno Deploy, el código base se agrupa en un solo archivo javascript con deno bundle y luego se entrega
a Deno.com.
Las configuraciones de tiempo de compilación y tiempo de ejecución de Cloudflare Workers se definen en wrangler.toml.
Webpack5 agrupa los archivos en un módulo ESM que luego Wrangler sube a Cloudflare.
Las configuraciones de tiempo de compilación y tiempo de ejecución de Fastly Compute@Edge se definen en fastly.toml.
Webpack5 agrupa los archivos en un módulo ESM que luego se compila a WASM con npx js-compute-runtime
y posteriormente se empaqueta y publica en Fastly Compute@Edge con la CLI de Fastly.
Para Fly.io, que ejecuta Node, las directivas de tiempo de ejecución se definen en fly.toml (usado por los tipos de despliegue dev y live),
mientras que las directivas de despliegue están en node.Dockerfile. flyctl configura en consecuencia
serverless-dns en la infraestructura de Fly.io.
# compilar y desplegar para cloudflare workers.dev
npm run build
# normalmente, env-name es prod
npx wrangler publish [-e <env-name>]
# agrupar, compilar y desplegar para fastly compute@edge
# developer.fastly.com/reference/cli/compute/publish
fastly compute publish
# compilar y desplegar en fly.io
npm run build:fly
flyctl deploy --dockerfile node.Dockerfile --config <fly.toml> [-a <app-name>] [--image-label <some-uniq-label>]
Para despliegues que descargan la terminación TLS a Fly.io (tipo de despliegue B1), las directivas de tiempo de ejecución se definen en su lugar en
fly.tls.toml, que configura HTTP2 Cleartext y HTTP/1.1 en el puerto 443, y DNS sobre TCP en el puerto 853.
Ref: github/workflows.
190+ listas de bloqueo se comprimen en un Succinct Radix Trie (basado en la impl de Steve Hanov) con modificaciones
para acelerar la búsqueda de cadenas (lookup) a expensas de la "compacidad". Las listas de bloqueo tienen versiones
con marca de tiempo unix (definida en src/basicconfig.json descargado por pre.sh), que se genera una vez por semana, pero nos gustaría generarlas diariamente / cada hora,
si es posible ver), y se alojan en Cloudflare R2 (variable de entorno: CF_BLOCKLIST_URL).
serverless-dns descarga 3 archivos de listas de bloqueo
necesarios para configurar el radix-trie durante la puesta en marcha del runtime o los descarga perezosamente,
al atender una solicitud DNS.
serverless-dns compila alrededor de ~13M de entradas (a enero de 2023) de alrededor de 190+ listas de bloqueo. Estas se definen en el repositorio serverless-dns/blocklists.