Browse Source

added calculation of certificate hash as separate command and tlsping, use base64 to represent fingerprint to align with jsonPb

Shelikhoo 4 years ago
parent
commit
92b845a45b
3 changed files with 79 additions and 10 deletions
  1. 57 0
      infra/control/certchainhash.go
  2. 20 8
      infra/control/tlsping.go
  3. 2 2
      transport/internet/tls/config.go

+ 57 - 0
infra/control/certchainhash.go

@@ -0,0 +1,57 @@
+package control
+
+import (
+	"encoding/base64"
+	"encoding/pem"
+	"flag"
+	"fmt"
+	"github.com/v2fly/v2ray-core/v4/common"
+	v2tls "github.com/v2fly/v2ray-core/v4/transport/internet/tls"
+	"io/ioutil"
+)
+
+type CertificateChainHashCommand struct {
+}
+
+func (c CertificateChainHashCommand) Name() string {
+	return "certChainHash"
+}
+
+func (c CertificateChainHashCommand) Description() Description {
+	return Description{
+		Short: "Calculate TLS certificates hash.",
+		Usage: []string{
+			"v2ctl certChainHash --cert <cert.pem>",
+			"Calculate TLS certificate chain hash.",
+		},
+	}
+}
+
+func (c CertificateChainHashCommand) Execute(args []string) error {
+	fs := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
+	cert := fs.String("cert", "fullchain.pem", "The file path of the certificates chain")
+	if err := fs.Parse(args); err != nil {
+		return err
+	}
+	certContent, err := ioutil.ReadFile(*cert)
+	if err != nil {
+		return err
+	}
+	var certChain [][]byte
+	for {
+		block, remain := pem.Decode(certContent)
+		if block == nil {
+			break
+		}
+		certChain = append(certChain, block.Bytes)
+		certContent = remain
+	}
+	certChainHash := v2tls.GenerateCertChainHash(certChain)
+	certChainHashB64 := base64.StdEncoding.EncodeToString(certChainHash)
+	fmt.Println(certChainHashB64)
+	return nil
+}
+
+func init() {
+	common.Must(RegisterCommand(&CertificateChainHashCommand{}))
+}

+ 20 - 8
infra/control/tlsping.go

@@ -3,11 +3,13 @@ package control
 import (
 import (
 	"crypto/tls"
 	"crypto/tls"
 	"crypto/x509"
 	"crypto/x509"
+	"encoding/base64"
 	"flag"
 	"flag"
 	"fmt"
 	"fmt"
 	"net"
 	"net"
 
 
 	"github.com/v2fly/v2ray-core/v4/common"
 	"github.com/v2fly/v2ray-core/v4/common"
+	v2tls "github.com/v2fly/v2ray-core/v4/transport/internet/tls"
 )
 )
 
 
 type TLSPingCommand struct{}
 type TLSPingCommand struct{}
@@ -71,10 +73,11 @@ func (c *TLSPingCommand) Execute(args []string) error {
 			return newError("dial tcp").Base(err)
 			return newError("dial tcp").Base(err)
 		}
 		}
 		tlsConn := tls.Client(tcpConn, &tls.Config{
 		tlsConn := tls.Client(tcpConn, &tls.Config{
-			InsecureSkipVerify: true,
-			NextProtos:         []string{"http/1.1"},
-			MaxVersion:         tls.VersionTLS12,
-			MinVersion:         tls.VersionTLS12,
+			InsecureSkipVerify:    true,
+			NextProtos:            []string{"http/1.1"},
+			MaxVersion:            tls.VersionTLS12,
+			MinVersion:            tls.VersionTLS12,
+			VerifyPeerCertificate: showCert(),
 		})
 		})
 		err = tlsConn.Handshake()
 		err = tlsConn.Handshake()
 		if err != nil {
 		if err != nil {
@@ -94,10 +97,11 @@ func (c *TLSPingCommand) Execute(args []string) error {
 			return newError("dial tcp").Base(err)
 			return newError("dial tcp").Base(err)
 		}
 		}
 		tlsConn := tls.Client(tcpConn, &tls.Config{
 		tlsConn := tls.Client(tcpConn, &tls.Config{
-			ServerName: domain,
-			NextProtos: []string{"http/1.1"},
-			MaxVersion: tls.VersionTLS12,
-			MinVersion: tls.VersionTLS12,
+			ServerName:            domain,
+			NextProtos:            []string{"http/1.1"},
+			MaxVersion:            tls.VersionTLS12,
+			MinVersion:            tls.VersionTLS12,
+			VerifyPeerCertificate: showCert(),
 		})
 		})
 		err = tlsConn.Handshake()
 		err = tlsConn.Handshake()
 		if err != nil {
 		if err != nil {
@@ -114,6 +118,14 @@ func (c *TLSPingCommand) Execute(args []string) error {
 	return nil
 	return nil
 }
 }
 
 
+func showCert() func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
+	return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
+		hash := v2tls.GenerateCertChainHash(rawCerts)
+		fmt.Println("Certificate Chain Hash: ", base64.StdEncoding.EncodeToString(hash))
+		return nil
+	}
+}
+
 func init() {
 func init() {
 	common.Must(RegisterCommand(&TLSPingCommand{}))
 	common.Must(RegisterCommand(&TLSPingCommand{}))
 }
 }

+ 2 - 2
transport/internet/tls/config.go

@@ -7,7 +7,7 @@ import (
 	"crypto/sha256"
 	"crypto/sha256"
 	"crypto/tls"
 	"crypto/tls"
 	"crypto/x509"
 	"crypto/x509"
-	"encoding/hex"
+	"encoding/base64"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
 	"time"
 	"time"
@@ -181,7 +181,7 @@ func (c *Config) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509.Cert
 				return nil
 				return nil
 			}
 			}
 		}
 		}
-		return newError("peer cert is unrecognized: ", hex.EncodeToString(hashValue))
+		return newError("peer cert is unrecognized: ", base64.StdEncoding.EncodeToString(hashValue))
 	}
 	}
 	return nil
 	return nil
 }
 }