
Biblioteca Go idiomática para invocar un binario de escáner de red, que permite el descubrimiento de hosts, escaneo de puertos, detección de servicios/SO y comprobaciones de vulnerabilidades mediante scripts para auditoría de seguridad.
Esta biblioteca tiene como objetivo proporcionar bindings idiomáticos de nmap para desarrolladores de Go, con el fin de facilitar la escritura de herramientas de auditoría de seguridad usando golang.
Nmap (Network Mapper) es un escáner de redes gratuito y de código abierto creado por Gordon Lyon. Nmap se utiliza para descubrir hosts y servicios en una red informática mediante el envío de paquetes y el análisis de las respuestas.
Nmap ofrece una serie de funciones para explorar redes informáticas, incluido el descubrimiento de hosts y la detección de servicios y sistemas operativos. Estas funciones son ampliables mediante scripts que proporcionan una detección de servicios más avanzada, detección de vulnerabilidades y otras características. Nmap puede adaptarse a las condiciones de la red, incluyendo la latencia y la congestión durante un escaneo.
La mayoría de las herramientas de pentest se escriben actualmente con Python y no con Go, porque es fácil escribir scripts rápidamente, hay muchas bibliotecas disponibles y es un lenguaje sencillo de usar. Sin embargo, para escribir aplicaciones robustas y fiables, Go es la mejor herramienta. Está compilado estáticamente, tiene un sistema de tipos estático, un rendimiento mucho mejor, también es un lenguaje muy sencillo de usar y las goroutines son increíbles... Pero puede que esté un poco sesgado, así que no dudes en discrepar.
Esta biblioteca invoca el binario nmap usando el paquete exec de Go y analiza la salida XML. Eso significa que nmap debe estar instalado y disponible en tu PATH para que esta biblioteca funcione.
La compatibilidad está confirmada con la versión más reciente actual de nmap, 7.98.
Algunos tipos de escaneo requieren privilegios elevados (por ejemplo, los escaneos SYN, la detección de SO o el uso de sockets raw). Si habilitas esas opciones, es posible que necesites ejecutar tu programa con sudo o con las capacidades adecuadas para tu plataforma.
[!TIP] Para ejecuciones sin privilegios, prefiere los escaneos de conexión (p. ej.
-sT).
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/Ullaakut/nmap/v4"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
// Equivalent to `/usr/local/bin/nmap -p 80,443,843 google.com facebook.com youtube.com`,
// with a 5-minute timeout.
scanner, err := nmap.NewScanner(
nmap.WithTargets("scanme.nmap.org"),
nmap.WithPorts("80,443,843"),
)
if err != nil {
log.Fatalf("creating nmap scanner: %v", err)
}
result, err := scanner.Run(ctx)
if err != nil {
log.Fatalf("running network scan: %v", err)
}
warnings := result.Warnings()
if len(warnings) > 0 {
log.Printf("warning: %v\n", warnings) // Warnings are non-critical errors from nmap.
}
// Use the results to print an example output
for _, host := range result.Hosts {
if len(host.Ports) == 0 || len(host.Addresses) == 0 {
continue
}
fmt.Printf("Host %q:\n", host.Addresses[0])
for _, port := range host.Ports {
fmt.Printf("\tPort %d/%s %s %s\n", port.ID, port.Protocol, port.State, port.Service.Name)
}
}
fmt.Printf("Nmap done: %d hosts up scanned in %.2f seconds\n", len(result.Hosts), result.Stats.Finished.Elapsed)
}
El programa anterior imprime:
Host "45.33.32.156":
Port 80/tcp open http
Port 443/tcp closed https
Port 843/tcp closed
Nmap done: 1 hosts up scanned in 0.42 seconds
[!IMPORTANT] Esto depende de las secuencias de escape del terminal y solo funciona cuando el proceso está asociado a una TTY.
[!NOTE] No se garantiza que el progreso aumente de forma monótona: nmap calcula el tiempo restante y puede revisar esa estimación, lo que puede hacer que el porcentaje notificado baje.
package main
import (
"context"
"log"
"time"
"github.com/Ullaakut/nmap/v4"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
scanner, err := nmap.NewScanner(
nmap.WithTargets("scanme.nmap.org"),
nmap.WithPorts("1-1024"),
nmap.WithTimingTemplate(nmap.TimingAggressive),
nmap.WithProgress(time.Second, handleProgress),
)
if err != nil {
log.Fatalf("creating nmap scanner: %v", err)
}
_, err = scanner.Run(ctx)
if err != nil {
log.Fatalf("running network scan: %v", err)
}
}
func handleProgress(p nmap.TaskProgress) {
log.Println("Current progress: ", p.Percent)
}
Este ejemplo genera la siguiente salida:
2026/01/27 16:13:02 task "Connect Scan": 2.59% remaining 38
2026/01/27 16:13:02 task "Connect Scan": 21.26% remaining 4
2026/01/27 16:13:04 task "Connect Scan": 42.61% remaining 5
2026/01/27 16:13:04 task "Connect Scan": 45.51% remaining 4
2026/01/27 16:13:05 task "Connect Scan": 53.44% remaining 4
2026/01/27 16:13:07 task "Connect Scan": 59.77% remaining 5
2026/01/27 16:13:07 task "Connect Scan": 62.77% remaining 4
2026/01/27 16:13:08 task "Connect Scan": 73.24% remaining 3
2026/01/27 16:13:09 task "Connect Scan": 81.71% remaining 2
2026/01/27 16:13:10 task "Connect Scan": 92.92% remaining 1
2026/01/27 16:13:11 task "Connect Scan": 100.00% remaining 0
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/Ullaakut/nmap/v4"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
scanner, err := nmap.NewScanner(
nmap.WithTargets("scanme.nmap.org"),
nmap.WithPorts("1-1024"),
)
if err != nil {
log.Fatalf("creating nmap scanner: %v", err)
}
stdout, stderr, resultCh, err := scanner.RunAsync(ctx)
if err != nil {
log.Fatalf("running network scan: %v", err)
}
for {
select {
case <-ctx.Done():
log.Fatalf("scan timed out: %v", ctx.Err())
case out := <-stdout:
fmt.Printf("nmap output: %s\n", out)
case errOut := <-stderr:
fmt.Printf("nmap error output: %s\n", errOut)
case result := <-resultCh:
if result.Err != nil {
log.Fatalf("running network scan: %v", result.Err)
}
fmt.Printf("Nmap done: %d hosts up\n", len(result.Result.Hosts))
return
}
}
}
Consulta el directorio examples para ver más ejemplos de uso.
Cameradar ya utiliza esta biblioteca en su núcleo para comunicarse con nmap, descubrir flujos RTSP y acceder a ellos de forma remota.
Más ejemplos: