diff --git a/internal/dns/dns.go b/internal/dns/dns.go index 8b6c9b1..f13880e 100644 --- a/internal/dns/dns.go +++ b/internal/dns/dns.go @@ -1,9 +1,11 @@ package dns import ( + "bytes" "context" "crypto/tls" "fmt" + "io" "net/http" "sync" "time" @@ -142,17 +144,46 @@ func (s *DNSServer) forwardDoH(req *dns.Msg) (*dns.Msg, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() - // 使用 DNS-over-HTTPS 客户端 - client := &dns.Client{ - Net: "https", - TLSConfig: &tls.Config{ - InsecureSkipVerify: false, - }, - Timeout: 3 * time.Second, + // 将 DNS 消息打包 + packed, err := req.Pack() + if err != nil { + return nil, err } - resp, _, err := client.ExchangeContext(ctx, req, s.DoHURL) - return resp, err + // 创建 HTTP POST 请求 + httpReq, err := http.NewRequestWithContext(ctx, "POST", s.DoHURL, bytes.NewReader(packed)) + if err != nil { + return nil, err + } + + // 设置 DoH 请求头 + httpReq.Header.Set("Content-Type", "application/dns-message") + httpReq.Header.Set("Accept", "application/dns-message") + + // 发送请求 + resp, err := s.httpClient.Do(httpReq) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("DoH server returned status %d", resp.StatusCode) + } + + // 读取响应 + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + // 解析 DNS 响应 + dnsResp := new(dns.Msg) + if err := dnsResp.Unpack(body); err != nil { + return nil, err + } + + return dnsResp, nil } // recordQuery 记录DNS查询