You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Go并发子域名爆破工具仅返回指定线程数结果的问题求助

解决Go子域名爆破工具结果数等于线程数的问题

嘿,我之前做并发工具时也踩过类似的坑,咱们一步步来排查和解决这个问题:

核心问题分析

从你给出的代码片段来看,有两个最可能的原因导致结果数和线程数一致:

  1. 通道接收的语法错误:你写的preparedSubdomain := <-words + "." + domain存在运算符优先级问题——Go里字符串拼接+的优先级高于通道接收<-,这行代码会被错误解析为<- (words + "." + domain),这显然是非法的(通道类型无法和字符串相加)。即便工具能运行,这种错误也可能导致线程接收一次数据后就异常退出。
  2. 线程提前终止:如果在解析子域名出错时直接return退出函数,而不是继续循环处理下一个子域名,那每个线程只处理一个任务就结束,最终结果数自然和线程数相等。

修正后的代码示例

咱们把代码调整为正确的并发处理逻辑:

import (
    "net"
    "sync"
)

type State struct {
    // 假设你的State包含结果通道、泛域名跳过配置等字段
    Results      chan string
    SkipWildcard bool
}

func CheckWildcardSubdomain(state *State, domain string, words <-chan string, wg *sync.WaitGroup) {
    defer wg.Done()
    // 用range遍历通道,直到通道关闭自动退出循环
    for word := range words {
        preparedSubdomain := word + "." + domain
        ipAddresses, err := net.LookupHost(preparedSubdomain)
        if err != nil {
            // 解析出错时跳过当前子域名,继续处理下一个,不要直接退出线程
            continue
        }
        // 可选:泛域名检测逻辑
        if state.SkipWildcard {
            if isWildcard(ipAddresses) {
                continue
            }
        }
        // 将有效子域名发送到结果通道
        state.Results <- preparedSubdomain
    }
}

// 示例泛域名检测函数(根据你的需求实现具体逻辑)
func isWildcard(ipAddresses []string) bool {
    // 比如判断是否返回了常见的泛域名IP池,或多个子域名IP重复等
    return false
}

关键修复点说明

  1. 正确遍历通道:用for word := range words替代无限循环手动接收,当words通道被关闭后,循环会自动退出,代码更简洁安全。
  2. 避免线程提前退出:解析出错时用continue跳过当前任务,而不是return终止线程,确保每个线程能处理完所有分配的子域名。
  3. 语法修正:先接收通道中的word变量,再和域名拼接,彻底解决运算符优先级导致的错误。

主线程配套逻辑

确保主线程正确发送任务、等待线程完成并收集结果:

func main() {
    targetDomain := "example.com"
    threadCount := 10
    wordList := []string{"www", "api", "admin", "test", "mail", ...} // 你的子域名词表

    // 初始化通道与WaitGroup
    wordsChan := make(chan string, threadCount) // 带缓冲的通道避免发送阻塞
    resultsChan := make(chan string, len(wordList))
    var wg sync.WaitGroup

    // 启动工作线程
    wg.Add(threadCount)
    for i := 0; i < threadCount; i++ {
        go CheckWildcardSubdomain(&State{Results: resultsChan, SkipWildcard: true}, targetDomain, wordsChan, &wg)
    }

    // 异步发送子域名词到通道
    go func() {
        for _, word := range wordList {
            wordsChan <- word
        }
        close(wordsChan) // 发送完成后关闭通道,通知线程结束任务
    }()

    // 等待所有线程完成后关闭结果通道
    go func() {
        wg.Wait()
        close(resultsChan)
    }()

    // 收集并输出结果
    for validSubdomain := range resultsChan {
        println(validSubdomain)
    }
}

额外注意事项

  • 通道缓冲:给任务通道设置和线程数匹配的缓冲,避免发送方阻塞;结果通道缓冲设为词表长度,防止接收方阻塞。
  • 错误日志:可以在解析出错时记录日志,方便排查哪些子域名解析失败,而不是直接跳过。
  • 泛域名优化:如果需要跳过泛域名,确保检测逻辑准确,避免误判丢失有效结果。

内容的提问来源于stack exchange,提问作者Ice3man

火山引擎 最新活动