mirror of
https://github.com/fankes/komari-agent.git
synced 2025-10-18 18:49:23 +08:00
feat: 添加自定义 DNS 解析器
This commit is contained in:
132
dnsresolver/resolver.go
Normal file
132
dnsresolver/resolver.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package dnsresolver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// DNS服务器列表,按优先级排序
|
||||
DNSServers = []string{
|
||||
"114.114.114.114:53", // 114DNS,中国大陆
|
||||
"8.8.8.8:53", // Google DNS,全球
|
||||
"8.8.4.4:53", // Google DNS备用,全球
|
||||
"1.1.1.1:53", // Cloudflare DNS,全球
|
||||
"223.5.5.5:53", // 阿里DNS,中国大陆
|
||||
"119.29.29.29:53", // DNSPod,中国大陆
|
||||
}
|
||||
|
||||
// CustomDNSServer 自定义DNS服务器,可以通过命令行参数设置
|
||||
CustomDNSServer string
|
||||
)
|
||||
|
||||
// SetCustomDNSServer 设置自定义DNS服务器
|
||||
func SetCustomDNSServer(dnsServer string) {
|
||||
if dnsServer != "" {
|
||||
// 检查是否已包含端口,如果没有则添加默认端口53
|
||||
if !strings.Contains(dnsServer, ":") {
|
||||
dnsServer = dnsServer + ":53"
|
||||
}
|
||||
CustomDNSServer = dnsServer
|
||||
}
|
||||
}
|
||||
|
||||
// getCurrentDNSServer 获取当前要使用的DNS服务器
|
||||
func getCurrentDNSServer() string {
|
||||
if CustomDNSServer != "" {
|
||||
return CustomDNSServer
|
||||
}
|
||||
// 如果没有设置自定义DNS,返回默认的第一个
|
||||
return DNSServers[0]
|
||||
}
|
||||
|
||||
// GetCustomResolver 返回一个使用指定DNS服务器的解析器
|
||||
func GetCustomResolver() *net.Resolver {
|
||||
return &net.Resolver{
|
||||
PreferGo: true,
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
d := net.Dialer{
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
// 尝试自定义DNS或默认DNS
|
||||
dnsServer := getCurrentDNSServer()
|
||||
conn, err := d.DialContext(ctx, "udp", dnsServer)
|
||||
if err == nil {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// 如果连接失败,尝试其他DNS服务器
|
||||
for _, server := range DNSServers {
|
||||
if server != dnsServer { // 避免重复尝试
|
||||
conn, err := d.DialContext(ctx, "udp", server)
|
||||
if err == nil {
|
||||
return conn, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 所有DNS服务器都失败,返回最后一次的错误
|
||||
return nil, err
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GetHTTPClient 返回一个使用自定义DNS解析器的HTTP客户端
|
||||
func GetHTTPClient(timeout time.Duration) *http.Client {
|
||||
if timeout <= 0 {
|
||||
timeout = 30 * time.Second
|
||||
}
|
||||
|
||||
customResolver := GetCustomResolver()
|
||||
|
||||
return &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
host, port, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ips, err := customResolver.LookupHost(ctx, host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, ip := range ips {
|
||||
dialer := &net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
DualStack: true,
|
||||
}
|
||||
conn, err := dialer.DialContext(ctx, network, net.JoinHostPort(ip, port))
|
||||
if err == nil {
|
||||
return conn, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("failed to dial to any of the resolved IPs")
|
||||
},
|
||||
MaxIdleConns: 10,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
},
|
||||
Timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// GetNetDialer 返回一个使用自定义DNS解析器的网络拨号器
|
||||
func GetNetDialer(timeout time.Duration) *net.Dialer {
|
||||
if timeout <= 0 {
|
||||
timeout = 5 * time.Second
|
||||
}
|
||||
|
||||
return &net.Dialer{
|
||||
Timeout: timeout,
|
||||
KeepAlive: 30 * time.Second,
|
||||
Resolver: GetCustomResolver(),
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user