
Servidor DNS pasivo que detecta buckets de almacenamiento en la nube expuestos (AWS S3, GCP, Azure) resolviendo solicitudes DNS, rastreando cadenas CNAME y marcando posibles secuestros de subdominio durante el reconocimiento.
s3dns es un servidor DNS ligero que ayuda a descubrir buckets de almacenamiento en la nube (AWS S3, Google Cloud Storage y Azure Blob) resolviendo solicitudes DNS, rastreando CNAMEs y coincidiendo con patrones conocidos de URLs de buckets.
Es un compañero útil para pentesters, cazadores de recompensas por bugs y analistas de seguridad en la nube que quieran detectar buckets en la nube expuestos durante el análisis de tráfico DNS.
Si S3DNS te ahorra tiempo en una sesión de reconocimiento, considera darle una ⭐️ — ayuda a que otros encuentren el proyecto.
CACHE_SIZE (por defecto: 1000 entradas, poner 0 para deshabilitar).RATE_LIMIT (por defecto: 100 req/s, poner 0 para deshabilitar).NXDOMAIN, S3DNS lo marca como un posible subdominio tomable. Esto indica un registro DNS colgante que apunta a un bucket no reclamado que un atacante podría registrar.max_cname_depth.AZURE_IP_RANGES=false o AWS_IP_RANGES=false (por defecto es true).regex_patterns y patrones codificados a la carpeta patterns como archivos YAML. Puedes añadir tus propios patrones.
regex_.53 (UDP y TCP)S3DNS escucha en el puerto 53 (UDP y TCP) para consultas DNS. Por cada solicitud:
1.1.1.1) — por UDP para clientes UDP, por TCP para clientes TCPEn paralelo, realiza lo siguiente:
s3dns.log⚡ Úsalo como tu DNS durante el reconocimiento, y detectará pasivamente buckets en la nube y candidatos a toma de subdominios para cada dominio que tus herramientas o navegador resuelvan.
Solo necesitarás una de las siguientes opciones:
Solo necesario si quieres ejecutarlo localmente con Python
git clone https://github.com/olizimmermann/s3dns.git
cd s3dns
(Se recomienda usar un entorno virtual)
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
El puerto 53 requiere privilegios elevados:
sudo python s3dns.py
Si sudo informa de un módulo faltante, intenta: sudo venv/bin/python s3dns.py
docker build -t ozimmermann/s3dns:latest .La forma más fácil de empezar con S3DNS.
docker pull ozimmermann/s3dns:latest
docker run --rm -p 53:53/udp -p 53:53/tcp \
-v "./bucket_findings/:/app/buckets/" \
--name "s3dns" \
ozimmermann/s3dns:latest
docker build -t ozimmermann/s3dns:latest .
docker run --rm -p 53:53/udp -p 53:53/tcp \
-v "./bucket_findings/:/app/buckets/" \
--name "s3dns" \
ozimmermann/s3dns:latest
Los hallazgos se guardan:
./bucket_findings/Al usar S3DNS en la misma máquina donde realizas el análisis, puede ayudar configurar la bandera --network host:
docker run --rm -p 53:53/udp -p 53:53/tcp \
-v "./bucket_findings/:/app/buckets/" \
--network host \
--name "s3dns" \
ozimmermann/s3dns:latest
Dado que el puerto 53 requiere privilegios elevados, algunos usuarios (ej., usuarios de Mac) pueden necesitar sudo:
sudo docker run --rm -p 53:53/udp -p 53:53/tcp \
-v "./bucket_findings/:/app/buckets/" \
--name "s3dns" \
ozimmermann/s3dns:latest
Configura el resolutor DNS de tu sistema o herramienta para que apunte a tu instancia de S3DNS.
Mientras navegas o haces fuzzing a tu objetivo, S3DNS analiza cada dominio y te indica si resuelve a:
- Un bucket de AWS S3
- Un bucket de GCP
- Un contenedor de Azure Blob
- Cualquiera de los otros 13 proveedores de almacenamiento en la nube soportados
Sigue los CNAMEs, por lo que si un dominio apunta a
cdn.ejemplo.com, que a su vez apunta a un bucket en la nube, también lo detectará.También marca posibles subdominios tomables — si un dominio coincide con un patrón de almacenamiento en la nube pero el objetivo no existe (NXDOMAIN), el registro colgante se resalta como posible candidato a toma de subdominio.
Úsalo pasivamente mientras analizas un sitio para detectar buckets expuestos y oportunidades de toma sin sondeo activo.
Puedes ajustar el comportamiento mediante banderas de línea de comandos, variables de entorno o modificando s3dns.py.
La precedencia para cada opción es: bandera de línea de comandos > variable de entorno > indicación interactiva / predeterminado. Ejecutar sin banderas se comporta exactamente como antes.
Ejecuta python s3dns.py -h para la lista completa:
Ejemplo:
sudo python s3dns.py -l 0.0.0.0 -u 1.1.1.1 --rate-limit 200 --no-azure-ip-ranges
Dado que Microsoft no nombra explícitamente sus rangos IP de Azure Blob Storage, S3DNS usa todas las direcciones IP de Azure Storage proporcionadas públicamente. Esto puede provocar falsos positivos. Considera deshabilitar esta verificación si encuentras problemas:
AZURE_IP_RANGES=false
Añade archivos YAML al directorio patterns/. Los archivos con prefijo regex_ se tratan como patrones regex; todos los demás se tratan como coincidencias de subcadena.
Python:
sudo su
export DEBUG=true
python s3dns.py
Docker:
docker run --rm -p 53:53/udp -p 53:53/tcp \
-v "./bucket_findings/:/app/buckets/" \
-e "DEBUG=true" \
--name "s3dns" \
ozimmermann/s3dns:latest
Configurar múltiples variables de entorno en Docker:
docker run --rm -p 53:53/udp -p 53:53/tcp \
-v "./bucket_findings/:/app/buckets/" \
-e "LOCAL_DNS_SERVER_IP=0.0.0.0" \
-e "REAL_DNS_SERVER_IP=1.1.1.1" \
-e "RATE_LIMIT=200" \
-e "CACHE_SIZE=2000" \
--name "s3dns" \
ozimmermann/s3dns:latest

Las contribuciones son bienvenidas — nuevos patrones de proveedores de nube, correcciones de errores y mejoras. Consulta CONTRIBUTING.md para las pautas.
Los archivos de patrones residen en patterns/. Añadir soporte para un nuevo proveedor es tan simple como añadir una entrada YAML — no se requiere Python.
Licencia MIT — Libre de usar, mejorar y compartir.
Úsalo responsablemente. Solo escanea dominios que poseas o para los que tengas permiso explícito para analizar.
El acceso no autorizado o la exploración pueden ser ilegales.
| Banderas | Variable de entorno equivalente | Descripción |
|---|
-h, --help | – | Mostrar ayuda y salir |
--version | – | Mostrar versión y salir |
-d, --debug | DEBUG | Habilitar salida de depuración detallada |
-l, --listen IP | LOCAL_DNS_SERVER_IP | Interfaz local en la que escuchar |
-u, --upstream IP | REAL_DNS_SERVER_IP | Resolutor DNS upstream al que reenviar |
-b, --bucket-file RUTA | BUCKET_FILE | Ruta para escribir los dominios de buckets descubiertos |
--aws-ip-ranges / --no-aws-ip-ranges | AWS_IP_RANGES | Activar/desactivar verificación de rangos IP de AWS S3 |
--azure-ip-ranges / --no-azure-ip-ranges | AZURE_IP_RANGES | Activar/desactivar verificación de rangos IP de Azure Storage |
--rate-limit N | RATE_LIMIT | Máx. solicitudes DNS/segundo por IP de cliente (0 = deshabilitado) |
--cache-size N | CACHE_SIZE | Máx. respuestas DNS en caché (0 = deshabilitado) |
--max-cname-depth N | – | Profundidad máxima de cadena CNAME a seguir (por defecto: 10) |
| Variable | Predeterminado | Descripción |
|---|
DEBUG | false | Habilitar salida de depuración detallada |
AWS_IP_RANGES | true | Activar verificación de rangos IP de AWS S3 |
AZURE_IP_RANGES | true | Activar verificación de rangos IP de Azure Storage |
REAL_DNS_SERVER_IP | 1.1.1.1 | Resolutor DNS upstream para reenviar consultas |
LOCAL_DNS_SERVER_IP | 0.0.0.0 | Interfaz local en la que escuchar |
BUCKET_FILE | buckets.txt | Ruta para escribir los dominios de buckets descubiertos |
RATE_LIMIT | 100 | Máx. solicitudes DNS por segundo por IP de cliente (0 = deshabilitado) |
CACHE_SIZE | 1000 | Máx. respuestas DNS en caché (0 = deshabilitado) |