Descripció

Aquest programa en Python permet realitzar un escaneig de xarxa utilitzant la potent eina Nmap, mostrant els resultats en una interfície gràfica intuïtiva amb mode fosc. És ideal per a administradors de sistemes, tècnics de xarxa o entusiastes que vulguin identificar dispositius actius i els ports oberts en la seva xarxa local.


Funcionalitats principals

  • Detecció de dispositius actius en un rang d’IP especificat.
  • Resolució opcional de noms d’host (hostnames).
  • Escaneig de ports oberts (del 1 al 1024) per a cada dispositiu detectat.
  • Interfície gràfica moderna amb Tkinter i estil en mode fosc.
  • Actualització automàtica cada 60 segons sense bloquejar la interfície.
  • Botó d’escaneig manual per iniciar el procés en qualsevol moment.

Requisits previs

Abans d’executar el programa, assegura’t de tenir:

  • Python 3 instal·lat.
  • Nmap (eina externa per a l’escaneig).
  • Llibreries estàndard de Python: subprocess, socket, tkinter, threading, time.

Instal·lació de Nmap:

sudo apt install nmap    # Debian/Ubuntu
brew install nmap        # macOS

Com funciona el programa

  1. Escaneig de xarxa (scan_with_nmap)\

Executa nmap -sn per descobrir dispositius actius en el rang IP indicat.

  • Si s’activa l’opció Resoldre Hostnames, intenta obtenir el nom del dispositiu amb socket.gethostbyaddr().
  • Escaneig de ports (scan_ports)\

Per cada IP trobada, executa nmap -p 1-1024 --open per llistar els ports oberts.

  1. Interfície gràfica
    • Camp per introduir el rang de xarxa (per defecte 192.168.1.0/24).
    • Checkbox per resoldre hostnames.
    • Botó Escanejar Ara per iniciar l’anàlisi.
    • Taula amb columnes: IP, Hostname, Estat, Ports Actius.
    • Barra de progrés i missatges d’estat.
  2. Actualització automàtica\

Un fil secundari executa l’escaneig cada 60 segons sense interrompre la interfície.


Codi complet

Inclou el codi dins d’un bloc amb format per a WordPress:

import subprocess
import socket
import tkinter as tk
from tkinter import ttk
import threading
import time

def scan_with_nmap(network_range, resolve_hostname=False):
    hosts = []
    try:
        result = subprocess.run(["nmap", "-sn", network_range, "-oG", "-"], capture_output=True, text=True)
        for line in result.stdout.splitlines():
            if "Host:" in line and "Status: Up" in line:
                ip = line.split()[1]
                hostname = "Unknown"
                if resolve_hostname:
                    try:
                        hostname = socket.gethostbyaddr(ip)[0]
                    except:
                        hostname = "No resuelto"
                hosts.append((ip, hostname))
    except Exception as e:
        print(f"Error ejecutando nmap: {e}")
    return hosts

def scan_ports(ip):
    ports = []
    try:
        result = subprocess.run(["nmap", "-p", "1-1024", "--open", ip], capture_output=True, text=True)
        for line in result.stdout.splitlines():
            if "/tcp" in line and "open" in line:
                port = line.split()[0]
                ports.append(port)
    except Exception as e:
        print(f"Error escaneando puertos en {ip}: {e}")
    return ports

def scan_network():
    status_label.config(text="Escaneando red...")
    progress_bar.start()
    root.update_idletasks()

    network_range = entry_range.get()
    resolve_hostname = hostname_var.get()

    hosts = scan_with_nmap(network_range, resolve_hostname)

    for row in tree.get_children():
        tree.delete(row)

    for ip, hostname in hosts:
        status_label.config(text=f"Escaneando puertos en {ip}...")
        root.update_idletasks()
        ports = scan_ports(ip)
        ports_str = ", ".join(ports) if ports else "Ninguno"
        tree.insert("", "end", values=(ip, hostname, "Activo", ports_str))

    status_label.config(text=f"Escaneo completado: {len(hosts)} dispositivos encontrados")
    progress_bar.stop()

def auto_refresh():
    while True:
        scan_network()
        time.sleep(60)

# Interfaz gráfica con Dark Mode
root = tk.Tk()
root.title("Escaneo de Red con Nmap - Dark Mode")

style = ttk.Style()
style.theme_use("clam")
style.configure("Treeview", background="#2b2b2b", foreground="white", fieldbackground="#2b2b2b")
style.configure("Treeview.Heading", background="#444", foreground="white")
style.configure("TLabel", background="#1e1e1e", foreground="white")
style.configure("TButton", background="#333", foreground="white")
root.configure(bg="#1e1e1e")

frame_top = tk.Frame(root, bg="#1e1e1e")
frame_top.pack(pady=10)

tk.Label(frame_top, text="Rango de red:", bg="#1e1e1e", fg="white").pack(side="left", padx=5)
entry_range = tk.Entry(frame_top, bg="#333", fg="white", insertbackground="white")
entry_range.insert(0, "192.168.1.0/24")
entry_range.pack(side="left", padx=5)

hostname_var = tk.BooleanVar()
tk.Checkbutton(frame_top, text="Resolver Hostnames", variable=hostname_var, bg="#1e1e1e", fg="white", selectcolor="#333").pack(side="left", padx=5)

scan_button = tk.Button(frame_top, text="Escanear Ahora", command=lambda: threading.Thread(target=scan_network, daemon=True).start(), bg="#444", fg="white")
scan_button.pack(side="left", padx=5)

status_label = tk.Label(root, text="Listo para escanear", font=("Arial", 12), bg="#1e1e1e", fg="white")
status_label.pack(pady=5)

progress_bar = ttk.Progressbar(root, mode="indeterminate")
progress_bar.pack(fill="x", padx=10, pady=5)

columns = ("IP", "Hostname", "Estado", "Puertos Activos")
tree = ttk.Treeview(root, columns=columns, show="headings")
for col in columns:
    tree.heading(col, text=col)
    tree.column(col, width=180)
tree.pack(expand=True, fill="both", padx=10, pady=10)

threading.Thread(target=auto_refresh, daemon=True).start()

root.mainloop()

Captura recomanada

Mostra la interfície en mode fosc amb la taula de resultats.


Advertiments

  • El programa necessita permisos per executar Nmap (pot requerir privilegis d’administrador).
  • Utilitza’l només en xarxes on tinguis autorització per fer escaneigs.
  • L’escaneig de ports pot tardar uns segons per dispositiu.