优化DoH请求处理,使用HTTP POST发送DNS消息并解析响应

This commit is contained in:
lirui
2026-01-04 22:37:17 +08:00
parent 27d53c8751
commit bd8d198fe5

View File

@@ -1,9 +1,11 @@
package dns package dns
import ( import (
"bytes"
"context" "context"
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"io"
"net/http" "net/http"
"sync" "sync"
"time" "time"
@@ -142,17 +144,46 @@ func (s *DNSServer) forwardDoH(req *dns.Msg) (*dns.Msg, error) {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel() defer cancel()
// 使用 DNS-over-HTTPS 客户端 // DNS 消息打包
client := &dns.Client{ packed, err := req.Pack()
Net: "https", if err != nil {
TLSConfig: &tls.Config{ return nil, err
InsecureSkipVerify: false,
},
Timeout: 3 * time.Second,
} }
resp, _, err := client.ExchangeContext(ctx, req, s.DoHURL) // 创建 HTTP POST 请求
return resp, err 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查询 // recordQuery 记录DNS查询