gpt4 book ai didi

go - 同时扫描多个端口时结果不可靠

转载 作者:行者123 更新时间:2023-12-01 20:26:22 25 4
gpt4 key购买 nike

背景 :

我正在阅读 Black Hat Go,作者介绍了一个使用 go 例程的简单端口扫描器 1 :

package main

import (
"fmt"
"net"
)

func main() {
for i := 1; i <= 9000; i++ {
go func(j int) {
address := fmt.Sprintf("127.0.0.1:%d", j)
conn, err := net.Dial("tcp", address)
if err != nil {
return
}
conn.Close()
fmt.Printf("%d open\n", j)
}(i)
}
}

然后他提到以下内容:

Scanning an excessive number of hosts or ports simultaneously may cause network or system limitations to skew your results.



为了测试它,我启动了 2 个 php 服务器 2在端口 8000 和 8500 上运行上面的代码来扫描我的本地端口。

每次它给我的结果不一致。有时它会检测到两个打开的端口,有时它不会。

问题 :
  • 不一致的结果是否是由于 TCP 的某些限制?
  • 有没有办法计算可以并行扫描的最佳端口数,以使结果保持正确?

  • 编辑 :

    我似乎错过了上面代码中的 WaitGroup 。

    除此之外,是否还有其他任何东西(操作系统限制或协议(protocol)限制)可以防止在大范围内进行并发端口扫描?

    最佳答案

    一旦 for 循环完成,您的 main 函数将退出。如果 main 函数退出,所有由它启动的 goroutines 也会退出。您需要等待 goroutine 完成。这可以通过 sync.WaitGroup 来实现, 例如。

    package main

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

    func main() {

    // This will help you to keep track of the goroutines
    var wg sync.WaitGroup

    for i := 1; i <= 9000; i++ {

    // Increment the counter for each goroutine you start.
    wg.Add(1)

    go func(j int) {

    // Make sure the wait group counter is decremented when the goroutine exits
    defer wg.Done()

    address := fmt.Sprintf("127.0.0.1:%d", j)
    conn, err := net.DialTimeout("tcp", address, 2 * time.Second)
    if err != nil {
    return
    }
    conn.Close()
    fmt.Printf("%d open\n", j)
    }(i)
    }

    // Wait for all goroutines to finish before exiting main
    wg.Wait()
    }

    编辑:对我来说,事实证明,由于缺少文件描述符,代码原样不起作用。以下功能可靠地工作。

    它需要更好的错误处理,但确实有效

    package main

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

    var minPort = 1
    var maxPort = 65535
    var timeout = 2 * time.Second
    const parallel = 50

    func main(){
    fmt.Println("portscan called")

    // Create a buffered channel with a size equal to the number of goroutines
    ctrl := make(chan int, parallel)

    // Keep track of the currently active goroutines
    var wg sync.WaitGroup

    for p := 1; p <= parallel; p++ {
    wg.Add(1)

    // Start a goroutine...
    go func(p int) {
    log.Printf("Starting goroutine %d", p)

    // ...listening to the control channel.
    // For every value this goroutine reads from the
    // channel...
    for i := range ctrl {
    address := fmt.Sprintf("127.0.0.1:%d", i)

    // ...try to conncet to the port.
    conn, err := net.DialTimeout("tcp", address, timeout)
    if err == nil {
    conn.Close()
    log.Printf("[%3d]: %5d open", p, i)
    }
    // TBD: ERROR HANDLING!!!
    }

    // If the channel is closed, this goroutine is done.
    wg.Done()
    log.Printf("[%3d]: Exiting", p)
    }(p)
    }

    // Fill the control channel with values.
    // If the channel is full, the write operation
    // to the channel will block until one of the goroutines
    // reads a value from it.
    for i := minPort; i <= maxPort; i++ {
    ctrl <- i
    }
    // We have sent all values, so the channel can be closed.
    // The goroutines will finish their current connection attempt,
    // notice that the channel is closed and will in turn call wg.Done().
    close(ctrl)

    // When all goroutines have announced that they are done, we can exit.
    wg.Wait()
    }

    关于go - 同时扫描多个端口时结果不可靠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62113459/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com