go 实现端口扫描器 | go 技术论坛-江南app体育官方入口

利用 go 批量扫描服务器端口

1、端口扫描器 v1 - 基本操作

package main
import (
    "fmt"
    "net"
    "time"
    "unsafe"
)
func main() {
    tcpscan("127.0.0.1", 1, 65535)
}
func tcpscan(ip string, portstart int, portend int) {
    start := time.now()
    // 参数校验
    isok := verifyparam(ip, portstart, portend)
    if isok == false {
        fmt.printf("[exit]\n")
    }
    for i := portstart; i <= portend; i {
        address := fmt.sprintf("%s:%d", ip, i)
        conn, err := net.dial("tcp", address)
        if err != nil {
            fmt.printf("[info] %s close \n", address)
            continue
        }
        conn.close()
        fmt.printf("[info] %s open \n", address)
    }
    cost := time.since(start)
    fmt.printf("[tcpscan] cost %s second \n", cost)
}
func verifyparam(ip string, portstart int, portend int) bool {
    netip := net.parseip(ip)
    if netip == nil {
        fmt.println("[error] ip type is must net.ip")
        return false
    }
    fmt.printf("[info] ip=%s | ip type is: %t | ip size is: %d \n", netip, netip, unsafe.sizeof(netip))
    if portstart < 1 || portend > 65535 {
        fmt.println("[error] port is must in the range of 1~65535")
        return false
    }
    fmt.printf("[info] port start:%d end:%d \n", portstart, portend)
    return true
}

2、端口扫描器 v2 - 使用 goroutine

package main
import (
    "fmt"
    "net"
    "sync"
    "time"
    "unsafe"
)
func main() {
    tcpscanbygoroutine("127.0.0.1", 1, 65535)
}
func tcpscanbygoroutine(ip string, portstart int, portend int) {
    start := time.now()
    // 参数校验
    isok := verifyparam(ip, portstart, portend)
    if isok == false {
        fmt.printf("[exit]\n")
    }
    var wg sync.waitgroup
    for i := portstart; i <= portend; i {
        wg.add(1)
        go func(j int) {
            defer wg.done()
            address := fmt.sprintf("%s:%d", ip, j)
            conn, err := net.dial("tcp", address)
            if err != nil {
                fmt.printf("[info] %s close \n", address)
                return
            }
            conn.close()
            fmt.printf("[info] %s open \n", address)
        }(i)
    }
    wg.wait()
    cost := time.since(start)
    fmt.printf("[tcpscanbygoroutine] cost %s second \n", cost)
}
func verifyparam(ip string, portstart int, portend int) bool {
    netip := net.parseip(ip)
    if netip == nil {
        fmt.println("[error] ip type is must net.ip")
        return false
    }
    fmt.printf("[info] ip=%s | ip type is: %t | ip size is: %d \n", netip, netip, unsafe.sizeof(netip))
    if portstart < 1 || portend > 65535 {
        fmt.println("[error] port is must in the range of 1~65535")
        return false
    }
    fmt.printf("[info] port start:%d end:%d \n", portstart, portend)
    return true
}

3、端口扫描器 v3 - 利用 goroutine channel

package main
import (
    "fmt"
    "net"
    "sync"
    "time"
    "unsafe"
)
func main() {
    tcpscanbygoroutinewithchannel("127.0.0.1", 1, 65535)
}
func handleworker(ip string, ports chan int, wg *sync.waitgroup) {
    for p := range ports {
        address := fmt.sprintf("%s:%d", ip, p)
        conn, err := net.dial("tcp", address)
        if err != nil {
            fmt.printf("[info] %s close \n", address)
            wg.done()
            continue
        }
        conn.close()
        fmt.printf("[info] %s open \n", address)
        wg.done()
    }
}
func tcpscanbygoroutinewithchannel(ip string, portstart int, portend int) {
    start := time.now()
    // 参数校验
    isok := verifyparam(ip, portstart, portend)
    if isok == false {
        fmt.printf("[exit]\n")
    }
    ports := make(chan int, 100)
    var wg sync.waitgroup
    for i := 0; i < cap(ports); i {
        go handleworker(ip, ports, &wg)
    }
    for i := portstart; i <= portend; i {
        wg.add(1)
        ports <- i
    }
    wg.wait()
    close(ports)
    cost := time.since(start)
    fmt.printf("[tcpscanbygoroutinewithchannel] cost %s second \n", cost)
}
func verifyparam(ip string, portstart int, portend int) bool {
    netip := net.parseip(ip)
    if netip == nil {
        fmt.println("[error] ip type is must net.ip")
        return false
    }
    fmt.printf("[info] ip=%s | ip type is: %t | ip size is: %d \n", netip, netip, unsafe.sizeof(netip))
    if portstart < 1 || portend > 65535 {
        fmt.println("[error] port is must in the range of 1~65535")
        return false
    }
    fmt.printf("[info] port start:%d end:%d \n", portstart, portend)
    return true
}

4 端口扫描器 v4 - 引入两个 channel

// package
package main
import (
    "fmt"
    "net"
    "sort"
    "time"
    "unsafe"
)
func main() {
    tcpscanbygoroutinewithchannelandsort("127.0.0.1", 1, 65535)
}
// the function handles checking if ports are open or closed for a given ip address.
func handleworker(ip string, ports chan int, results chan int) {
    for p := range ports {
        address := fmt.sprintf("%s:%d", ip, p)
        conn, err := net.dial("tcp", address)
        if err != nil {
            // fmt.printf("[debug] ip %s close \n", address)
            results <- (-p)
            continue
        }
        // fmt.printf("[debug] ip %s open \n", address)
        conn.close()
        results <- p
    }
}
func tcpscanbygoroutinewithchannelandsort(ip string, portstart int, portend int) {
    start := time.now()
    // 参数校验
    isok := verifyparam(ip, portstart, portend)
    if isok == false {
        fmt.printf("[exit]\n")
    }
    ports := make(chan int, 50)
    results := make(chan int)
    var openslice []int
    var closeslice []int
    // 任务生产者-分发任务 (新起一个 goroutinue ,进行分发数据)
    go func(a int, b int) {
        for i := a; i <= b; i {
            ports <- i
        }
    }(portstart, portend)
    // 任务消费者-处理任务  (每一个端口号都分配一个 goroutinue ,进行扫描)
    // 结果生产者-每次得到结果 再写入 结果 chan 中
    for i := 0; i < cap(ports); i {
        go handleworker(ip, ports, results)
    }
    // 结果消费者-等待收集结果 (main中的 goroutinue 不断从 chan 中阻塞式读取数据)
    for i := portstart; i <= portend; i {
        resport := <-results
        if resport > 0 {
            openslice = append(openslice, resport)
        } else {
            closeslice = append(closeslice, -resport)
        }
    }
    // 关闭 chan
    close(ports)
    close(results)
    // 排序
    sort.ints(openslice)
    sort.ints(closeslice)
    // 输出
    for _, p := range openslice {
        fmt.printf("[info] %s:%-8d open\n", ip, p)
    }
    // for _, p := range closeslice {
    //     fmt.printf("[info] %s:%-8d close\n", ip, p)
    // }
    cost := time.since(start)
    fmt.printf("[tcpscanbygoroutinewithchannelandsort] cost %s second \n", cost)
}
func verifyparam(ip string, portstart int, portend int) bool {
    netip := net.parseip(ip)
    if netip == nil {
        fmt.println("[error] ip type is must net.ip")
        return false
    }
    fmt.printf("[info] ip=%s | ip type is: %t | ip size is: %d \n", netip, netip, unsafe.sizeof(netip))
    if portstart < 1 || portend > 65535 {
        fmt.println("[error] port is must in the range of 1~65535")
        return false
    }
    fmt.printf("[info] port start:%d end:%d \n", portstart, portend)
    return true
}
go
本作品采用《cc 协议》,转载必须注明作者和本文链接
明天我们吃什么 悲哀藏在现实中 tacks
本帖由系统于 1年前 自动加精
讨论数量: 5

循序渐进 这个好

1年前

好文收藏

1年前

写的真不错

1年前

好,写的真好

1年前

好活当赏

1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
网站地图