Go实现TCP端口扫描器

2023-08-26 19:20:48 浏览数 (1)

TCP连接函数

定义一个connect函数进行TCP连接,接收三个参数:

  • ports chan int:端口管道,用于接收要扫描的端口
  • results chan int:结果管道,用于发送结果
  • host string:主机,用于拼接地址

从端口管道中读取端口后与主机拼接成完整地址,使用net.Dial测试TCP连接是否成功,并将结果发送到results管道,失败则返回0,成功则返回端口。

代码语言:javascript复制
func connect(ports chan int, results chan int, host string) {
    //  从管道接收要扫描的端口
    for p := range ports {
                    //  拼接地址
        address := fmt.Sprintf("%s:%d", host, p)
                    //  TCP连接
        conn, err := net.Dial("tcp", address)
        if err != nil {
            results <- 0
            continue
        }
                    //  关闭连接
        conn.Close()
            //  将结果发送到管道
        results <- p
    }
}

封装函数

定义一个run函数,接收四个参数:

  • start int:起始端口
  • end int:结束端口
  • rlen int:goroutine池缓存大小
  • host string:主机

该函数用于创建管道和goroutine池,并向管道发送要扫描的端口范围,最后从管道中接收结果,经过排序后返回一个切片。

代码语言:javascript复制
func run(start int, end int, rlen int, host string) []int {
    //  创建管道
    ports := make(chan int, rlen)
    results := make(chan int)
    //  切片,用于保存扫描的结果
    var openports []int
    //  goroutine池,并发执行TCP连接函数
    for i := 0; i < cap(ports); i   {
        go connect(ports, results, host)
    }
    //  向管道发送要扫描的端口
    go func() {
        for i := start; i <= end; i   {
            ports <- i
        }
    }()
    //  从管道接收结果
    for i := start; i <= end; i   {
        port := <-results
        if port != 0 {
            openports = append(openports, port)
        }
    }
    //  关闭管道
    close(ports)
    close(results)
    //  排序
    sort.Ints(openports)
    //  返回数据
    return openports
}

主函数

调用封装函数,向封装函数传递参数,并输出结果 func main() {

代码语言:javascript复制
    //  参数
    host := "127.0.0.1"
    start := 0
    end := 66535
    rlen := 4096
    //  调用封装函数,接收返回值
    res := run(start, end, rlen, host)
    //  输出结果
    for _, port := range res {
        fmt.Printf("%d is openn", port)
    }
}

完整代码

scan.go

代码语言:javascript复制
package main

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

func connect(ports chan int, results chan int, host string) {
    //  从管道接收要扫描的端口
    for p := range ports {
        //  拼接地址
        address := fmt.Sprintf("%s:%d", host, p)
        //  TCP连接
        conn, err := net.Dial("tcp", address)
        if err != nil {
            results <- 0
            continue
        }
        //  关闭连接
        conn.Close()
        //  将结果发送到管道
        results <- p
    }
}

func run(start int, end int, rlen int, host string) []int {
    //  创建管道
    ports := make(chan int, rlen)
    results := make(chan int)
    //  切片,用于保存扫描的结果
    var openports []int
    //  goroutine池,并发执行TCP连接函数
    for i := 0; i < cap(ports); i   {
        go connect(ports, results, host)
    }
    //  向管道发送要扫描的端口
    go func() {
        for i := start; i <= end; i   {
            ports <- i
        }
    }()
    //  从管道接收结果
    for i := start; i <= end; i   {
        port := <-results
        if port != 0 {
            openports = append(openports, port)
        }
    }
    //  关闭管道
    close(ports)
    close(results)
    //  排序
    sort.Ints(openports)
    //  返回数据
    return openports
}

func main() {
    //  参数
    host := "127.0.0.1"
    start := 0
    end := 66535
    rlen := 4096
    //  调用封装函数,接收返回值
    res := run(start, end, rlen, host)
    //  输出结果
    for _, port := range res {
        fmt.Printf("%d is openn", port)
    }
}

0 人点赞