1. 程式人生 > 其它 >golang建立簡單tcp掃描器

golang建立簡單tcp掃描器

實現最簡單的tcp掃描器:

最簡單的tcp掃描器非常簡單,我們只需要知道一個函式 net.Dial()

Go語言中 Dial() 函式用於建立網路連線,函式原型如下:
func Dial(network, address string) (Conn, error) {
var d Dialer
return d.Dial(network, address)
}
引數說明如下:
network 引數表示傳入的網路協議(比如 tcp、udp 等);
address 引數表示傳入的 IP 地址或域名,而埠號是可選的,如果需要指定的話,以:的形式跟在地址或域名的後面即可。如果連線成功,該函式返回連線物件,否則返回 error。

此函式會返回兩個引數,型別分別為conn和err,如果連線成功err會為空,也就是nil。所以我們只需要判斷err == nil。就能知道是否可以連線,從而達到探測的作用。下面是實現:

func main() {
	_, err := net.Dial("tcp", "scanme.nmap.org:80")
	if err == nil {
		fmt.Println("連線成功")
	}
}

很明顯,如果能夠連線,將會返回連線成功。這只是探測nmap測試網站的80埠,作為掃描肯定是不夠的,但是以此為基礎,我們可以很輕易的想到在程式碼的外層新增上迴圈,tcp埠範圍為165535,這裡我們只探測1

1000作為例子:

func main() {
	for i := 1; i <= 1000; i++ {
		addstr := fmt.Sprintf("scanme.nmap.org:%d", i)
		conn, err := net.Dial("tcp", addstr)
		if err != nil {
			continue
		}
		conn.Close()
		fmt.Println("埠", i, "開啟")
	}
}

這就已經是最簡單的掃描器了,當然,這個的掃描速度會慢的離譜,我們需要加上併發,go實現併發非常方便。但是我們要知道並不是併發數越高越好。
在這個掃描過程中,如果併發數量過高,會導致掃描速度過快而導致掃描結果不準確。所以我們需要控制併發,下面是用通道控制併發:

func worker(ports, results chan int) {
	for p := range ports {
		address := fmt.Sprintf("scanme.nmap.org:%d", p)
		conn, err := net.Dial("tcp", address)
		if err != nil {
			results <- 0
			continue
		}
		conn.Close()
		results <- p
	}
}

func main() {
	ports := make(chan int, 100)
	results := make(chan int)
	var resultPortsList []int
	for i := 1; i <= 50; i++ {
		go worker(ports, results)
	}
	go func() {
		for i := 1; i <= 1000; i++ {
			ports <- i
		}
	}()
	for i := 0; i < 1000; i++ {
		port := <-results
		if port != 0 {
			resultPortsList = append(resultPortsList, port)
		}
	}
	close(ports)
	close(results)
	sort.Ints(resultPortsList)
	for _, port := range resultPortsList {
		fmt.Println(port, "is open")
	}
}

這樣,一個簡單的掃描器就完成了。