scanSingleIP 扫描单个IP地址
(ip net.IP, origin string, resultChan chan<- ScanResult, geo *Geo)
| 50 | |
| 51 | // scanSingleIP 扫描单个IP地址 |
| 52 | func scanSingleIP(ip net.IP, origin string, resultChan chan<- ScanResult, geo *Geo) { |
| 53 | startTime := time.Now() |
| 54 | |
| 55 | result := ScanResult{ |
| 56 | IP: ip.String(), |
| 57 | Origin: origin, |
| 58 | Port: config.Port, |
| 59 | } |
| 60 | |
| 61 | // 获取地理位置信息 |
| 62 | if geo != nil { |
| 63 | result.GeoCode = geo.GetGeo(ip) |
| 64 | } |
| 65 | |
| 66 | // 建立TCP连接 |
| 67 | address := fmt.Sprintf("%s:%d", ip.String(), config.Port) |
| 68 | conn, err := net.DialTimeout("tcp", address, time.Duration(config.Timeout)*time.Second) |
| 69 | if err != nil { |
| 70 | result.Error = fmt.Sprintf("TCP连接失败: %v", err) |
| 71 | resultChan <- result |
| 72 | return |
| 73 | } |
| 74 | defer conn.Close() |
| 75 | |
| 76 | // Reality专用TLS配置 |
| 77 | tlsConfig := &tls.Config{ |
| 78 | InsecureSkipVerify: true, // 跳过证书验证 |
| 79 | NextProtos: []string{"h2", "http/1.1"}, // ALPN协议优先HTTP/2 |
| 80 | CurvePreferences: []tls.CurveID{tls.X25519}, // 强制使用X25519椭圆曲线 |
| 81 | ServerName: origin, // SNI |
| 82 | } |
| 83 | |
| 84 | // 如果原始输入是域名,使用域名作为SNI |
| 85 | if ValidateDomainName(origin) { |
| 86 | tlsConfig.ServerName = origin |
| 87 | } else { |
| 88 | // 如果是IP,尝试从证书中获取域名 |
| 89 | tlsConfig.ServerName = "" |
| 90 | } |
| 91 | |
| 92 | // 执行TLS握手 |
| 93 | tlsConn := tls.Client(conn, tlsConfig) |
| 94 | err = tlsConn.Handshake() |
| 95 | if err != nil { |
| 96 | result.Error = fmt.Sprintf("TLS握手失败: %v", err) |
| 97 | resultChan <- result |
| 98 | return |
| 99 | } |
| 100 | defer tlsConn.Close() |
| 101 | |
| 102 | // 获取连接状态 |
| 103 | state := tlsConn.ConnectionState() |
| 104 | |
| 105 | // 记录响应时间 |
| 106 | result.ResponseTime = time.Since(startTime).Milliseconds() |
| 107 | |
| 108 | // 提取TLS版本 |
| 109 | result.TLSVersion = getTLSVersionString(state.Version) |
no test coverage detected