refactor: 优化Web服务检测逻辑,优先使用指纹识别结果

功能优化:
- 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检测架构
This commit is contained in:
ZacharyZcR 2025-09-02 06:40:14 +00:00
parent 82ab894bcf
commit 1ff44d1ebc

View File

@ -102,8 +102,15 @@ func newWebPortDetector() *WebPortDetector {
} }
} }
// IsWebService 智能检测端口是否运行Web服务 // IsWebService 智能检测端口是否运行Web服务(优化版:优先使用指纹识别结果)
func (w *WebPortDetector) IsWebService(host string, port int) bool { 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 // 1. 快速路径常见Web端口直接返回true
if w.IsCommonWebPort(port) { if w.IsCommonWebPort(port) {
common.LogDebug(fmt.Sprintf("端口 %d 是常见Web端口启用Web插件", 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() w.cacheMutex.RUnlock()
// 3. 智能路径对非常见端口进行HTTP协议探测 // 3. 回退路径对非常见端口进行HTTP协议探测仅在服务指纹识别失败时使用
common.LogDebug(fmt.Sprintf("对端口 %d 进行智能Web检测", port)) common.LogDebug(fmt.Sprintf("端口 %d 未通过服务指纹识别为Web服务回退到HTTP协议探测", port))
result := w.detectHTTPService(host, port) result := w.detectHTTPService(host, port)
// 4. 缓存结果 // 4. 缓存结果
@ -129,7 +136,7 @@ func (w *WebPortDetector) IsWebService(host string, port int) bool {
w.detectionCache[cacheKey] = result w.detectionCache[cacheKey] = result
w.cacheMutex.Unlock() w.cacheMutex.Unlock()
common.LogDebug(fmt.Sprintf("端口 %d 智能检测结果: %v", port, result)) common.LogDebug(fmt.Sprintf("端口 %d HTTP协议探测结果: %v", port, result))
return result return result
} }
@ -420,4 +427,106 @@ func min(a, b int) int {
return b 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
}