--- name: whois_lookup kind: function lang: py domain: cybersecurity version: "1.0.0" purity: impure signature: "def whois_lookup(dominio: str, timeout_s: float = 15.0) -> dict" description: "Recoleccion OSINT pasiva de datos de registro de dominio via RDAP (reemplazo moderno de WHOIS sobre HTTP/JSON). Consulta https://rdap.org/domain/ con http_get_json y normaliza registrar, fechas de creacion/expiracion/ultimo cambio, nameservers, estados y entidades. Devuelve {found: False} si el dominio no existe (404)." tags: [osint-passive, whois, rdap, recon, cybersecurity] params: - name: dominio desc: "Dominio a consultar, ej. organic-machine.com. Vacio lanza RuntimeError." - name: timeout_s desc: "Segundos maximo de espera de la peticion HTTP a rdap.org (default 15.0)." output: "dict normalizado con found (bool), registrar, creation_date, expiration_date, last_changed, nameservers (lista), status (lista), entities (lista de {handle, roles}) y raw (RDAP completo). Si el dominio no existe (HTTP 404) devuelve {found: False}." uses_functions: ["http_get_json_py_infra"] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [] tested: true tests: ["test_normaliza_respuesta_rdap", "test_dominio_no_encontrado_404", "test_otro_error_http_se_propaga", "test_sin_registrar_ni_fechas", "test_dominio_vacio_lanza_error"] test_file_path: "python/functions/cybersecurity/whois_lookup_test.py" file_path: "python/functions/cybersecurity/whois_lookup.py" --- ## Ejemplo ```python import sys, os sys.path.insert(0, os.path.join("python", "functions")) from cybersecurity import whois_lookup info = whois_lookup("organic-machine.com") if info["found"]: print(info["registrar"]) # 'Example Registrar Inc.' print(info["creation_date"]) # '2020-01-15T10:00:00Z' print(info["expiration_date"]) # '2027-01-15T10:00:00Z' print(info["nameservers"]) # ['ns1.example.net', 'ns2.example.net'] print(info["status"]) # ['client transfer prohibited'] else: print("dominio no registrado") ``` ## Cuando usarla Usala para obtener metadatos de registro de un dominio sin depender del CLI `whois` (no instalado): edad del dominio, fecha de expiracion (dominios a punto de caducar), registrar y nameservers autoritativos. Util en perfilado pasivo, deteccion de dominios recien creados (typosquatting/phishing) y validacion de propiedad. ## Gotchas - RDAP no esta uniformemente desplegado en todos los TLD: algunos devuelven campos vacios o ni siquiera responden. Por eso los campos opcionales pueden quedar `None` y `nameservers`/`status`/`entities` listas vacias. - rdap.org actua como bootstrap y redirige al servidor RDAP autoritativo del TLD; depende de su disponibilidad. - El registrante (`entities` con rol distinto de `registrar`) suele estar redactado por privacy/GDPR: casi siempre solo veras `handle` y `roles`, sin datos personales. - Un dominio no registrado devuelve `{"found": False}` (HTTP 404); cualquier otro error HTTP (rate limit 429, 5xx) se propaga como `RuntimeError`. - Las fechas se devuelven tal cual las da RDAP (ISO 8601 UTC), sin parsear a objetos `datetime`.