开发者

基于Go语言实现一个并发端口扫描器

目录
  • 一、实战背景
  • 二、实战目标
  • 三、完整代码实现
    • 1. 扫描器实现(scanner.go)
  • 四、运行方式
    • 执行端口扫描器
      • 输入示例:
      • 输出示例:
  • 五、关键技术点解析
    • 1. 使用 Goroutine 并发扫描端口
      • 2. 使用 sync.WaitGroup 等待所有 Goroutine 完成
        • 3. 使用 net.DialTimeout 设置连接超时
          • 4. 使用 channxENHfXel 收集扫描结果
            • 5. 缓存扫描结果并打印
            • 六、优化和扩展方向
              • 七、小结

                一、实战背景

                端口扫描器是网络安全领域常用的工具,它通过对目标主机的端口进行扫描,检测目标设备是否开放某些服务端口(如 HTTP、FTP、SSH 等)。常见的端口扫描场景包括:

                • 安全审计:检测主机是否存在未授权服务
                • 漏洞扫描:识别可能存在漏洞的服务端口
                • 网络诊断:排查服务器是否正常工作

                传统的端口扫描使用串行方式,一个端口一个端口地检查,速度非常慢。而 Go 的并发编程可以极大地提升扫描效率。

                二、实战目标

                我们将实现一个并发端口扫描器,具备以下功能:

                1. 输入目标主机 IP 和端口范围
                2. 使用并发扫描多个端口
                3. 输出每个端口的开放状态
                4. 使用超时机制控制扫描时间,避免阻塞

                三、完整代码实现

                1. 扫描器实现(scanner.go)

                package main
                
                import (
                    "fmt"
                    "net"
                    "strconv"
                    "sync"
                    "time"
                )
                
                func scanPort(ip string, port int, wg *sync.WaitGroup, resultCh chan<- string) {
                    defer wg.Done()
                
                    address := fmt.Sprintf("%s:%d", ip, port)
                    conn, err := net.DialTimeout("tcp", address, 1*time.Second) // 设置连接超时时间
                    if err != nil {
                        resultCh <- fmt.Sprintf("端口 %d: 关闭", port)
                       编程客栈 return
                    }
                    conn.Close()
                    resultCh <- fmt.Sprintf("端口 %d: 开放", port)
                }
                
                func main() {
                    var wg sync.WaitGroup
                    resultCh := make(chan string, 100) // 创建带缓冲的 Channel,缓冲区大小为 100
                
                    fmt.Print("请输入目标 IP 地址: ")
                    var ip string
                    fmt.Scanln(&ip)
                
                    fmt.Print("请输入端口范围(例如:80 100): ")
                    var startPort, endPort int
                    fmt.Scanln(&startPort, &endPort)
                
                    // 扫描指定范围的端口
                    for port := startPort; port <= endPort; port++ {
                        wg.Add(1编程客栈)
                        go scanPort(ip, port, &wg, resultCh)
                    }
                
                    // 等待所有扫描任务完成并关闭 Channel
                    go func() {
                        wg.Wait()
                        close(resultCh)
                    }()
                
                    // 打印扫描结果
                    fmt.Println("\n扫描结果:")
                    for result := range resultCh {
                        fmt.Println(result)
                    }
                }
                

                四、运行方式

                执行端口扫描器

                go run scanner.go
                

                输入示例:

                请输入目标 IP 地址: 192.168.1.1
                请输入端口范围(例如:80 100): 80 90
                

                输出示例:

                扫描结果:
                端口 80: 开放
                端口 81: 关闭
                端口 82: 关闭
                端口 83: 关闭
                端口 84: 开放
                端口 85: 关闭
                端口 86: 开放
                端口 87: 关闭
                端口 88: 关闭
                端口 89: 开放
                端口 90: 关闭
                

                五、关键技术点解析

                1. 使用 Go编程客栈routine 并发扫描端口

                每个端口的扫描任务都是由独立的 Goroutine 执行的。这样可以最大化利用 CPU 核心,实现端口扫描的并发化。

                go scanPort(ip, port, &wg, resultCh)
                

                2. 使用 sync.WaitGroup 等待所有 Goroutine 完成

                WaitGroup 用来等待所有扫描任务完成,确保在关闭结果通道之前所有扫描任务已经结束。

                var wg sync.WaitGroup
                wg.Add(1)
                

                3. 使用 net.DialTimeout 设置连接超时

                DialTimeout 可以在指定的超时时间内完成连接,如果超时则返回错误。我们在这python里设置了 1 秒的超时。

                conn, err := net.DialTimeout("tcp", address, 1*time.Second)
                

                4. 使用 channel 收集扫描结果

                通过 Channel 传递每个端口的扫描结果,避免了主线程和 Goroutine 之间的数据竞争问题。

                resultCh <- fmt.Sprintf("端口 %d: 开放", port)
                

                5. 缓存扫描结果并打印

                使用带缓冲的 Channel resultCh 存储扫描结果。所有任务完成后,我们关闭通道并打印扫描结果。

                go func() {
                    wg.Wait()
                    close(resultCh)
                }()
                

                六、优化和扩展方向

                优化方向说明
                控制并发数量使用令牌桶算法(Token Bucket)或 sem 控制并发扫描的 Goroutine 数量
                支持输入多个目标 IP扩展支持一次扫描多个 IP 地址
                扫描端口的协议支持不仅支持 TCP 端口扫描,还可支持 UDP 扫描
                日志记录将扫描结果输出到日志文件,便于后期分析
                进度条显示添加扫描进度显示,提升用户体验
                智能端口扫描根据常见端口列表(如 80、443、21 等)进行扫描

                七、小结

                通过本篇案例,你学会了如何用 Go 实现一个并发端口扫描器,掌握了以下关键技术:

                • 使用 Goroutine 实现并发任务处理
                • 利用 sync.WaitGroup 等待所有并发任务完成
                • 使用 net.DialTimeout 进行超时控制,防止阻塞
                • 使用 Channel 收集并传递任务结果

                这个并发端口扫描器可以帮助你在网络安全和系统维护中快速诊断目标主机的开放端口。通过优化,您还可以将其扩展成更完整的网络扫描工具。

                以上就是基于Go语言实现一个并发端口扫描器的详细内容,更多关于Go并发端口扫描器的资料请关注编程客栈(www.devze.com)其它相关文章!

                0

                上一篇:

                下一篇:

                精彩评论

                暂无评论...
                验证码 换一张
                取 消

                最新开发

                开发排行榜