in

Port Scanner written in Go

Golang Project

Note: Only utilize a port scanner on sites you have permission to test. Also, note the legalities of port scanners in your territories.

Update 8/13/17: I made a few modifications to the code. Namely:

  1. some software answers on a port but doesn’t respond and isn’t closed causing a hang. I put a timeout on the read action
  2. I used 4 go routines to add concurrency.
  3. I removed the bufio ReadString methods in place of raw bytes read in the buffer using this users methodology: https://gist.github.com/kenshinx/5796276  It improved the performance from 8000 ports scaned in over a min, to under 20 seconds!

Go Project

As I’m learning the Go language, I thought I’d work on a small project of making a utility I wrote in Python, in the Go language.  In this case, I chose a port scanner I wrote in Python.  The scanner tries to interrogate ports and return any banner that would indicate what’s installed there.

The original code I wrote in Python utilized the socket and sys libraries.  I wrote it while taking an InfoSec course over at Offensive Security.  Anyway… years later, I’m thinking of a project to try and do in Go (just go kick the tires and get used to the code) and I figure I might as well port that project into Go.

Go Port Scanner

The code is simple it basically kicks off a shell prompt asking for a host, then a starting port and an ending port.  It then iterates over the port range, trying each port in turn.

Here’s the code (link):

package main

import (
	"fmt"
	"net"
	"time"
	"sync"
)

var host string
var start_port int
var end_port int
var wg sync.WaitGroup

func main() {
	user_input()
}

func check_port(host string, start_port, end_port int) {

	for i := start_port; i <= end_port; i++ {
		//fmt.Println('\n')
		qualified_host := fmt.Sprintf("%s%s%d", host, ":", i)
		conn, err := net.DialTimeout("tcp", qualified_host, 10*time.Millisecond)  // Got the timeout code from: https://stackoverflow.com/questions/37294052/golang-why-net-dialtimeout-get-timeout-half-of-the-time
		if err != nil {
			continue
		}
		fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n1\n22\n\n\n\n")
		conn.SetReadDeadline(time.Now().Add(10*time.Millisecond))

		// swapping bufio reads to reading buffers as bytes gets huge performance increase: 8000 ports in 20s (vs 1min 10s using bufio reads)
		buff := make([]byte, 1024)
		n, _ := conn.Read(buff)
		fmt.Printf("Port: %d%s\n",i, buff[:n])
	}
	wg.Done()
}

func user_input() {
	fmt.Println("Host> ")
	fmt.Scan(&host)
	fmt.Println("Starting Port (i.e. 80)> ")
	fmt.Scan(&start_port)
	fmt.Println("End Port (i.e. 8080)> ")
	fmt.Scan(&end_port)
	fmt.Println("Running scan... ")

	//check_port_set1(host, start_port, end_port) // 15s to run 1000 ports sequentially

	port_range := end_port - start_port
	end_port_set1 := (port_range / 4) + start_port
	end_port_set2 := (port_range / 4) + end_port_set1
	end_port_set3 := (port_range / 4) + end_port_set2

	wg.Add(4)		// 3s to run 1000 ports on 4 concurrent groups
	go check_port(host, start_port, end_port_set1)
	go check_port(host, (end_port_set1 + 1), end_port_set2)
	go check_port(host, (end_port_set2 + 1), end_port_set3)
	go check_port(host, (end_port_set3 + 1), end_port)
	wg.Wait()

}

What do you think?

0 points
Upvote Downvote

Total votes: 0

Upvotes: 0

Upvotes percentage: 0.000000%

Downvotes: 0

Downvotes percentage: 0.000000%

Written by Admin

I work for a Telecom company writing and testing software. My passion for writing code is expressed through this blog. It's my hope that it gives hope to any and all who are self-taught.

Go Basics – Defer

Go and OOP