From be7ba1f820258342f728b9b9deb73428f7f0c5c7 Mon Sep 17 00:00:00 2001 From: Patrick Di Fazio Date: Fri, 9 Jan 2026 20:37:20 +0100 Subject: [PATCH] added download button --- config.yaml | 2 +- src/exports/malicious_ips.txt | 1 + src/handler.py | 32 +++++++++++++++++++++++++- src/templates/dashboard_template.py | 35 +++++++++++++++++++++++++++-- 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/exports/malicious_ips.txt diff --git a/config.yaml b/config.yaml index 52daa09..a2f6b58 100644 --- a/config.yaml +++ b/config.yaml @@ -1,7 +1,7 @@ # Krawl Honeypot Configuration server: - port: 5000 + port: 1234 delay: 100 # Response delay in milliseconds timezone: null # e.g., "America/New_York", "Europe/Paris" or null for system default diff --git a/src/exports/malicious_ips.txt b/src/exports/malicious_ips.txt new file mode 100644 index 0000000..7b9ad53 --- /dev/null +++ b/src/exports/malicious_ips.txt @@ -0,0 +1 @@ +127.0.0.1 diff --git a/src/handler.py b/src/handler.py index ebc0b66..1f96d6c 100644 --- a/src/handler.py +++ b/src/handler.py @@ -408,7 +408,8 @@ class Handler(BaseHTTPRequestHandler): try: stats = self.tracker.get_stats() timezone = str(self.config.timezone) if self.config.timezone else 'UTC' - self.wfile.write(generate_dashboard(stats, timezone).encode()) + dashboard_path = self.config.dashboard_secret_path + self.wfile.write(generate_dashboard(stats, timezone, dashboard_path).encode()) except BrokenPipeError: pass except Exception as e: @@ -442,6 +443,35 @@ class Handler(BaseHTTPRequestHandler): self.wfile.write(json.dumps({'error': str(e)}).encode()) return + # API endpoint for downloading malicious IPs file + if self.config.dashboard_secret_path and self.path == f"{self.config.dashboard_secret_path}/api/download/malicious_ips.txt": + import os + file_path = os.path.join(os.path.dirname(__file__), 'exports', 'malicious_ips.txt') + try: + if os.path.exists(file_path): + with open(file_path, 'rb') as f: + content = f.read() + self.send_response(200) + self.send_header('Content-type', 'text/plain') + self.send_header('Content-Disposition', 'attachment; filename="malicious_ips.txt"') + self.send_header('Content-Length', str(len(content))) + self.end_headers() + self.wfile.write(content) + else: + self.send_response(404) + self.send_header('Content-type', 'text/plain') + self.end_headers() + self.wfile.write(b'File not found') + except BrokenPipeError: + pass + except Exception as e: + self.app_logger.error(f"Error serving malicious IPs file: {e}") + self.send_response(500) + self.send_header('Content-type', 'text/plain') + self.end_headers() + self.wfile.write(b'Internal server error') + return + self.tracker.record_access(client_ip, self.path, user_agent, method='GET') self.analyzer.infer_user_category(client_ip) diff --git a/src/templates/dashboard_template.py b/src/templates/dashboard_template.py index bbb6ad9..4e7005c 100644 --- a/src/templates/dashboard_template.py +++ b/src/templates/dashboard_template.py @@ -38,12 +38,13 @@ def format_timestamp(iso_timestamp: str, timezone: str = 'UTC', time_only: bool return iso_timestamp.split("T")[1][:8] if "T" in iso_timestamp else iso_timestamp -def generate_dashboard(stats: dict, timezone: str = 'UTC') -> str: +def generate_dashboard(stats: dict, timezone: str = 'UTC', dashboard_path: str = '') -> str: """Generate dashboard HTML with access statistics Args: stats: Statistics dictionary timezone: IANA timezone string (e.g., 'Europe/Paris', 'America/New_York') + dashboard_path: The secret dashboard path for generating API URLs """ # Generate IP rows with clickable functionality for dropdown stats @@ -164,12 +165,36 @@ def generate_dashboard(stats: dict, timezone: str = 'UTC') -> str: .container {{ max-width: 1400px; margin: 0 auto; + position: relative; }} h1 {{ color: #58a6ff; text-align: center; margin-bottom: 40px; }} + .download-section {{ + position: absolute; + top: 0; + right: 0; + }} + .download-btn {{ + display: inline-block; + padding: 8px 14px; + background: #238636; + color: #ffffff; + text-decoration: none; + border-radius: 6px; + font-weight: 500; + font-size: 13px; + transition: background 0.2s; + border: 1px solid #2ea043; + }} + .download-btn:hover {{ + background: #2ea043; + }} + .download-btn:active {{ + background: #1f7a2f; + }} .stats-grid {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); @@ -450,6 +475,11 @@ def generate_dashboard(stats: dict, timezone: str = 'UTC') -> str:
+

Krawl Dashboard

@@ -599,6 +629,7 @@ def generate_dashboard(stats: dict, timezone: str = 'UTC') -> str: