Spaces:
Sleeping
Sleeping
File size: 4,193 Bytes
74cb9b4 1c6e1aa 74cb9b4 1c6e1aa 74cb9b4 1c6e1aa 74cb9b4 1c6e1aa 74cb9b4 1c6e1aa 74cb9b4 1c6e1aa 74cb9b4 1c6e1aa 74cb9b4 1c6e1aa 74cb9b4 1c6e1aa 74cb9b4 1c6e1aa 74cb9b4 1c6e1aa 74cb9b4 1c6e1aa 74cb9b4 1c6e1aa 74cb9b4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
import shodan
import gradio as gr
import logging
from abc import ABC, abstractmethod
from typing import List, Optional
import json
import asyncio
# Logging setup
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[logging.StreamHandler()]
)
logger = logging.getLogger(__name__)
# Custom exceptions
class ScannerException(Exception):
"""Base exception for scanner errors."""
pass
# Instance class (assuming a basic structure since it wasn’t provided)
class Instance:
"""Represents an Ollama instance."""
def __init__(self, ip: str, port: int, owner_id: Optional[str] = None):
self.ip = ip
self.port = port
self.owner_id = owner_id
@classmethod
def from_shodan(cls, result: dict, owner_id: Optional[str] = None) -> 'Instance':
"""Create Instance from Shodan result."""
return cls(ip=result['ip_str'], port=result['port'], owner_id=owner_id)
def to_dict(self) -> dict:
"""Convert to dict for JSON output."""
return {"ip": self.ip, "port": self.port, "owner_id": self.owner_id}
# Scanner interface
class IScanner(ABC):
"""Scanner interface for finding Ollama instances."""
@abstractmethod
async def scan_instances(self, limit: int = 100) -> List[Instance]:
pass
# ShodanScanner implementation
class ShodanScanner(IScanner):
"""Scanner for finding public Ollama instances using Shodan."""
def __init__(self, api_key: str, owner_id: Optional[str] = None):
self.api_key = api_key
self.owner_id = owner_id
async def scan_instances(self, limit: int = 100) -> List[Instance]:
"""Scan for Ollama instances using Shodan."""
try:
api = shodan.Shodan(self.api_key)
results = api.search('port:11434 "Ollama"', limit=limit)
instances = [Instance.from_shodan(result, self.owner_id) for result in results['matches']]
return instances
except shodan.APIError as e:
raise ScannerException(f"Shodan API error: {str(e)}")
except Exception as e:
raise ScannerException(f"Error during Shodan scan: {str(e)}")
# Gradio processing function
async def scan_ollama_instances(api_key: str, limit: int, owner_id: str = "") -> str:
"""Process Shodan scan and return results."""
try:
if not api_key:
return "Yo, drop a Shodan API key, fam!"
scanner = ShodanScanner(api_key, owner_id if owner_id else None)
instances = await scanner.scan_instances(limit=limit)
if not instances:
return "No Ollama instances found, dawg!"
output = ["Found Ollama Instances:"]
for i, instance in enumerate(instances, 1):
output.append(f"{i}. {json.dumps(instance.to_dict(), indent=2)}")
logger.info(f"Scanned {len(instances)} Ollama instances")
return "\n\n".join(output)
except ScannerException as e:
logger.error(f"Scan failed: {str(e)}")
return f"Scan crashed: {str(e)}"
except Exception as e:
logger.error(f"Unexpected error: {str(e)}")
return f"Shit hit the fan, fam: {str(e)}"
# Gradio wrapper to run async function
def gradio_scan(api_key: str, limit: int, owner_id: str) -> str:
"""Wrapper to run async scan in Gradio."""
return asyncio.run(scan_ollama_instances(api_key, limit, owner_id))
# Gradio interface
demo = gr.Interface(
fn=gradio_scan,
inputs=[
gr.Textbox(label="Shodan API Key", placeholder="Enter your Shodan API key here", type="password"),
gr.Slider(label="Max Results", minimum=1, maximum=1000, value=100, step=1),
gr.Textbox(label="Owner ID (Optional)", placeholder="e.g., your_user_id", value="")
],
outputs=gr.Textbox(label="Ollama Instances Found"),
title="Ollama Instance Scanner",
description="Scan for public Ollama instances using Shodan, Bay Area style! Drop your API key and let’s roll.",
allow_flagging="never"
)
if __name__ == "__main__":
logger.info("Firin’ up the Ollama scanner on Gradio...")
demo.launch(server_name="0.0.0.0", server_port=7860) |