## 问题分析

通过深入分析代码，我找到了导致所有查询都显示同一个 NXDOMAIN 错误的根本原因：

**核心问题**：`mergeResponses` 函数在合并多个 DNS 响应时，**没有正确处理 Rcode 字段**！

**具体原因**：
1. 当使用并行查询模式时，DNS 服务器会向多个上游服务器发送请求
2. 函数使用第一个响应作为基础来合并其他响应
3. 它清空了 `Answer`、`Ns` 和 `Extra` 字段，但**保留了第一个响应的 Rcode**
4. 如果第一个响应返回 NXDOMAIN（比如对于恶意域名 www.evilsnssdk.com），那么**合并后的响应也会保持 NXDOMAIN 状态**，即使其他响应返回成功
5. 这导致所有查询都显示同一个 NXDOMAIN 错误

## 修复方案

### 修复 `mergeResponses` 函数

**关键修改点**：
1. **重置 Rcode**：在合并响应前，将 Rcode 重置为成功状态
2. **处理 NXDOMAIN**：只有当所有响应都是 NXDOMAIN 时，才返回 NXDOMAIN
3. **优先使用成功响应**：如果有任何响应返回成功，就使用成功的 Rcode

### 修复步骤

1. **修改 `mergeResponses` 函数** (`/root/dns/dns/server.go:842-933`)
   - 在合并记录前，将 `mergedResponse.Rcode` 设置为 `dns.RcodeSuccess`
   - 添加变量 `allNXDOMAIN` 来跟踪是否所有响应都是 NXDOMAIN
   - 遍历所有响应，检查是否有成功响应
   - 如果所有响应都是 NXDOMAIN，才将 `mergedResponse.Rcode` 设置为 `dns.RcodeNameError`

2. **优化合并逻辑**
   - 确保优先使用成功响应中的记录
   - 避免将 NXDOMAIN 响应的记录合并到成功响应中
   - 保持响应的一致性，Rcode 与记录内容匹配

## 修复代码

```go
// mergeResponses 合并多个DNS响应
func mergeResponses(responses []*dns.Msg) *dns.Msg {
    if len(responses) == 0 {
        return nil
    }

    // 如果只有一个响应，直接返回，避免不必要的合并操作
    if len(responses) == 1 {
        return responses[0].Copy()
    }

    // 使用第一个响应作为基础
    mergedResponse := responses[0].Copy()
    mergedResponse.Answer = []dns.RR{}
    mergedResponse.Ns = []dns.RR{}
    mergedResponse.Extra = []dns.RR{}
    
    // 重置Rcode为成功，除非所有响应都是NXDOMAIN
    mergedResponse.Rcode = dns.RcodeSuccess
    
    // 检查是否所有响应都是NXDOMAIN
    allNXDOMAIN := true
    
    // 收集所有成功响应的记录
    for _, resp := range responses {
        if resp == nil {
            continue
        }
        
        // 如果有任何响应是成功的，就不是allNXDOMAIN
        if resp.Rcode == dns.RcodeSuccess {
            allNXDOMAIN = false
        }
    }
    
    // 如果所有响应都是NXDOMAIN，设置合并响应为NXDOMAIN
    if allNXDOMAIN {
        mergedResponse.Rcode = dns.RcodeNameError
    }

    // 使用map存储唯一记录，选择最长TTL
    // 预分配map容量，减少扩容开销
    answerMap := make(map[recordKey]dns.RR, len(responses[0].Answer)*len(responses))
    nsMap := make(map[recordKey]dns.RR, len(responses[0].Ns)*len(responses))
    extraMap := make(map[recordKey]dns.RR, len(responses[0].Extra)*len(responses))

    for _, resp := range responses {
        if resp == nil {
            continue
        }
        
        // 只合并与最终Rcode匹配的响应记录
        if (mergedResponse.Rcode == dns.RcodeSuccess && resp.Rcode == dns.RcodeSuccess) ||
           (mergedResponse.Rcode == dns.RcodeNameError && resp.Rcode == dns.RcodeNameError) {
            
            // 合并Answer部分
            for _, rr := range resp.Answer {
                key := getRecordKey(rr)
                if existing, exists := answerMap[key]; exists {
                    // 如果存在相同记录，选择TTL更长的
                    if rr.Header().Ttl > existing.Header().Ttl {
                        answerMap[key] = rr
                    }
                } else {
                    answerMap[key] = rr
                }
            }

            // 合并Ns部分
            for _, rr := range resp.Ns {
                key := getRecordKey(rr)
                if existing, exists := nsMap[key]; exists {
                    // 如果存在相同记录，选择TTL更长的
                    if rr.Header().Ttl > existing.Header().Ttl {
                        nsMap[key] = rr
                    }
                } else {
                    nsMap[key] = rr
                }
            }

            // 合并Extra部分
            for _, rr := range resp.Extra {
                // 跳过OPT记录，避免重复
                if rr.Header().Rrtype == dns.TypeOPT {
                    continue
                }
                key := getRecordKey(rr)
                if existing, exists := extraMap[key]; exists {
                    // 如果存在相同记录，选择TTL更长的
                    if rr.Header().Ttl > existing.Header().Ttl {
                        extraMap[key] = rr
                    }
                } else {
                    extraMap[key] = rr
                }
            }
        }
    }

    // 预分配切片容量，减少扩容开销
    mergedResponse.Answer = make([]dns.RR, 0, len(answerMap))
    mergedResponse.Ns = make([]dns.RR, 0, len(nsMap))
    mergedResponse.Extra = make([]dns.RR, 0, len(extraMap))

    // 将map转换回切片
    for _, rr := range answerMap {
        mergedResponse.Answer = append(mergedResponse.Answer, rr)
    }

    for _, rr := range nsMap {
        mergedResponse.Ns = append(mergedResponse.Ns, rr)
    }

    for _, rr := range extraMap {
        mergedResponse.Extra = append(mergedResponse.Extra, rr)
    }

    return mergedResponse
}```

## 预期效果

修复后，DNS服务器将能够：
- 正确合并多个 DNS 响应
- 确保 Rcode 与实际记录内容匹配
- 只有当所有响应都是 NXDOMAIN 时才返回 NXDOMAIN
- 避免单个恶意域名影响所有查询结果
- 正确显示各个域名的查询结果

## 修复代码位置

- **核心修改文件**：`/root/dns/dns/server.go`
- **关键函数**：`mergeResponses`
- **修改内容**：修复响应合并逻辑，正确处理 Rcode 字段

## 测试方法

1. 使用 nslookup 测试不同域名
2. 检查是否每个域名都显示正确的查询结果
3. 验证 www.evilsnssdk.com 返回 NXDOMAIN，而其他域名返回成功
4. 检查日志中是否还有大量错误信息

这个修复将彻底解决所有查询都显示同一个 NXDOMAIN 错误的问题！