Files
linkmaster-node/internal/handler/dns.go
2025-11-21 18:35:31 +08:00

144 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handler
import (
"encoding/base64"
"fmt"
"net"
"os/exec"
"strings"
"time"
"github.com/gin-gonic/gin"
)
func handleDns(c *gin.Context, url string, params map[string]interface{}) {
// 获取seq参数
seq := ""
if seqVal, ok := params["seq"].(string); ok {
seq = seqVal
}
// 获取dig类型参数
digType := ""
if dt, ok := params["dt"].(string); ok {
digType = dt
}
// 获取DNS服务器参数
dnsServer := ""
if ds, ok := params["ds"].(string); ok {
dnsServer = ds
}
// 解析URL提取hostname
hostname := url
if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") {
parts := strings.Split(url, "//")
if len(parts) > 1 {
hostParts := strings.Split(parts[1], "/")
hostname = hostParts[0]
if idx := strings.Index(hostname, ":"); idx != -1 {
hostname = hostname[:idx]
}
}
}
// 准备结果
result := map[string]interface{}{
"seq": seq,
"type": "ceDns",
"requrl": hostname,
"ips": []interface{}{},
}
// 构建dig命令
args := []string{hostname}
if digType != "" {
args = append([]string{"-t", digType}, args...)
}
if dnsServer != "" {
args = append([]string{"@" + dnsServer}, args...)
}
cmd := exec.Command("dig", args...)
output, err := cmd.CombinedOutput()
outputStr := string(output)
// 编码完整输出为base64header字段
result["header"] = base64.StdEncoding.EncodeToString([]byte(outputStr))
if err != nil {
result["error"] = err.Error()
c.JSON(200, result)
return
}
// 解析dig输出
lines := strings.Split(outputStr, "\n")
inAnswerSection := false
ipList := make([]map[string]interface{}, 0)
for _, line := range lines {
line = strings.TrimSpace(line)
if strings.Contains(line, "ANSWER SECTION") {
inAnswerSection = true
continue
}
if inAnswerSection {
if line == "" {
break
}
// 解析dig输出行格式如example.com. 300 IN A 192.168.1.1
parts := strings.Fields(line)
if len(parts) >= 5 {
// parts[3] 是 "IN" (record type)parts[4] 是记录类型 (A, AAAA, CNAME等)
recordClass := parts[4] // A, AAAA, CNAME等
recordValue := ""
if len(parts) > 5 {
recordValue = strings.Join(parts[5:], " ")
}
// 只处理A和AAAA记录
if recordClass == "A" || recordClass == "AAAA" {
ipItem := map[string]interface{}{
"url": parts[0],
"type": recordClass,
"ip": recordValue,
}
ipList = append(ipList, ipItem)
}
}
}
}
// 如果没有从dig输出解析到IP尝试使用net.LookupIP
if len(ipList) == 0 {
start := time.Now()
ips, err := net.LookupIP(hostname)
lookupTime := time.Since(start)
if err == nil {
for _, ip := range ips {
ipType := "A"
if ip.To4() == nil {
ipType = "AAAA"
}
ipItem := map[string]interface{}{
"url": hostname,
"type": ipType,
"ip": ip.String(),
}
ipList = append(ipList, ipItem)
}
// 更新header包含lookup时间信息
lookupInfo := fmt.Sprintf("Lookup time: %v\n", lookupTime)
result["header"] = base64.StdEncoding.EncodeToString([]byte(outputStr + lookupInfo))
} else {
result["error"] = err.Error()
}
}
result["ips"] = ipList
c.JSON(200, result)
}