commit ce91b2e52052482f44a70547370088cb7307d25e Author: Vlastislav Svatek Date: Wed May 20 13:50:28 2026 +0200 first commit diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..32d112e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +# Použití základního Python image +FROM python:3.14-rc-slim + +# Instalace Tini +RUN apt-get update && apt-get install -y tini + +# Nastavení Tini jako init procesu +ENTRYPOINT ["/usr/bin/tini", "--"] + +# Nastavení pracovního adresáře +WORKDIR /app + +# Zkopírování požadavků +COPY requirements.txt requirements.txt + +# Instalace Python knihoven +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 + +# 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"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..a6bf558 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,6 @@ +version: '3' +services: + netbox-importer: + build: . + container_name: netbox_importer + tty: true diff --git a/ipscan-v2.py b/ipscan-v2.py new file mode 100644 index 0000000..cadd949 --- /dev/null +++ b/ipscan-v2.py @@ -0,0 +1,110 @@ +import os +import nmap +import pynetbox +import requests +import socket +from concurrent.futures import ThreadPoolExecutor, as_completed + +# Disable SSL Warnings +requests.packages.urllib3.disable_warnings() + +# Disable SSL Verification +os.environ['PYTHONHTTPSVERIFY'] = '0' + +# Initiate the port scanner +nm = nmap.PortScanner() + +# Scan the subnet for hosts (replace with your networks) +networks = [ + "192.168.64.0/24", + "192.168.65.0/24", + "192.168.68.0/24", + "192.168.72.0/24", + "192.168.73.0/24", + "192.168.74.0/24", + "192.168.75.0/24", + "192.168.80.0/24", + "192.168.81.0/24", + "192.168.83.0/24", + "192.168.84.0/24", + "192.168.85.0/24", + "192.168.86.0/24" +] + +# NetBox configuration +netbox = pynetbox.api(url='https://netbox.quanti.cz/', token='a20493110ca9b9c1658ff624d8668b45260e1b02') + +tenant = "Quanti Praha" + +def scan_network(network): + print(f"Scanning network: {network}") + nm.scan(hosts=network, arguments='-p 1-32768 -T4 --host-timeout 2m') # Adding a host-timeout of 2 minutes + host_results = [] + for host in nm.all_hosts(): + if 'tcp' in nm[host]: + ports = [port for port in nm[host]['tcp'] if nm[host]['tcp'][port]['state'] == 'open'] + ports_str = ' '.join(str(port) for port in ports) + else: + ports_str = '' + host_results.append((host, nm[host]['status']['state'], ports_str)) + print(f"Host: {host}, Status: {nm[host]['status']['state']}, Open Ports: {ports_str}") + return host_results + +def add_ip_to_netbox(host, status, ports): + if status == 'up': + try: + hostname = socket.gethostbyaddr(host)[0] + except socket.herror: + hostname = host # Use the IP if the hostname couldn't be resolved + + ip_data = { + "address": f"{host}/24", + "dns_name": hostname, + "status": "active", + "tenant": tenant, + "comments": f"Open ports: {ports}", + # Add other fields as needed + } + + # Create or update the IP address in NetBox + print(f"Adding IP address: {ip_data['address']}, Hostname: {hostname}, Open Ports: {ports}") + netbox.ipam.ip_addresses.create(ip_data) + +# Create a thread pool and scan networks in parallel +hosts_list = [] +with ThreadPoolExecutor(max_workers=5) as executor: # Adjust number of workers as needed + future_to_network = {executor.submit(scan_network, network): network for network in networks} + for future in as_completed(future_to_network): + network = future_to_network[future] + try: + data = future.result() + hosts_list.extend(data) + except Exception as exc: + print(f"{network} generated an exception: {exc}") + +# Add each IP address to NetBox +with ThreadPoolExecutor(max_workers=5) as executor: # Adjust number of workers as needed + futures = [executor.submit(add_ip_to_netbox, host, status, ports) for host, status, ports in hosts_list] + for future in as_completed(futures): + future.result() + +# Get all IP addresses from NetBox +all_ip_addresses = netbox.ipam.ip_addresses.all() + +# Create a list of hostnames from the scanned hosts +scanned_hosts = [] +for host, status, ports in hosts_list: + if status == 'up': + try: + hostname = socket.gethostbyaddr(host)[0] + except socket.herror: + hostname = host # Use the IP if the hostname couldn't be resolved + scanned_hosts.append(hostname) + +# Check each IP address in NetBox +for ip_address in all_ip_addresses: + # If the IP address's hostname was not found in the scan results, mark it as offline + if ip_address.description not in scanned_hosts: + ip_address.status = 'offline' + ip_address.save() + print(f"Marked IP address {ip_address.address} as offline in NetBox.") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..5bf5adb --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +python-nmap==0.7.1 +pynetbox==7.4.1 +requests==2.32.3 \ No newline at end of file diff --git a/scanner.py b/scanner.py new file mode 100644 index 0000000..075021f --- /dev/null +++ b/scanner.py @@ -0,0 +1,72 @@ +import os +import nmap +import pynetbox +import requests +import socket + +# Disable SSL Warnings +requests.packages.urllib3.disable_warnings() + +# Disable SSL Verification +os.environ['PYTHONHTTPSVERIFY'] = '0' + +# Initiate the port scanner +nm = nmap.PortScanner() + +# Scan the subnet for hosts for example 192.168.1.0/24 +nm.scan(hosts='192.168.1.0/24', arguments='-sn') + +# Get a list of all hosts that are up +hosts_list = [(x, nm[x]['status']['state']) for x in nm.all_hosts()] +for host, status in hosts_list: + print(f'{host} is {status}') + +# Enter your Netbox url and token +netbox = pynetbox.api(url='https://example.com', token='TOKENHERE', ssl_verify=False) + +# Add each host to NetBox +for host, status in hosts_list: + if status == 'up': + try: + hostname = socket.gethostbyaddr(host)[0] + except socket.herror: + hostname = host # Use the IP if the hostname couldn't be resolved + + device_data = { + "name": hostname, + "device_type": 1, # device type ID + "device_role": 1, # device role ID + "site": 1, # site ID + "status": "active", + # Add other fields as needed + } + +# Get all the devices from NetBox +all_devices = netbox.dcim.devices.all() + +# Create a list of hostnames from the scanned hosts +scanned_hosts = [] +for host, status in hosts_list: + if status == 'up': + try: + hostname = socket.gethostbyaddr(host)[0] + except socket.herror: + hostname = host # Use the IP if the hostname couldn't be resolved + scanned_hosts.append(hostname) + +# Check each device in NetBox +for device in all_devices: + # If the device was not found in the scan results, mark it as offline + if device.name not in scanned_hosts: + device.status = 'offline' + device.save() + print(f"Marked {device.name} as offline in NetBox.") + + # Remove the IP address of the offline device from NetBox + try: + ip_address = netbox.ipam.ip_addresses.get(address=f"{device.name}/24") + if ip_address: + ip_address.delete() + print(f"Deleted IP address {device.name} from NetBox.") + except Exception as e: + print(f"Failed to delete IP address {device.name} from NetBox: {e}")