Go语言(Golang)编写 TCP 端口扫描器

· 1min · Paxon Qiao

Go 语言编写 TCP 扫描器

TCP

  • TCP,也就是传输控制协议(Transmission Control Protocol)。

TCP握手

  • 建立 TCP连接(或者叫打开端口),需要3次握手

客户端 -> 端口打开 ->服务器

  1. syn (请求建立新连接)
  2. syn-ack (同意创建新连接)
  3. ack (表示响应)
  • 服务端端口关闭 Closed Port
    • client -syn-> Server
    • Server -rst-> Client
  • 如果存在防火墙 Filtered Port
    • Client —syn (Timeout)— Firewall Server

非并发的 TCP 扫描器

创建目录并在该目录创建main.go 文件

~/Code/go via 🐹 v1.20.3 via 🅒 base
➜ mcd tcp-scanner

Code/go/tcp-scanner via 🐹 v1.20.3 via 🅒 base
➜ go mod init
go: cannot determine module path for source directory /Users/qiaopengjun/Code/go/tcp-scanner (outside GOPATH, module path must be specified)

Example usage:
 'go mod init example.com/m' to initialize a v0 or v1 module
 'go mod init example.com/m/v2' to initialize a v2 module

Run 'go help mod init' for more information.

Code/go/tcp-scanner via 🐹 v1.20.3 via 🅒 base
➜ go mod init tcp-scanner
go: creating new go.mod: module tcp-scanner

Code/go/tcp-scanner via 🐹 v1.20.3 via 🅒 base
➜ c

Code/go/tcp-scanner via 🐹 v1.20.3 via 🅒 base

main.go 文件

package main

import (
 "fmt"
 "net"
)

func main() {
 for i := 21; i < 120; i++ {
  address := fmt.Sprintf("20.194.168.28:%d", i)
  conn, err := net.Dial("tcp", address)
  if err != nil {
   fmt.Printf("%s failed 关闭了\n", address)
   continue
  }
  conn.Close()
  fmt.Printf("%s connected 打开了!!!\n", address)
 }
}

并发的 TCP 扫描器

package main

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

func main() {
 start := time.Now()
 var wg sync.WaitGroup
 for i := 21; i < 120; i++ {
  wg.Add(1)
  go func(j int) {
   defer wg.Done()
   address := fmt.Sprintf("20.194.168.28:%d", j)
   conn, err := net.Dial("tcp", address)
   if err != nil {
    fmt.Printf("%s 关闭了\n", address)
    return
   }
   conn.Close()
   fmt.Printf("%s 打开了!!!\n", address)
  }(i)
 }
 wg.Wait()
 elapsed := time.Since(start) / 1e9
 fmt.Printf("\n\n%d seconds", elapsed)
}

// func main() {
//  for i := 21; i < 120; i++ {
//   address := fmt.Sprintf("20.194.168.28:%d", i)
//   conn, err := net.Dial("tcp", address)
//   if err != nil {
//    fmt.Printf("%s failed 关闭了\n", address)
//    continue
//   }
//   conn.Close()
//   fmt.Printf("%s connected 打开了!!!\n", address)
//  }
// }

并发的 TCP 扫描器 - WORKER 池

package main

import (
 "fmt"
 "sync"
)

func worker(ports chan int, wg *sync.WaitGroup) {
 for p := range ports {
  fmt.Println("p", p)
  wg.Done()
 }
}

func main() {
 ports := make(chan int, 100)
 var wg sync.WaitGroup

 for i := 0; i < cap(ports); i++ {
  go worker(ports, &wg)
 }

 for i := 1; i < 1024; i++ {
  wg.Add(1)
  ports <- i
 }

 wg.Wait()
 close(ports)
}

// func main() {
//  start := time.Now()
//  var wg sync.WaitGroup
//  for i := 21; i < 120; i++ {
//   wg.Add(1)
//   go func(j int) {
//    defer wg.Done()
//    address := fmt.Sprintf("20.194.168.28:%d", j)
//    conn, err := net.Dial("tcp", address)
//    if err != nil {
//     fmt.Printf("%s 关闭了\n", address)
//     return
//    }
//    conn.Close()
//    fmt.Printf("%s 打开了!!!\n", address)
//   }(i)
//  }
//  wg.Wait()
//  elapsed := time.Since(start) / 1e9
//  fmt.Printf("\n\n%d seconds", elapsed)
// }

// func main() {
//  for i := 21; i < 120; i++ {
//   address := fmt.Sprintf("20.194.168.28:%d", i)
//   conn, err := net.Dial("tcp", address)
//   if err != nil {
//    fmt.Printf("%s failed 关闭了\n", address)
//    continue
//   }
//   conn.Close()
//   fmt.Printf("%s connected 打开了!!!\n", address)
//  }
// }

优化之后

package main

import (
 "fmt"
 "net"
 "sort"
)

func worker(ports chan int, results chan int) {
 for p := range ports {
  address := fmt.Sprintf("20.194.168.28:%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 openports []int
 var closeports []int

 for i := 0; i < cap(ports); i++ {
  go worker(ports, results)
 }
 go func() {
  for i := 1; i < 1024; i++ {

   ports <- i
  }
 }()

 for i := 1; i < 1024; i++ {
  port := <-results
  if port != 0 {
   openports = append(openports, port)
  } else {
   closeports = append(closeports, port)
  }
 }

 close(ports)
 close(results)

 sort.Ints(openports)
 sort.Ints(closeports)

 for _, port := range closeports {
  fmt.Printf("%d closed\n", port)
 }

 for _, port := range openports {
  fmt.Printf("%d opened\n", port)
 }
}

// func main() {
//  start := time.Now()
//  var wg sync.WaitGroup
//  for i := 21; i < 120; i++ {
//   wg.Add(1)
//   go func(j int) {
//    defer wg.Done()
//    address := fmt.Sprintf("20.194.168.28:%d", j)
//    conn, err := net.Dial("tcp", address)
//    if err != nil {
//     fmt.Printf("%s 关闭了\n", address)
//     return
//    }
//    conn.Close()
//    fmt.Printf("%s 打开了!!!\n", address)
//   }(i)
//  }
//  wg.Wait()
//  elapsed := time.Since(start) / 1e9
//  fmt.Printf("\n\n%d seconds", elapsed)
// }

// func main() {
//  for i := 21; i < 120; i++ {
//   address := fmt.Sprintf("20.194.168.28:%d", i)
//   conn, err := net.Dial("tcp", address)
//   if err != nil {
//    fmt.Printf("%s failed 关闭了\n", address)
//    continue
//   }
//   conn.Close()
//   fmt.Printf("%s connected 打开了!!!\n", address)
//  }
// }


Categories Go
Tags Go