
Biblioteca Go idiomática para invocar um binário de scanner de rede, permitindo descoberta de hosts, varredura de portas, detecção de serviços/SO e verificações de vulnerabilidades por script para auditoria de segurança.
Esta biblioteca tem como objetivo fornecer bindings idiomáticos de nmap para desenvolvedores Go, a fim de facilitar a escrita de ferramentas de auditoria de segurança usando golang.
Nmap (Network Mapper) é um scanner de rede gratuito e de código aberto criado por Gordon Lyon. O Nmap é usado para descobrir hosts e serviços em uma rede de computadores, enviando pacotes e analisando as respostas.
O Nmap oferece uma série de recursos para sondar redes de computadores, incluindo descoberta de hosts e detecção de serviços e sistemas operacionais. Esses recursos são extensíveis por meio de scripts que fornecem detecção de serviços mais avançada, detecção de vulnerabilidades e outros recursos. O Nmap pode se adaptar às condições da rede, incluindo latência e congestionamento durante uma varredura.
A maioria das ferramentas de pentest atualmente é escrita em Python e não em Go, porque é fácil escrever scripts rapidamente, há muitas bibliotecas disponíveis e é uma linguagem simples de usar. No entanto, para escrever aplicações robustas e confiáveis, Go é a melhor ferramenta. Ela é compilada estaticamente, possui um sistema de tipos estático, desempenho muito melhor, também é uma linguagem muito simples de usar e goroutines são incríveis... Mas talvez eu esteja um pouco tendencioso, então sinta-se à vontade para discordar.
Esta biblioteca invoca o binário nmap usando o pacote exec do Go e analisa a saída XML.
Isso significa que o nmap deve estar instalado e disponível no seu PATH para que esta biblioteca funcione.
A compatibilidade é confirmada com a versão atual mais recente do nmap, 7.98.
Alguns tipos de varredura exigem privilégios elevados (por exemplo, varreduras SYN, detecção de SO ou uso de soquetes brutos). Se você habilitar essas opções, talvez seja necessário executar seu programa com sudo ou com as capacidades apropriadas para sua plataforma.
[!TIP] Para execuções sem privilégios, prefira varreduras do tipo connect (ex.:
-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)
}
O programa acima gera:
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] Isso depende de sequências de escape de terminal e só funciona quando o processo está anexado a um TTY.
[!NOTE] Não há garantia de que o progresso aumente de forma monotônica: o nmap estima o tempo restante e pode revisar essa estimativa, o que pode fazer com que a porcentagem informada diminua.
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 exemplo gera a seguinte saída:
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
}
}
}
Consulte o diretório examples para mais exemplos de uso.
Cameradar já utiliza esta biblioteca em seu núcleo para se comunicar com o nmap, descobrir streams RTSP e acessá-los remotamente.
Mais exemplos: