GoLand编写 TCP 端口扫描器的详细过程

 更新时间:2023年05月09日 10:42:05   作者:QIAOPENGJUN  
TCP,也就是传输控制协议(Transmission Control Protocol),这篇文章主要介绍了Go语言(Golang)编写 TCP 端口扫描器,需要的朋友可以参考下

Go 语言编写 TCP 扫描器

TCP

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

TCP握手

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

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

  • syn (请求建立新连接)
  • syn-ack (同意创建新连接)
  • 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)
// 	}
// }

到此这篇关于Go语言(Golang)编写 TCP 端口扫描器的文章就介绍到这了,更多相关Go语言TCP 端口扫描器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • go benchmark 基准测试详解

    go benchmark 基准测试详解

    这篇文章主要介绍了go benchmark 基准测试详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • GPT回答 go语言和C语言数组操作对比

    GPT回答 go语言和C语言数组操作对比

    这篇文章主要为大家介绍了GPT回答的go语言和C语言数组操作方法对比,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • 使用Golang的Context管理上下文的方法

    使用Golang的Context管理上下文的方法

    这篇文章主要介绍了使用Golang的Context管理上下文的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • 一文详解go的defer和return的执行顺序

    一文详解go的defer和return的执行顺序

    go的defer和return是golang中的两个关键字,return用于返回函数的返回值,也可以参与一定的流程控制,defer是golang中的延迟调用,经常用于文件流的关闭,锁的解锁操作,本文给大家介绍了go的defer和return的执行顺序,需要的朋友可以参考下
    2024-07-07
  • Go Slice进行参数传递如何实现详解

    Go Slice进行参数传递如何实现详解

    这篇文章主要为大家介绍了Go Slice进行参数传递如何实现的过程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • 一文带你了解Golang中select的实现原理

    一文带你了解Golang中select的实现原理

    select是go提供的一种跟并发相关的语法,非常有用。本文将介绍 Go 语言中的 select 的实现原理,包括 select 的结构和常见问题、编译期间的多种优化以及运行时的执行过程
    2023-02-02
  • Go语言中获取IP地址的方法详解

    Go语言中获取IP地址的方法详解

    这篇文章主要为大家详细介绍了Go语言中获取IP地址的相关方法,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-11-11
  • Go 常量基础概念(声明更改只读)

    Go 常量基础概念(声明更改只读)

    这篇文章主要为大家介绍了Go常量基础概念包括常量的声明更改只读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • GO项目配置与使用的方法步骤

    GO项目配置与使用的方法步骤

    本文主要介绍了GO项目配置与使用的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧<BR>
    2022-06-06
  • 详解Golang中哪些类型可以作为map的key

    详解Golang中哪些类型可以作为map的key

    在 Go 语言中,map 是一种内置的关联数据结构类型,由一组无序的键值对组成,每个键都是唯一的,并与一个对应的值相关联,本文将详细介绍哪些类型的变量可以作为 map 的键,并通过实例进行说明,感兴趣的朋友可以参考下
    2024-01-01

最新评论