github.com/moqsien/xraycore@v1.8.5/main/commands/all/tls/ping.go (about)

     1  package tls
     2  
     3  import (
     4  	gotls "crypto/tls"
     5  	"crypto/x509"
     6  	"encoding/base64"
     7  	"fmt"
     8  	"net"
     9  
    10  	"github.com/moqsien/xraycore/main/commands/base"
    11  	. "github.com/moqsien/xraycore/transport/internet/tls"
    12  )
    13  
    14  // cmdPing is the tls ping command
    15  var cmdPing = &base.Command{
    16  	UsageLine: "{{.Exec}} tls ping [-ip <ip>] <domain>",
    17  	Short:     "Ping the domain with TLS handshake",
    18  	Long: `
    19  Ping the domain with TLS handshake.
    20  
    21  Arguments:
    22  
    23  	-ip
    24  		The IP address of the domain.
    25  `,
    26  }
    27  
    28  func init() {
    29  	cmdPing.Run = executePing // break init loop
    30  }
    31  
    32  var pingIPStr = cmdPing.Flag.String("ip", "", "")
    33  
    34  func executePing(cmd *base.Command, args []string) {
    35  	if cmdPing.Flag.NArg() < 1 {
    36  		base.Fatalf("domain not specified")
    37  	}
    38  
    39  	domain := cmdPing.Flag.Arg(0)
    40  	fmt.Println("Tls ping: ", domain)
    41  
    42  	var ip net.IP
    43  	if len(*pingIPStr) > 0 {
    44  		v := net.ParseIP(*pingIPStr)
    45  		if v == nil {
    46  			base.Fatalf("invalid IP: %s", *pingIPStr)
    47  		}
    48  		ip = v
    49  	} else {
    50  		v, err := net.ResolveIPAddr("ip", domain)
    51  		if err != nil {
    52  			base.Fatalf("Failed to resolve IP: %s", err)
    53  		}
    54  		ip = v.IP
    55  	}
    56  	fmt.Println("Using IP: ", ip.String())
    57  
    58  	fmt.Println("-------------------")
    59  	fmt.Println("Pinging without SNI")
    60  	{
    61  		tcpConn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: ip, Port: 443})
    62  		if err != nil {
    63  			base.Fatalf("Failed to dial tcp: %s", err)
    64  		}
    65  		tlsConn := gotls.Client(tcpConn, &gotls.Config{
    66  			InsecureSkipVerify: true,
    67  			NextProtos:         []string{"http/1.1"},
    68  			MaxVersion:         gotls.VersionTLS12,
    69  			MinVersion:         gotls.VersionTLS12,
    70  			// Do not release tool before v5's refactor
    71  			// VerifyPeerCertificate: showCert(),
    72  		})
    73  		err = tlsConn.Handshake()
    74  		if err != nil {
    75  			fmt.Println("Handshake failure: ", err)
    76  		} else {
    77  			fmt.Println("Handshake succeeded")
    78  			printCertificates(tlsConn.ConnectionState().PeerCertificates)
    79  		}
    80  		tlsConn.Close()
    81  	}
    82  
    83  	fmt.Println("-------------------")
    84  	fmt.Println("Pinging with SNI")
    85  	{
    86  		tcpConn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: ip, Port: 443})
    87  		if err != nil {
    88  			base.Fatalf("Failed to dial tcp: %s", err)
    89  		}
    90  		tlsConn := gotls.Client(tcpConn, &gotls.Config{
    91  			ServerName: domain,
    92  			NextProtos: []string{"http/1.1"},
    93  			MaxVersion: gotls.VersionTLS12,
    94  			MinVersion: gotls.VersionTLS12,
    95  			// Do not release tool before v5's refactor
    96  			// VerifyPeerCertificate: showCert(),
    97  		})
    98  		err = tlsConn.Handshake()
    99  		if err != nil {
   100  			fmt.Println("handshake failure: ", err)
   101  		} else {
   102  			fmt.Println("handshake succeeded")
   103  			printCertificates(tlsConn.ConnectionState().PeerCertificates)
   104  		}
   105  		tlsConn.Close()
   106  	}
   107  
   108  	fmt.Println("Tls ping finished")
   109  }
   110  
   111  func printCertificates(certs []*x509.Certificate) {
   112  	for _, cert := range certs {
   113  		if len(cert.DNSNames) == 0 {
   114  			continue
   115  		}
   116  		fmt.Println("Allowed domains: ", cert.DNSNames)
   117  	}
   118  }
   119  
   120  func showCert() func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
   121  	return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
   122  		hash := GenerateCertChainHash(rawCerts)
   123  		fmt.Println("Certificate Chain Hash: ", base64.StdEncoding.EncodeToString(hash))
   124  		return nil
   125  	}
   126  }