Skip to content

Instantly share code, notes, and snippets.

@krmnn
Created December 13, 2019 09:13
Show Gist options
  • Save krmnn/e00934290e3d849be4945fe36e731532 to your computer and use it in GitHub Desktop.
Save krmnn/e00934290e3d849be4945fe36e731532 to your computer and use it in GitHub Desktop.
a simple threaded port scanner in go
package main
import (
"errors"
"fmt"
"net"
"os"
"sort"
"time"
)
type portinfo struct {
number int
isOpen bool
}
var tcpTimeout, _ = time.ParseDuration("200ms")
type ByPortNumber []portinfo
func (a ByPortNumber) Len() int { return len(a) }
func (a ByPortNumber) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByPortNumber) Less(i, j int) bool {
return a[i].number < a[j].number
}
func scanPort(channel chan portinfo, host string, port int) (err error) {
target := fmt.Sprintf("%s:%d", host, port)
tcpAddress, err := net.ResolveTCPAddr("tcp4", target)
if err != nil {
channel <- portinfo{port, false}
return errors.New("Resolving of address failed.")
}
conn, err := net.DialTimeout("tcp", tcpAddress.String(), tcpTimeout)
if err != nil {
channel <- portinfo{port, false}
} else {
channel <- portinfo{port, true}
conn.Close()
}
return nil
}
func main() {
numports := 32768
startTime := time.Now()
if len(os.Args) != 2 {
fmt.Println("usage: portscanner idealo.de")
return
}
host := os.Args[1]
channel := make(chan portinfo, numports)
fmt.Printf("Scanning host '%s'\n", host)
for port := 1; port < numports; port++ {
go scanPort(channel, host, port)
}
var results []portinfo
for port := 1; port < numports; port++ {
s := <-channel
results = append(results, s)
}
close(channel)
sort.Sort(ByPortNumber(results))
for idx := range results {
if results[idx].isOpen == true {
fmt.Printf("%10d: open\n", results[idx].number)
}
}
fmt.Printf("Finished in %v\n", time.Now().Sub(startTime))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment