""" This plugin provides DNSDumpster.com integration for domain reconnaissance and DNS mapping. """ import logging import os import aiohttp import simplematrixbotlib as botlib from plugins.common import html_escape, collapsible_summary DNSDUMPSTER_API_KEY = os.getenv("DNSDUMPSTER_KEY", "") DNSDUMPSTER_API_BASE = "https://api.dnsdumpster.com" async def handle_command(room, message, bot, prefix, config): match = botlib.MessageMatch(room, message, bot, prefix) if match.is_not_from_this_bot() and match.prefix() and match.command("dnsdumpster"): logging.info("Received !dnsdumpster command") if not DNSDUMPSTER_API_KEY: await bot.api.send_text_message( room.room_id, "DNSDumpster API key not configured. Set DNSDUMPSTER_KEY in .env." ) return args = match.args() if len(args) < 1: await show_usage(room, bot) return if args[0].lower() == "test": await test_dnsdumpster_connection(room, bot) else: domain = args[0].lower().strip() await dnsdumpster_domain_lookup(room, bot, domain) async def show_usage(room, bot): usage = """🔍 DNSDumpster Commands: !dnsdumpster <domain_name> - Get comprehensive DNS reconnaissance for a domain !dnsdumpster test - Test API connection Examples:!dnsdumpster google.com!dnsdumpster github.com """ await bot.api.send_markdown_message(room.room_id, usage) async def test_dnsdumpster_connection(room, bot): test_domain = "google.com" try: url = f"{DNSDUMPSTER_API_BASE}/domain/{test_domain}" headers = {"X-API-Key": DNSDUMPSTER_API_KEY} async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers, timeout=15) as response: status = response.status debug_info = f"🔧 DNSDumpster API Test
Status Code: {status}
Test Domain: {test_domain}
" if status == 200: data = await response.json() debug_info += "✅ SUCCESS
" if data.get('a'): debug_info += f"A Records Found: {len(data['a'])}
" elif status == 401: debug_info += "❌ Unauthorized - Invalid API key
" elif status == 429: debug_info += "⚠️ Rate Limit Exceeded
" else: debug_info += f"❌ Error: {status}
" await bot.api.send_markdown_message(room.room_id, debug_info) except Exception as e: await bot.api.send_text_message(room.room_id, f"Test failed: {str(e)}") async def dnsdumpster_domain_lookup(room, bot, domain): safe_domain = html_escape(domain) try: await bot.api.send_text_message(room.room_id, f"🔍 Processing DNS reconnaissance for {safe_domain}...") url = f"{DNSDUMPSTER_API_BASE}/domain/{domain}" headers = {"X-API-Key": DNSDUMPSTER_API_KEY} async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers, timeout=30) as response: if response.status != 200: await bot.api.send_text_message(room.room_id, f"API error: {response.status}") return data = await response.json() output = await format_dnsdumpster_report(domain, data) await bot.api.send_markdown_message(room.room_id, output) logging.info(f"Sent DNSDumpster data for {domain}") except asyncio.TimeoutError: await bot.api.send_text_message(room.room_id, "Request timed out.") except Exception as e: await bot.api.send_text_message(room.room_id, f"Error: {e}") async def format_dnsdumpster_report(domain, data): safe_domain = html_escape(domain) output = f"🔍 DNSDumpster Report: {safe_domain}

" if data.get('total_a_recs'): output += f"📊 Summary
Total A Records: {data['total_a_recs']}
" for record_type, label in [('a','A Records'),('ns','NS Records'),('mx','MX Records'),('cname','CNAME'),('txt','TXT')]: if data.get(record_type) and data[record_type]: output += f"
{label} ({len(data[record_type])} found)
" for rec in data[record_type]: if record_type == 'txt': txt = html_escape(str(rec)) if len(txt) > 200: txt = txt[:200] + "..." output += f" • {txt}
" elif record_type == 'a': host = html_escape(rec.get('host','N/A')) ips = rec.get('ips',[]) output += f" • {host}
" for ip_info in ips: ip = html_escape(ip_info.get('ip','N/A')) country = html_escape(ip_info.get('country','Unknown')) output += f" └─ {ip} ({country})
" else: host = html_escape(rec.get('host','N/A')) ips = rec.get('ips',[]) output += f" • {host}
" for ip_info in ips: ip = html_escape(ip_info.get('ip','N/A')) country = html_escape(ip_info.get('country','Unknown')) output += f" └─ {ip} ({country})
" output += "
💡 Rate Limit: 1 request per 2 seconds" return collapsible_summary(f"🔍 DNSDumpster Report: {safe_domain} (Click to expand)", output) __version__ = "1.0.1" __author__ = "Funguy Bot" __description__ = "DNSDumpster domain reconnaissance" __help__ = """
!dnsdumpster – Comprehensive DNS mapping via DNSDumpster

Requires DNSDUMPSTER_KEY env var.

"""