github.com/v2fly/v2ray-core/v4@v4.45.2/infra/control/tlsping.go (about) 1 package control 2 3 import ( 4 "crypto/tls" 5 "crypto/x509" 6 "encoding/base64" 7 "flag" 8 "fmt" 9 "net" 10 11 "github.com/v2fly/v2ray-core/v4/common" 12 v2tls "github.com/v2fly/v2ray-core/v4/transport/internet/tls" 13 ) 14 15 type TLSPingCommand struct{} 16 17 func (c *TLSPingCommand) Name() string { 18 return "tlsping" 19 } 20 21 func (c *TLSPingCommand) Description() Description { 22 return Description{ 23 Short: "Ping the domain with TLS handshake", 24 Usage: []string{"v2ctl tlsping <domain> --ip <ip>"}, 25 } 26 } 27 28 func printCertificates(certs []*x509.Certificate) { 29 for _, cert := range certs { 30 if len(cert.DNSNames) == 0 { 31 continue 32 } 33 fmt.Println("Allowed domains: ", cert.DNSNames) 34 } 35 } 36 37 func (c *TLSPingCommand) Execute(args []string) error { 38 fs := flag.NewFlagSet(c.Name(), flag.ContinueOnError) 39 ipStr := fs.String("ip", "", "IP address of the domain") 40 41 if err := fs.Parse(args); err != nil { 42 return newError("flag parsing").Base(err) 43 } 44 45 if fs.NArg() < 1 { 46 return newError("domain not specified") 47 } 48 49 domain := fs.Arg(0) 50 fmt.Println("Tls ping: ", domain) 51 52 var ip net.IP 53 if len(*ipStr) > 0 { 54 v := net.ParseIP(*ipStr) 55 if v == nil { 56 return newError("invalid IP: ", *ipStr) 57 } 58 ip = v 59 } else { 60 v, err := net.ResolveIPAddr("ip", domain) 61 if err != nil { 62 return newError("resolve IP").Base(err) 63 } 64 ip = v.IP 65 } 66 fmt.Println("Using IP: ", ip.String()) 67 68 fmt.Println("-------------------") 69 fmt.Println("Pinging without SNI") 70 { 71 tcpConn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: ip, Port: 443}) 72 if err != nil { 73 return newError("dial tcp").Base(err) 74 } 75 tlsConn := tls.Client(tcpConn, &tls.Config{ 76 InsecureSkipVerify: true, 77 NextProtos: []string{"http/1.1"}, 78 MaxVersion: tls.VersionTLS12, 79 MinVersion: tls.VersionTLS12, 80 // Do not release tool before v5's refactor 81 // VerifyPeerCertificate: showCert(), 82 }) 83 err = tlsConn.Handshake() 84 if err != nil { 85 fmt.Println("Handshake failure: ", err) 86 } else { 87 fmt.Println("Handshake succeeded") 88 printCertificates(tlsConn.ConnectionState().PeerCertificates) 89 } 90 tlsConn.Close() 91 } 92 93 fmt.Println("-------------------") 94 fmt.Println("Pinging with SNI") 95 { 96 tcpConn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: ip, Port: 443}) 97 if err != nil { 98 return newError("dial tcp").Base(err) 99 } 100 tlsConn := tls.Client(tcpConn, &tls.Config{ 101 ServerName: domain, 102 NextProtos: []string{"http/1.1"}, 103 MaxVersion: tls.VersionTLS12, 104 MinVersion: tls.VersionTLS12, 105 // Do not release tool before v5's refactor 106 // VerifyPeerCertificate: showCert(), 107 }) 108 err = tlsConn.Handshake() 109 if err != nil { 110 fmt.Println("handshake failure: ", err) 111 } else { 112 fmt.Println("handshake succeeded") 113 printCertificates(tlsConn.ConnectionState().PeerCertificates) 114 } 115 tlsConn.Close() 116 } 117 118 fmt.Println("Tls ping finished") 119 120 return nil 121 } 122 123 func showCert() func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { 124 return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { 125 hash := v2tls.GenerateCertChainHash(rawCerts) 126 fmt.Println("Certificate Chain Hash: ", base64.StdEncoding.EncodeToString(hash)) 127 return nil 128 } 129 } 130 131 func init() { 132 common.Must(RegisterCommand(&TLSPingCommand{})) 133 }