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
- 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.
- 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.
- Camp per introduir el rang de xarxa (per defecte
- 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.