为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕沐林林 2022-06-06 16:51:46
背景:我正在阅读 Black Hat Go,作者展示了一个使用 goroutines 1的简单端口扫描器:package mainimport (    "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)    }}然后他提到以下内容:同时扫描过多的主机或端口可能会导致网络或系统限制影响您的结果。为了测试它,我在端口 8000 和 8500 上启动了 2 个 php 服务器2并运行上面的代码来扫描我的本地端口。每次它给我的结果不一致。有时它会检测到两个打开的端口,有时它不会。问题:不一致的结果是否是由于 TCP 的某些限制?有没有办法计算可以并行扫描的最佳端口数,以使结果保持正确?编辑:我似乎错过了上面代码中的等待组。除此之外,是否还有其他任何东西(操作系统限制或协议限制)可以防止在大范围内进行并发端口扫描?
查看完整描述

1 回答

?
红糖糍粑

TA贡献1815条经验 获得超6个赞

一旦 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()

}



查看完整回答
反对 回复 2022-06-06
  • 1 回答
  • 0 关注
  • 215 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号