Ullaakut / nmap

Idiomatic nmap library for go developers
MIT License
922 stars 102 forks source link

Run nmap without runtime interaction #113

Open wallrj opened 1 year ago

wallrj commented 1 year ago

Thanks for this great module.

When I use it, it corrupts the terminal.

I think you need to provide an option to run nmap without runtime interaction. (There's a not well documented --noninteractive CLI flag in my version of nmap)

My temporary work around:

diff --git a/nmap.go b/nmap.go
index 206f38a..60d06b7 100644
--- a/nmap.go
+++ b/nmap.go
@@ -15,6 +15,7 @@ func getServerInfo(ctx context.Context, ...) (string, error) {
        log := klog.FromContext(ctx)
        scanner, err := nmap.NewScanner(
                ctx,
+               nmap.WithCustomArguments("--noninteractive"),
                nmap.WithTargets(r.CommonName),
                nmap.WithPorts("443"),
                nmap.WithServiceInfo(),
$ nmap -V
Nmap version 7.80 ( https://nmap.org )
Platform: x86_64-pc-linux-gnu
Compiled with: liblua-5.3.6 openssl-3.0.2 nmap-libssh2-1.8.2 libz-1.2.11 libpcre-8.39 libpcap-1.10.1 nmap-libdnet-1.12 ipv6
Compiled without:
Available nsock engines: epoll poll select
$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.2 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.2 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian

See also:

elivlo commented 1 year ago

Hi @wallrj,

Indeed, you have found a command line argument we do not have implemented yet. I will shortly open a PR out of this Issue to add the option to provide this with an option. :) Will your terminal break all the time you run Nmap with this wrapper?

wallrj commented 1 year ago

Will your terminal break all the time you run Nmap with this wrapper?

Yes it breaks everytime. Probably because my program prints to stdout and from a separate go routine. I would recommend making --noninteractive the default, but I'm not sure if all versions of nmap support the flag.

Perhaps instead you can provide a closed stdin before executing nmap.

qashlan commented 1 year ago

I want to be assigned on the issue

elivlo commented 1 year ago

@Ahmedelqashlan

I want to be assigned on the issue

Sure. You can open a PR when you have a solution for it. What's your plan to solve it?

qashlan commented 1 year ago

@Ahmedelqashlan

I want to be assigned on the issue

Sure. You can open a PR when you have a solution for it. What's your plan to solve it?

@elivlo Perhaps it could be added to the options and can be added to scanner as arg

elivlo commented 1 year ago

I reproduced the issue with the following code, sampled and modified from the example basic_scan_async and running the latest version of Fedora and with Nmap version 7.93.

I am still unconfident implementing this argument in the Run function. Furthermore, I was considering adding a short hint to the Scanner documentation and the Option which @Ahmedelqashlan implemented.

But, since we do not provide a way to interact with Nmap with stdin, we could also disable it by default. @wallrj That supports your suggestion, right?

The example to reproduce the issue:

// Equivalent to `/usr/local/bin/nmap -p 80,443,843 google.com facebook.com youtube.com`,
// with a 5-minute timeout.
s, err := nmap.NewScanner(
    context.Background(),
    nmap.WithTargets("google.com", "facebook.com", "youtube.com"),
    nmap.WithPorts("1-65535"),
    //nmap.WithCustomArguments("--noninteractive"),
)
if err != nil {
    log.Fatalf("unable to create nmap scanner: %v", err)
}

// Executes asynchronously, allowing results to be streamed in real time.
done := make(chan error)
result, warnings, err := s.Async(done).Run()
if err != nil {
    log.Fatal(err)
}

fmt.Println(s.Args())

for {
    var in string
    _, err := fmt.Scanln(&in)
    if err != nil {
        fmt.Println(err)
        break
    }
    fmt.Println(in)
    if in == "exit" {
        break
    }
}

// Blocks main until the scan has completed.
if err := <-done; err != nil {
    if len(*warnings) > 0 {
        log.Printf("run finished with warnings: %s\n", *warnings) // Warnings are non-critical errors from nmap.
    }
    log.Fatal(err)
}