From 832f3f35267bef54fa44bfeb2f729570256e5c86 Mon Sep 17 00:00:00 2001 From: Vlastislav Svatek Date: Wed, 20 May 2026 14:10:54 +0200 Subject: [PATCH] add 2 metoths --- Dockerfile | 8 +++--- README.md | 71 ++++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 17 +++++++++++ ipscan-v2.py | 13 +++++---- scan.py | 67 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 166 insertions(+), 10 deletions(-) create mode 100644 README.md create mode 100644 scan.py diff --git a/Dockerfile b/Dockerfile index 32d112e..99ca6bb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,13 +17,13 @@ COPY requirements.txt requirements.txt RUN pip install --upgrade pip RUN pip install --no-cache-dir -r requirements.txt -# Zkopírování Python skriptu do pracovního adresáře -COPY ipscan-v2.py ipscan-v2.py +# Zkopírování Python skriptů do pracovního adresáře +COPY ipscan-v2.py scan.py ./ # Instalace nmap RUN apt-get update && \ apt-get install -y nmap && \ rm -rf /var/lib/apt/lists/* -# Spuštění Python skriptu -CMD ["python", "ipscan.py"] +# Spuštění výchozího Python skriptu +CMD ["python", "scan.py"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..59379fa --- /dev/null +++ b/README.md @@ -0,0 +1,71 @@ +# Netbox Scanner + +This repository includes a simple Dockerized network scanner and a NetBox importer. + +## Services + +- `scanner`: runs `scan.py` and saves scan results to `output/network.txt` +- `netbox-importer`: runs `ipscan-v2.py` and imports scan results into NetBox + +## Files + +- `scan.py`: performs Nmap scans for configured networks and writes `network.txt` +- `ipscan-v2.py`: imports scan results into NetBox using environment variables +- `docker-compose.yml`: defines `scanner` and `netbox-importer` services +- `Dockerfile`: installs Python and Nmap and copies both scripts into the container + +## Usage + +### Build and run the scanner + +```bash +docker compose build +docker compose up scanner +``` + +The scan output is written to: + +```bash +./output/network.txt +``` + +### Run the NetBox importer + +```bash +docker compose up netbox-importer +``` + +## Configuration + +### Scanner service + +- `OUTPUT_PATH`: path to save results inside container (default: `/app/output/network.txt`) +- `SCAN_NETWORKS`: comma-separated CIDR networks to scan (default set in `scan.py`) + +### NetBox importer service + +- `NETBOX_URL`: NetBox API URL +- `NETBOX_TOKEN`: NetBox API token +- `NETWORKS`: comma-separated networks to scan +- `TENANT`: NetBox tenant name +- `SSL_VERIFY`: whether to verify SSL (`false`, `0`, `no` disable verification) + +## Output format + +The generated `network.txt` file includes scan results in this format: + +```text +# network.txt generated on 2026-05-20T00:00:00Z +# host status open_ports +192.168.85.1 up 22 80 +192.168.85.2 down +``` + +## Notes + +- Ensure `nmap` is installed in the container via the provided `Dockerfile`. +- If you want to run both services together, use: + +```bash +docker compose up scanner netbox-importer +``` diff --git a/docker-compose.yml b/docker-compose.yml index a6bf558..fdaa3f7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,23 @@ version: '3' services: + scanner: + build: . + container_name: netbox_scanner + tty: true + command: python scan.py + volumes: + - ./output:/app/output + environment: + - OUTPUT_PATH=/app/output/network.txt + netbox-importer: build: . container_name: netbox_importer tty: true + command: python ipscan-v2.py + environment: + - NETBOX_URL=https://netbox.xxxxx.xx/ + - NETBOX_TOKEN=xxxxx + - NETWORKS=192.168.85.0/24,192.168.86.0/24 + - TENANT=Xxxxx Praha + - SSL_VERIFY=false diff --git a/ipscan-v2.py b/ipscan-v2.py index d44548b..c8deb9f 100644 --- a/ipscan-v2.py +++ b/ipscan-v2.py @@ -15,15 +15,16 @@ os.environ['PYTHONHTTPSVERIFY'] = '0' nm = nmap.PortScanner() # Scan the subnet for hosts (replace with your networks) -networks = [ - "192.168.85.0/24", - "192.168.86.0/24" -] +networks_env = os.getenv("NETWORKS", "192.168.85.0/24,192.168.86.0/24") +networks = [network.strip() for network in networks_env.split(",") if network.strip()] # NetBox configuration -netbox = pynetbox.api(url='https://netbox.xxxxx.xx/', token='xxxxx') +netbox_url = os.getenv("NETBOX_URL", "https://netbox.xxxxx.xx/") +netbox_token = os.getenv("NETBOX_TOKEN", "xxxxx") +ssl_verify = os.getenv("SSL_VERIFY", "false").lower() not in ("0", "false", "no", "n") +netbox = pynetbox.api(url=netbox_url, token=netbox_token, ssl_verify=ssl_verify) -tenant = "Xxxxx Praha" +tenant = os.getenv("TENANT", "Xxxxx Praha") def scan_network(network): print(f"Scanning network: {network}") diff --git a/scan.py b/scan.py new file mode 100644 index 0000000..2b2360a --- /dev/null +++ b/scan.py @@ -0,0 +1,67 @@ +import os +import socket +import nmap +import requests +from datetime import datetime + +requests.packages.urllib3.disable_warnings() +os.environ['PYTHONHTTPSVERIFY'] = '0' + +DEFAULT_NETWORKS = "192.168.85.0/24,192.168.86.0/24" + + +def load_networks(): + networks = os.getenv("SCAN_NETWORKS", DEFAULT_NETWORKS) + return [network.strip() for network in networks.split(",") if network.strip()] + + +def scan_network(network): + print(f"Scanning network: {network}") + nm = nmap.PortScanner() + nm.scan(hosts=network, arguments='-p 1-32768 -T4 --host-timeout 2m') + host_results = [] + + for host in nm.all_hosts(): + status = nm[host]["status"]["state"] + ports = [] + if 'tcp' in nm[host]: + ports = [ + port for port, info in nm[host]['tcp'].items() + if info['state'] == 'open' + ] + host_results.append((host, status, ports)) + print(f"Host: {host}, Status: {status}, Open ports: {' '.join(str(port) for port in ports)}") + + return host_results + + +def write_output(hosts, output_path): + os.makedirs(os.path.dirname(output_path), exist_ok=True) + header = f"# network.txt generated on {datetime.utcnow().isoformat()}Z\n" + + with open(output_path, 'w', encoding='utf-8') as output_file: + output_file.write(header) + output_file.write("# host status open_ports\n") + for host, status, ports in hosts: + ports_text = ' '.join(str(port) for port in ports) + output_file.write(f"{host} {status} {ports_text}\n") + + print(f"Scan saved to {output_path}") + + +def main(): + networks = load_networks() + all_hosts = [] + + for network in networks: + try: + all_hosts.extend(scan_network(network)) + except Exception as exc: + print(f"Failed to scan {network}: {exc}") + + output_path = os.getenv("OUTPUT_PATH", "/app/output/network.txt") + write_output(all_hosts, output_path) + + +if __name__ == '__main__': + main()