package core import ( "context" "net" "net/http" "strings" "time" ) // WebPortDetector Web端口检测器 type WebPortDetector struct { // 常见Web端口列表 commonWebPorts map[int]bool // HTTP检测超时时间 httpTimeout time.Duration } // NewWebPortDetector 创建Web端口检测器 func NewWebPortDetector() *WebPortDetector { // 定义常见Web端口 commonPorts := map[int]bool{ 80: true, // HTTP 443: true, // HTTPS 8080: true, // HTTP alternate 8443: true, // HTTPS alternate 8000: true, // Development server 8888: true, // Common dev port 9000: true, // Common dev port 9090: true, // Common dev port 3000: true, // Node.js dev server 4000: true, // Ruby dev server 5000: true, // Python dev server 8081: true, // HTTP alternate 8082: true, // HTTP alternate 8083: true, // HTTP alternate 8084: true, // HTTP alternate 8085: true, // HTTP alternate 8086: true, // HTTP alternate 8087: true, // HTTP alternate 8088: true, // HTTP alternate 8089: true, // HTTP alternate } return &WebPortDetector{ commonWebPorts: commonPorts, httpTimeout: 2 * time.Second, // 2秒超时,快速检测 } } // IsWebService 检测指定主机端口是否为Web服务 func (w *WebPortDetector) IsWebService(host string, port int) bool { // 1. 首先检查是否为常见Web端口 if w.commonWebPorts[port] { return true } // 2. 对于非常见端口,进行HTTP协议检测 return w.detectHTTPService(host, port) } // IsCommonWebPort 检查是否为常见Web端口 func (w *WebPortDetector) IsCommonWebPort(port int) bool { return w.commonWebPorts[port] } // detectHTTPService 检测HTTP服务(轻量级探测) func (w *WebPortDetector) detectHTTPService(host string, port int) bool { // 创建检测上下文,避免长时间阻塞 ctx, cancel := context.WithTimeout(context.Background(), w.httpTimeout) defer cancel() // 尝试HTTP连接 if w.tryHTTPConnection(ctx, host, port, "http") { return true } // 尝试HTTPS连接(对于高端口常见) if w.tryHTTPConnection(ctx, host, port, "https") { return true } return false } // tryHTTPConnection 尝试HTTP连接 func (w *WebPortDetector) tryHTTPConnection(ctx context.Context, host string, port int, protocol string) bool { url := "" if port == 80 && protocol == "http" { url = "http://" + host } else if port == 443 && protocol == "https" { url = "https://" + host } else { url = protocol + "://" + host + ":" + string(rune(port)) } // 创建HTTP客户端,快速检测 client := &http.Client{ Timeout: w.httpTimeout, Transport: &http.Transport{ DialContext: (&net.Dialer{ Timeout: w.httpTimeout, }).DialContext, TLSHandshakeTimeout: w.httpTimeout, ResponseHeaderTimeout: w.httpTimeout, DisableKeepAlives: true, }, CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse // 不跟随重定向,加快检测速度 }, } // 发送HEAD请求,最小化网络开销 req, err := http.NewRequestWithContext(ctx, "HEAD", url, nil) if err != nil { return false } req.Header.Set("User-Agent", "fscan-web-detector/2.0") resp, err := client.Do(req) if err != nil { // 检查错误类型,某些错误也表明是HTTP服务 errStr := strings.ToLower(err.Error()) if strings.Contains(errStr, "http") || strings.Contains(errStr, "malformed http") || strings.Contains(errStr, "server closed") { return true } return false } defer resp.Body.Close() // 任何HTTP响应都表明这是Web服务 return resp.StatusCode > 0 } // GetCommonWebPorts 获取常见Web端口列表 func (w *WebPortDetector) GetCommonWebPorts() []int { ports := make([]int, 0, len(w.commonWebPorts)) for port := range w.commonWebPorts { ports = append(ports, port) } return ports }