| 10 | ) |
| 11 | |
| 12 | func ScanTLS(host Host, out chan<- string, geo *Geo) { |
| 13 | if host.IP == nil { |
| 14 | ip, err := LookupIP(host.Origin) |
| 15 | if err != nil { |
| 16 | slog.Debug("Failed to get IP from the origin", "origin", host.Origin, "err", err) |
| 17 | return |
| 18 | } |
| 19 | host.IP = ip |
| 20 | } |
| 21 | hostPort := net.JoinHostPort(host.IP.String(), strconv.Itoa(port)) |
| 22 | conn, err := net.DialTimeout("tcp", hostPort, time.Duration(timeout)*time.Second) |
| 23 | if err != nil { |
| 24 | slog.Debug("Cannot dial", "target", hostPort) |
| 25 | return |
| 26 | } |
| 27 | defer conn.Close() |
| 28 | err = conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second)) |
| 29 | if err != nil { |
| 30 | slog.Error("Error setting deadline", "err", err) |
| 31 | return |
| 32 | } |
| 33 | tlsCfg := &tls.Config{ |
| 34 | InsecureSkipVerify: true, |
| 35 | NextProtos: []string{"h2", "http/1.1"}, |
| 36 | CurvePreferences: []tls.CurveID{tls.X25519, tls.X25519MLKEM768}, |
| 37 | } |
| 38 | if host.Type == HostTypeDomain { |
| 39 | tlsCfg.ServerName = host.Origin |
| 40 | } |
| 41 | c := tls.Client(conn, tlsCfg) |
| 42 | err = c.Handshake() |
| 43 | if err != nil { |
| 44 | slog.Debug("TLS handshake failed", "target", hostPort) |
| 45 | return |
| 46 | } |
| 47 | state := c.ConnectionState() |
| 48 | alpn := state.NegotiatedProtocol |
| 49 | domain := state.PeerCertificates[0].Subject.CommonName |
| 50 | issuers := strings.Join(state.PeerCertificates[0].Issuer.Organization, " | ") |
| 51 | length := 0 |
| 52 | leaf := state.PeerCertificates[0] |
| 53 | for _, cert := range state.PeerCertificates { |
| 54 | length += len(cert.Raw) |
| 55 | if len(cert.DNSNames) != 0 { |
| 56 | leaf = cert |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | log := slog.Info |
| 61 | feasible := true |
| 62 | geoCode := geo.GetGeo(host.IP) |
| 63 | if state.Version != tls.VersionTLS13 || alpn != "h2" || len(domain) == 0 || len(issuers) == 0 { |
| 64 | // not feasible |
| 65 | log = slog.Debug |
| 66 | feasible = false |
| 67 | } else { |
| 68 | out <- strings.Join([]string{ |
| 69 | host.IP.String(), |