From 1ff44d1ebc48888cd3cb2b9369fe9f25eeaa968d Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Tue, 2 Sep 2025 06:40:14 +0000 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96Web=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E6=A3=80=E6=B5=8B=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=85=88=E4=BD=BF=E7=94=A8=E6=8C=87=E7=BA=B9=E8=AF=86=E5=88=AB?= =?UTF-8?q?=E7=BB=93=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 功能优化: - IsWebService现在优先检查服务指纹识别的结果 - 避免对已识别为Web服务的端口进行重复HTTP探测 - 改进调试日志,区分不同检测路径 Web服务识别逻辑: 1. 优先级1: 检查指纹识别缓存 2. 优先级2: 常见Web端口快速路径 3. 优先级3: 检测缓存 4. 优先级4: HTTP协议探测(回退机制) 新增函数: - IsWebServiceByFingerprint: 基于nmap指纹智能判断Web服务 - MarkAsWebService: 缓存已识别的Web服务 - GetWebServiceInfo: 获取Web服务信息 - IsMarkedWebService: 检查端口是否已标记为Web服务 效果: - 减少重复HTTP探测请求 - 提高Web服务识别准确性 - 统一服务识别和Web检测架构 --- core/WebDetection.go | 117 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 4 deletions(-) diff --git a/core/WebDetection.go b/core/WebDetection.go index 871c35a..a703ac7 100644 --- a/core/WebDetection.go +++ b/core/WebDetection.go @@ -102,8 +102,15 @@ func newWebPortDetector() *WebPortDetector { } } -// IsWebService 智能检测端口是否运行Web服务 +// IsWebService 智能检测端口是否运行Web服务(优化版:优先使用指纹识别结果) func (w *WebPortDetector) IsWebService(host string, port int) bool { + // 0. 最优先路径:检查是否已通过服务指纹识别为Web服务 + if IsMarkedWebService(host, port) { + serviceInfo, _ := GetWebServiceInfo(host, port) + common.LogDebug(fmt.Sprintf("端口 %d 通过服务指纹已识别为Web服务: %s", port, serviceInfo.Name)) + return true + } + // 1. 快速路径:常见Web端口直接返回true if w.IsCommonWebPort(port) { common.LogDebug(fmt.Sprintf("端口 %d 是常见Web端口,启用Web插件", port)) @@ -120,8 +127,8 @@ func (w *WebPortDetector) IsWebService(host string, port int) bool { } w.cacheMutex.RUnlock() - // 3. 智能路径:对非常见端口进行HTTP协议探测 - common.LogDebug(fmt.Sprintf("对端口 %d 进行智能Web检测", port)) + // 3. 回退路径:对非常见端口进行HTTP协议探测(仅在服务指纹识别失败时使用) + common.LogDebug(fmt.Sprintf("端口 %d 未通过服务指纹识别为Web服务,回退到HTTP协议探测", port)) result := w.detectHTTPService(host, port) // 4. 缓存结果 @@ -129,7 +136,7 @@ func (w *WebPortDetector) IsWebService(host string, port int) bool { w.detectionCache[cacheKey] = result w.cacheMutex.Unlock() - common.LogDebug(fmt.Sprintf("端口 %d 智能检测结果: %v", port, result)) + common.LogDebug(fmt.Sprintf("端口 %d HTTP协议探测结果: %v", port, result)) return result } @@ -420,4 +427,106 @@ func min(a, b int) int { return b } +// =============================== +// 统一服务识别架构 - 基于指纹的Web服务判断 +// =============================== + +// WebServiceCache Web服务缓存,用于存储已识别的Web服务信息 +var ( + webServiceCache = make(map[string]*ServiceInfo) + webCacheMutex sync.RWMutex +) + +// IsWebServiceByFingerprint 基于服务指纹智能判断是否为Web服务 +func IsWebServiceByFingerprint(serviceInfo *ServiceInfo) bool { + if serviceInfo == nil || serviceInfo.Name == "" { + return false + } + + serviceName := strings.ToLower(serviceInfo.Name) + + // HTTP相关服务类型列表(基于nmap服务指纹库) + webServices := []string{ + "http", "https", "http-proxy", "http-alt", "ssl/http", + "http-mgmt", "httpd", "nginx", "apache", "iis", + "tomcat", "jetty", "lighttpd", "caddy", "traefik", + "websphere", "weblogic", "jboss", "wildfly", + "nodejs", "express", "kestrel", "gunicorn", "uvicorn", + "cherrypy", "tornado", "flask", "django", "rails", + "php", "php-fpm", "asp", "aspx", "jsp", "servlet", + "cgid", "cgi", "fcgi", "wsgi", "node.js", + } + + // 检查服务名称是否匹配Web服务 + for _, webService := range webServices { + if serviceName == webService || strings.Contains(serviceName, webService) { + common.LogDebug(fmt.Sprintf("基于指纹识别为Web服务: %s -> %s", serviceName, webService)) + return true + } + } + + // 检查Banner中的Web服务器特征 + if serviceInfo.Banner != "" { + banner := strings.ToLower(serviceInfo.Banner) + webBanners := []string{ + "server:", "apache", "nginx", "iis", "lighttpd", + "caddy", "traefik", "tomcat", "jetty", "nodejs", + "content-type:", "content-length:", "http/", + "connection:", "keep-alive", "close", + } + + for _, webBanner := range webBanners { + if strings.Contains(banner, webBanner) { + common.LogDebug(fmt.Sprintf("基于Banner识别为Web服务: %s", webBanner)) + return true + } + } + } + + // 检查额外信息中的Web特征 + if serviceInfo.Extras != nil { + for key, value := range serviceInfo.Extras { + keyLower := strings.ToLower(key) + valueLower := strings.ToLower(value) + + if keyLower == "info" && (strings.Contains(valueLower, "web") || + strings.Contains(valueLower, "http") || strings.Contains(valueLower, "html")) { + common.LogDebug(fmt.Sprintf("基于Extras识别为Web服务: %s=%s", key, value)) + return true + } + } + } + + common.LogDebug(fmt.Sprintf("指纹识别为非Web服务: %s", serviceName)) + return false +} + +// MarkAsWebService 标记端口为Web服务,用于后续Web插件调用 +func MarkAsWebService(host string, port int, serviceInfo *ServiceInfo) { + cacheKey := fmt.Sprintf("%s:%d", host, port) + + webCacheMutex.Lock() + defer webCacheMutex.Unlock() + + webServiceCache[cacheKey] = serviceInfo + common.LogDebug(fmt.Sprintf("标记Web服务: %s [%s]", cacheKey, serviceInfo.Name)) +} + +// GetWebServiceInfo 获取已标记的Web服务信息 +func GetWebServiceInfo(host string, port int) (*ServiceInfo, bool) { + cacheKey := fmt.Sprintf("%s:%d", host, port) + + webCacheMutex.RLock() + defer webCacheMutex.RUnlock() + + serviceInfo, exists := webServiceCache[cacheKey] + return serviceInfo, exists +} + +// IsMarkedWebService 检查端口是否已被标记为Web服务 +func IsMarkedWebService(host string, port int) bool { + _, exists := GetWebServiceInfo(host, port) + return exists +} +