mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 14:06:44 +08:00
145 lines
3.8 KiB
Go
145 lines
3.8 KiB
Go
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
|
||
} |