golang建立簡單tcp掃描器
阿新 • • 發佈:2022-03-25
實現最簡單的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
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")
}
}
這樣,一個簡單的掃描器就完成了。