Skip to content

Commit

Permalink
Merge pull request #1 from vokomarov/feature/scan-hosts
Browse files Browse the repository at this point in the history
Implement host scanning
  • Loading branch information
vokomarov committed Mar 8, 2020
2 parents c17fa53 + 75f1c4b commit 289e0ac
Show file tree
Hide file tree
Showing 9 changed files with 494 additions and 2 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*.dll
*.so
*.dylib
.idea

# Test binary, built with `go test -c`
*.test
Expand All @@ -12,4 +13,4 @@
*.out

# Dependency directories (remove the comment below to include it)
# vendor/
vendor/
63 changes: 62 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,63 @@
# netshark
Command line tool to scan local network and opened ports
[![Build Status](https://travis-ci.org/vokomarov/netshark.svg?branch=master)](https://travis-ci.org/vokomarov/netshark)
[![Coverage Status](https://coveralls.io/repos/github/vokomarov/netshark/badge.svg?branch=master)](https://coveralls.io/github/vokomarov/netshark?branch=master)
[![GoDoc](https://godoc.org/github.com/DimitarPetrov/stegify?status.svg)](https://godoc.org/github.com/DimitarPetrov/stegify)
[![Go Report Card](https://goreportcard.com/badge/github.com/vokomarov/netshark)](https://goreportcard.com/report/github.com/vokomarov/netshark)

## Overview

`netshark` is a simple command line tool to scan your local network to available hosts and his opened ports.

Features:
- Scan local network neighbor hosts
- Display client MAC address

Coming soon:
- Scan opened TCP ports
- Specify scanning port ranges
- Use predefined port ranges to scan
- Multithreaded scan
- Shadow scan
- Use STDIN as source of hosts to support Unix pipes

## Installation

#### Installing from Source

```
go get -u github.com/vokomarov/netshark
```

#### Download

Download binary for your system [here](https://github.com/vokomarov/netshark/releases).

## Usage

### As a command line tool

```shell script
# Scan local network for neighbor hosts
$ netshark scan hosts [--timeout 15]

# Scan given host for opened ports of all port range
$ netshark scan ports --host 192.168.1.1 # scan specific

# Specify TCP port range from lower to higher number of ports
$ netshark scan ports --range 1,65535
$ netshark scan ports --range-min 1024 # check registered ports and private ports range
$ netshark scan ports --range-max 1023 # check only well-known port range

# Or use predefined port ranges
$ netshark scan ports --range known # scan ports from 0 to 1023
$ netshark scan ports --range reg # scan ports from 1024 to 49151
$ netshark scan ports --range private # scan ports from 49152 to 65535
```

### Programmatically in your code

`netshark` can be used programmatically. You can visit [godoc](https://godoc.org/github.com/vokomarov/netshark) to check API documentation.

## License

`netshark` is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT).
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module github.com/vokomarov/netshark

go 1.14

require (
github.com/google/gopacket v1.1.17
github.com/jessevdk/go-flags v1.4.0
)
11 changes: 11 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY=
github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM=
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 h1:1Fzlr8kkDLQwqMP8GxrhptBLqZG/EDpiATneiZHY998=
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
64 changes: 64 additions & 0 deletions hosts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package main

import (
"fmt"
"os"
"os/signal"
"time"

"github.com/vokomarov/netshark/scanner/host"
)

type HostsCommand struct {
Timeout int `short:"t" long:"timeout" default:"5" description:"Timeout in seconds to wait for ARP responses."`
}

func (c *HostsCommand) Execute(_ []string) error {
fmt.Printf("Scanning Hosts..\n")

quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)

scanner := host.NewScanner()

go scanner.Scan()

timeout := time.NewTicker(time.Duration(c.Timeout) * time.Second)

func() {
for {
fmt.Printf("found %d hosts...\r", len(scanner.Hosts))

time.Sleep(1 * time.Second)

select {
case <-timeout.C:
scanner.Stop()
return
case <-quit:
scanner.Stop()
return
case <-scanner.Done:

return
default:
}
}
}()

// Clear line
fmt.Printf("%c[2K\r", 27)

if scanner.Error != nil {
fmt.Printf("\n\r")
return scanner.Error
}

fmt.Printf("\nFound %d hosts: \n", len(scanner.Hosts))

for _, h := range scanner.Hosts {
fmt.Printf(" [IP: %s] \t [MAC: %s] \n", h.IP, h.MAC)
}

return nil
}
44 changes: 44 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

import (
"fmt"
"os"

"github.com/jessevdk/go-flags"
)

var parser *flags.Parser

type scanCommand struct {
HostsCommand HostsCommand `command:"hosts" description:"Scan all available neighbor hosts of current local network"`
PortsCommand PortsCommand `command:"ports" description:"Scan open ports on a host"`
}

func registerCommands(parser *flags.Parser) {
_, _ = parser.AddCommand(
"scan",
"Network scanner",
"Perform scanning over network",
&scanCommand{},
)
}

func init() {
parser = flags.NewParser(nil, flags.HelpFlag|flags.PassDoubleDash)
registerCommands(parser)
}

func main() {
if _, err := parser.Parse(); err != nil {
if flagsErr, ok := err.(*flags.Error); ok && flagsErr.Type == flags.ErrHelp {
os.Exit(0)
return
} else {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
return
}
}

os.Exit(0)
}
13 changes: 13 additions & 0 deletions ports.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package main

import (
"fmt"
)

type PortsCommand struct {
}

func (c *PortsCommand) Execute(_ []string) error {
fmt.Printf("Scanning Ports..\n")
return nil
}
23 changes: 23 additions & 0 deletions scanner/host/host.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package host

import (
"crypto/md5"
"fmt"
"io"
)

type Host struct {
id string
IP string
MAC string
}

func (h *Host) ID() string {
if h.id == "" {
hash := md5.New()
_, _ = io.WriteString(hash, h.IP+h.MAC)
h.id = fmt.Sprintf("%x", hash.Sum(nil))
}

return h.id
}
Loading

0 comments on commit 289e0ac

Please sign in to comment.