|
|
@@ -0,0 +1,105 @@
|
|
|
+package control
|
|
|
+
|
|
|
+import (
|
|
|
+ "crypto/tls"
|
|
|
+ "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 (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("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")
|
|
|
+ }
|
|
|
+ tlsConn.Close()
|
|
|
+ }
|
|
|
+
|
|
|
+ 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")
|
|
|
+ }
|
|
|
+ tlsConn.Close()
|
|
|
+ }
|
|
|
+
|
|
|
+ fmt.Println("Tls ping finished")
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func init() {
|
|
|
+ common.Must(RegisterCommand(&TlsPingCommand{}))
|
|
|
+}
|