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 +} +