Ullaakut / nmap

Idiomatic nmap library for go developers
MIT License
939 stars 105 forks source link

RunWithProgress goes from 100% to 0% and back again #101

Open stephanebruckert opened 2 years ago

stephanebruckert commented 2 years ago

When the IP range is < /26 the progress is not accurate as it goes to 100% and then back to 0% multiple times:

✗ go run main.go
Progress: 27.25 %
Progress: 43.55 %
Progress: 54.1 %
Progress: 75.49 %
Progress: 75.49 %
Progress: 89.06 %
Progress: 95.51 %
Progress: 97.75 %
Progress: 32.3 % <------
Progress: 56.64 %
Progress: 56.64 %
Progress: 84.96 %
Host "172.217.169.0":
    Port 80/tcp open http
Host "172.217.169.1":
    Port 80/tcp open http
Host "172.217.169.2":
    Port 80/tcp open http
Host "172.217.169.3":
    Port 80/tcp open http
package main

import (
    "context"
    "fmt"
    "github.com/Ullaakut/nmap/v2"
    "log"
    "time"
)

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
    defer cancel()

    scanner, err := nmap.NewScanner(
        nmap.WithTargets("172.217.169.0/24"),
        nmap.WithPorts("80"),
        nmap.WithContext(ctx),
        nmap.WithVerbosity(3),
    )
    if err != nil {
        log.Fatalf("unable to create nmap scanner: %v", err)
    }

    progress := make(chan float32, 1)

    // Function to listen and print the progress
    go func() {
        for p := range progress {
            fmt.Printf("Progress: %v %%\n", p)
        }
    }()

    result, warnings, err := scanner.RunWithProgress(progress)
    if err != nil {
        log.Fatalf("unable to run nmap scan: %v", err)
    }

    if warnings != nil {
        log.Printf("Warnings: \n %v", warnings)
    }
    // 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 %3f seconds\n", len(result.Hosts), result.Stats.Finished.Elapsed)
}
elivlo commented 2 years ago

Hi @stephanebruckert :)

I know this problem, but haven't found a solution for it. The progress is directly captured by the stdout from nmap. nmap splits the scans into multiple steps or parts and calculates the progress for every step. And we do not know the quantity of steps either. :/

stephanebruckert commented 2 years ago

nmap alone seems to manage the progress correctly, apart from some very slight decreases https://security.stackexchange.com/questions/141548/nmap-tcp-scan-decreases-the-progress-percentage

There must be a way, I will have a deeper look when I get some time