mirror of https://github.com/v2ray/v2ray-core
				
				
				
			
		
			
				
	
	
		
			120 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
package control
 | 
						|
 | 
						|
import (
 | 
						|
	"crypto/tls"
 | 
						|
	"crypto/x509"
 | 
						|
	"flag"
 | 
						|
	"fmt"
 | 
						|
	"net"
 | 
						|
 | 
						|
	"v2ray.com/core/common"
 | 
						|
)
 | 
						|
 | 
						|
type TlsPingCommand struct{}
 | 
						|
 | 
						|
func (c *TlsPingCommand) Name() string {
 | 
						|
	return "tlsping"
 | 
						|
}
 | 
						|
 | 
						|
func (c *TlsPingCommand) Description() Description {
 | 
						|
	return Description{
 | 
						|
		Short: "Ping the domain with TLS handshake",
 | 
						|
		Usage: []string{"v2ctl tlsping <domain> --ip <ip>"},
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func printCertificates(certs []*x509.Certificate) {
 | 
						|
	for _, cert := range certs {
 | 
						|
		if len(cert.DNSNames) == 0 {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		fmt.Println("Allowed domains: ", cert.DNSNames)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (c *TlsPingCommand) Execute(args []string) error {
 | 
						|
	fs := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
 | 
						|
	ipStr := fs.String("ip", "", "IP address of the domain")
 | 
						|
 | 
						|
	if err := fs.Parse(args); err != nil {
 | 
						|
		return newError("flag parsing").Base(err)
 | 
						|
	}
 | 
						|
 | 
						|
	if fs.NArg() < 1 {
 | 
						|
		return newError("domain not specified")
 | 
						|
	}
 | 
						|
 | 
						|
	domain := fs.Arg(0)
 | 
						|
	fmt.Println("Tls ping: ", domain)
 | 
						|
 | 
						|
	var ip net.IP
 | 
						|
	if len(*ipStr) > 0 {
 | 
						|
		v := net.ParseIP(*ipStr)
 | 
						|
		if v == nil {
 | 
						|
			return newError("invalid IP: ", *ipStr)
 | 
						|
		}
 | 
						|
		ip = v
 | 
						|
	} else {
 | 
						|
		v, err := net.ResolveIPAddr("ip", domain)
 | 
						|
		if err != nil {
 | 
						|
			return newError("resolve IP").Base(err)
 | 
						|
		}
 | 
						|
		ip = v.IP
 | 
						|
	}
 | 
						|
	fmt.Println("Using IP: ", ip.String())
 | 
						|
 | 
						|
	fmt.Println("-------------------")
 | 
						|
	fmt.Println("Pinging without SNI")
 | 
						|
	{
 | 
						|
		tcpConn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: ip, Port: 443})
 | 
						|
		if err != nil {
 | 
						|
			return newError("dial tcp").Base(err)
 | 
						|
		}
 | 
						|
		tlsConn := tls.Client(tcpConn, &tls.Config{
 | 
						|
			InsecureSkipVerify: true,
 | 
						|
			NextProtos:         []string{"http/1.1"},
 | 
						|
			MaxVersion:         tls.VersionTLS12,
 | 
						|
			MinVersion:         tls.VersionTLS12,
 | 
						|
		})
 | 
						|
		err = tlsConn.Handshake()
 | 
						|
		if err != nil {
 | 
						|
			fmt.Println("Handshake failure: ", err)
 | 
						|
		} else {
 | 
						|
			fmt.Println("Handshake succeeded")
 | 
						|
			printCertificates(tlsConn.ConnectionState().PeerCertificates)
 | 
						|
		}
 | 
						|
		tlsConn.Close()
 | 
						|
	}
 | 
						|
 | 
						|
	fmt.Println("-------------------")
 | 
						|
	fmt.Println("Pinging with SNI")
 | 
						|
	{
 | 
						|
		tcpConn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: ip, Port: 443})
 | 
						|
		if err != nil {
 | 
						|
			return newError("dial tcp").Base(err)
 | 
						|
		}
 | 
						|
		tlsConn := tls.Client(tcpConn, &tls.Config{
 | 
						|
			ServerName: domain,
 | 
						|
			NextProtos: []string{"http/1.1"},
 | 
						|
			MaxVersion: tls.VersionTLS12,
 | 
						|
			MinVersion: tls.VersionTLS12,
 | 
						|
		})
 | 
						|
		err = tlsConn.Handshake()
 | 
						|
		if err != nil {
 | 
						|
			fmt.Println("handshake failure: ", err)
 | 
						|
		} else {
 | 
						|
			fmt.Println("handshake succeeded")
 | 
						|
			printCertificates(tlsConn.ConnectionState().PeerCertificates)
 | 
						|
		}
 | 
						|
		tlsConn.Close()
 | 
						|
	}
 | 
						|
 | 
						|
	fmt.Println("Tls ping finished")
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func init() {
 | 
						|
	common.Must(RegisterCommand(&TlsPingCommand{}))
 | 
						|
}
 |