优化gost执行诊断时计入DNS解析时间的问题

This commit is contained in:
qaq
2025-11-21 16:27:58 +08:00
parent 4a23f3b45a
commit 31290137fe
2 changed files with 75 additions and 77 deletions
+1 -1
View File
@@ -119,7 +119,7 @@ func main() {
log := xlogger.NewLogger() log := xlogger.NewLogger()
logger.SetDefault(log) logger.SetDefault(log)
wsReporter := socket.StartWebSocketReporterWithConfig(config.Addr, config.Secret, config.Http, config.Tls, config.Socks, "2.0.1") wsReporter := socket.StartWebSocketReporterWithConfig(config.Addr, config.Secret, config.Http, config.Tls, config.Socks, "2.0.2")
defer wsReporter.Stop() defer wsReporter.Stop()
service.SetHTTPReportURL(config.Addr, config.Secret) service.SetHTTPReportURL(config.Addr, config.Secret)
+74 -76
View File
@@ -14,8 +14,8 @@ import (
"time" "time"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
"github.com/go-gost/x/service"
"github.com/go-gost/x/internal/util/crypto" "github.com/go-gost/x/internal/util/crypto"
"github.com/go-gost/x/service"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/shirou/gopsutil/v3/cpu" "github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/host" "github.com/shirou/gopsutil/v3/host"
@@ -87,9 +87,9 @@ type TcpPingResponse struct {
type WebSocketReporter struct { type WebSocketReporter struct {
url string url string
addr string // 保存服务器地址 addr string // 保存服务器地址
secret string // 保存密钥 secret string // 保存密钥
version string // 保存版本号 version string // 保存版本号
conn *websocket.Conn conn *websocket.Conn
reconnectTime time.Duration reconnectTime time.Duration
pingInterval time.Duration pingInterval time.Duration
@@ -206,14 +206,14 @@ func (w *WebSocketReporter) connect() error {
Tls int `json:"tls"` Tls int `json:"tls"`
Socks int `json:"socks"` Socks int `json:"socks"`
} }
var cfg LocalConfig var cfg LocalConfig
if b, err := os.ReadFile("config.json"); err == nil { if b, err := os.ReadFile("config.json"); err == nil {
json.Unmarshal(b, &cfg) json.Unmarshal(b, &cfg)
} }
// 使用最新的配置重新构建 URL // 使用最新的配置重新构建 URL
currentURL := "ws://" + w.addr + "/system-info?type=1&secret=" + w.secret + "&version=" + w.version + currentURL := "ws://" + w.addr + "/system-info?type=1&secret=" + w.secret + "&version=" + w.version +
"&http=" + strconv.Itoa(cfg.Http) + "&tls=" + strconv.Itoa(cfg.Tls) + "&socks=" + strconv.Itoa(cfg.Socks) "&http=" + strconv.Itoa(cfg.Http) + "&tls=" + strconv.Itoa(cfg.Tls) + "&socks=" + strconv.Itoa(cfg.Socks)
u, err := url.Parse(currentURL) u, err := url.Parse(currentURL)
@@ -796,81 +796,81 @@ func (w *WebSocketReporter) handleDeleteLimiter(data interface{}) error {
// handleSetProtocol 处理设置屏蔽协议的命令 // handleSetProtocol 处理设置屏蔽协议的命令
func (w *WebSocketReporter) handleSetProtocol(data interface{}) error { func (w *WebSocketReporter) handleSetProtocol(data interface{}) error {
jsonData, err := json.Marshal(data) jsonData, err := json.Marshal(data)
if err != nil { if err != nil {
return fmt.Errorf("序列化协议设置失败: %v", err) return fmt.Errorf("序列化协议设置失败: %v", err)
} }
// 支持 {"http":0/1, "tls":0/1, "socks":0/1} // 支持 {"http":0/1, "tls":0/1, "socks":0/1}
var req struct { var req struct {
HTTP *int `json:"http"` HTTP *int `json:"http"`
TLS *int `json:"tls"` TLS *int `json:"tls"`
SOCKS *int `json:"socks"` SOCKS *int `json:"socks"`
} }
if err := json.Unmarshal(jsonData, &req); err != nil { if err := json.Unmarshal(jsonData, &req); err != nil {
return fmt.Errorf("解析协议设置失败: %v", err) return fmt.Errorf("解析协议设置失败: %v", err)
} }
// 读取当前值作为默认 // 读取当前值作为默认
httpVal, tlsVal, socksVal := 0, 0, 0 httpVal, tlsVal, socksVal := 0, 0, 0
if req.HTTP != nil { if req.HTTP != nil {
if *req.HTTP != 0 && *req.HTTP != 1 { if *req.HTTP != 0 && *req.HTTP != 1 {
return fmt.Errorf("http 取值必须为0或1") return fmt.Errorf("http 取值必须为0或1")
} }
httpVal = *req.HTTP httpVal = *req.HTTP
} }
if req.TLS != nil { if req.TLS != nil {
if *req.TLS != 0 && *req.TLS != 1 { if *req.TLS != 0 && *req.TLS != 1 {
return fmt.Errorf("tls 取值必须为0或1") return fmt.Errorf("tls 取值必须为0或1")
} }
tlsVal = *req.TLS tlsVal = *req.TLS
} }
if req.SOCKS != nil { if req.SOCKS != nil {
if *req.SOCKS != 0 && *req.SOCKS != 1 { if *req.SOCKS != 0 && *req.SOCKS != 1 {
return fmt.Errorf("socks 取值必须为0或1") return fmt.Errorf("socks 取值必须为0或1")
} }
socksVal = *req.SOCKS socksVal = *req.SOCKS
} }
// 设置至 service,全量传递(未提供的值沿用0) // 设置至 service,全量传递(未提供的值沿用0)
service.SetProtocolBlock(httpVal, tlsVal, socksVal) service.SetProtocolBlock(httpVal, tlsVal, socksVal)
// 同步写入本地 config.json // 同步写入本地 config.json
if err := updateLocalConfigJSON(httpVal, tlsVal, socksVal); err != nil { if err := updateLocalConfigJSON(httpVal, tlsVal, socksVal); err != nil {
return fmt.Errorf("写入config.json失败: %v", err) return fmt.Errorf("写入config.json失败: %v", err)
} }
return nil return nil
} }
// updateLocalConfigJSON 将 http/tls/socks 写入工作目录下的 config.json // updateLocalConfigJSON 将 http/tls/socks 写入工作目录下的 config.json
func updateLocalConfigJSON(httpVal int, tlsVal int, socksVal int) error { func updateLocalConfigJSON(httpVal int, tlsVal int, socksVal int) error {
path := "config.json" path := "config.json"
// 读取现有配置 // 读取现有配置
type LocalConfig struct { type LocalConfig struct {
Addr string `json:"addr"` Addr string `json:"addr"`
Secret string `json:"secret"` Secret string `json:"secret"`
Http int `json:"http"` Http int `json:"http"`
Tls int `json:"tls"` Tls int `json:"tls"`
Socks int `json:"socks"` Socks int `json:"socks"`
} }
var cfg LocalConfig var cfg LocalConfig
if b, err := os.ReadFile(path); err == nil { if b, err := os.ReadFile(path); err == nil {
_ = json.Unmarshal(b, &cfg) _ = json.Unmarshal(b, &cfg)
} }
cfg.Http = httpVal cfg.Http = httpVal
cfg.Tls = tlsVal cfg.Tls = tlsVal
cfg.Socks = socksVal cfg.Socks = socksVal
// 写回 // 写回
data, err := json.MarshalIndent(cfg, "", " ") data, err := json.MarshalIndent(cfg, "", " ")
if err != nil { if err != nil {
return err return err
} }
return os.WriteFile(path, data, 0644) return os.WriteFile(path, data, 0644)
} }
// handleCall 处理服务端的call回调消息 // handleCall 处理服务端的call回调消息
@@ -1133,26 +1133,24 @@ func tcpPingHost(ip string, port int, count int, timeoutMs int) (float64, float6
fmt.Printf("🔍 开始TCP ping测试: %s,次数: %d,超时: %dms\n", target, count, timeoutMs) fmt.Printf("🔍 开始TCP ping测试: %s,次数: %d,超时: %dms\n", target, count, timeoutMs)
// 如果是域名,先解析一次DNS,避免每次连接都重新解析导致延迟累加 // 如果是域名,先解析一次DNS,避免每次连接都重新解析导致延迟累加
var resolvedIPs []string
if net.ParseIP(ip) == nil { if net.ParseIP(ip) == nil {
// 是域名,需要解析 // 是域名,需要解析
fmt.Printf("🔍 检测到域名,正在解析DNS...\n") fmt.Printf("🔍 检测到域名,正在解析DNS...\n")
dnsStart := time.Now() dnsStart := time.Now()
addrs, err := net.LookupHost(ip) addrs, err := net.LookupHost(ip)
dnsDuration := time.Since(dnsStart) dnsDuration := time.Since(dnsStart)
if err != nil { if err != nil {
return 0, 100.0, fmt.Errorf("DNS解析失败: %v", err) return 0, 100.0, fmt.Errorf("DNS解析失败: %v", err)
} }
if len(addrs) == 0 { if len(addrs) == 0 {
return 0, 100.0, fmt.Errorf("DNS解析未返回任何IP地址") return 0, 100.0, fmt.Errorf("DNS解析未返回任何IP地址")
} }
resolvedIPs = addrs fmt.Printf("✅ DNS解析完成 (%.2fms),解析到 %d 个IP: %v\n",
fmt.Printf("✅ DNS解析完成 (%.2fms),解析到 %d 个IP: %v\n",
dnsDuration.Seconds()*1000, len(addrs), addrs) dnsDuration.Seconds()*1000, len(addrs), addrs)
// 使用第一个解析到的IP进行测试 // 使用第一个解析到的IP进行测试
target = net.JoinHostPort(addrs[0], fmt.Sprintf("%d", port)) target = net.JoinHostPort(addrs[0], fmt.Sprintf("%d", port))
fmt.Printf("🎯 使用IP地址进行测试: %s\n", target) fmt.Printf("🎯 使用IP地址进行测试: %s\n", target)