Verify peer cert function for better man in the middle prevention (#746)

* verify peer cert function for better man in the middle prevention

* publish cert chain hash generation algorithm

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

* apply coding style

* added test case for pinned certificates

* refactored cert pin

* pinned cert test

* added json loading of the PinnedPeerCertificateChainSha256

* removed tool to prepare for v5

* Add server cert pinning for Xtls

Change command "xray tls certChainHash" to xray style

Co-authored-by: Shelikhoo <xiaokangwang@outlook.com>
This commit is contained in:
yuhan6665 2021-10-22 00:04:06 -04:00 committed by 世界
parent 6a60332700
commit acb81ebe3d
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
13 changed files with 447 additions and 35 deletions

View file

@ -0,0 +1,41 @@
package tls
import (
"flag"
"fmt"
"io/ioutil"
"github.com/xtls/xray-core/main/commands/base"
"github.com/xtls/xray-core/transport/internet/tls"
)
var cmdCertChainHash = &base.Command{
UsageLine: "{{.Exec}} certChainHash",
Short: "Calculate TLS certificates hash.",
Long: `
xray tls certChainHash --cert <cert.pem>
Calculate TLS certificate chain hash.
`,
}
func init() {
cmdCertChainHash.Run = executeCertChainHash // break init loop
}
var input = cmdCertChainHash.Flag.String("cert", "fullchain.pem", "The file path of the certificates chain")
func executeCertChainHash(cmd *base.Command, args []string) {
fs := flag.NewFlagSet("certChainHash", flag.ContinueOnError)
if err := fs.Parse(args); err != nil {
fmt.Println(err)
return
}
certContent, err := ioutil.ReadFile(*input)
if err != nil {
fmt.Println(err)
return
}
certChainHashB64 := tls.CalculatePEMCertChainSHA256Hash(certContent)
fmt.Println(certChainHashB64)
return
}

View file

@ -1,12 +1,14 @@
package tls
import (
"crypto/tls"
gotls "crypto/tls"
"crypto/x509"
"encoding/base64"
"fmt"
"net"
"github.com/xtls/xray-core/main/commands/base"
. "github.com/xtls/xray-core/transport/internet/tls"
)
// cmdPing is the tls ping command
@ -60,11 +62,13 @@ func executePing(cmd *base.Command, args []string) {
if err != nil {
base.Fatalf("Failed to dial tcp: %s", err)
}
tlsConn := tls.Client(tcpConn, &tls.Config{
tlsConn := gotls.Client(tcpConn, &gotls.Config{
InsecureSkipVerify: true,
NextProtos: []string{"http/1.1"},
MaxVersion: tls.VersionTLS12,
MinVersion: tls.VersionTLS12,
MaxVersion: gotls.VersionTLS12,
MinVersion: gotls.VersionTLS12,
// Do not release tool before v5's refactor
// VerifyPeerCertificate: showCert(),
})
err = tlsConn.Handshake()
if err != nil {
@ -83,11 +87,13 @@ func executePing(cmd *base.Command, args []string) {
if err != nil {
base.Fatalf("Failed to dial tcp: %s", err)
}
tlsConn := tls.Client(tcpConn, &tls.Config{
tlsConn := gotls.Client(tcpConn, &gotls.Config{
ServerName: domain,
NextProtos: []string{"http/1.1"},
MaxVersion: tls.VersionTLS12,
MinVersion: tls.VersionTLS12,
MaxVersion: gotls.VersionTLS12,
MinVersion: gotls.VersionTLS12,
// Do not release tool before v5's refactor
// VerifyPeerCertificate: showCert(),
})
err = tlsConn.Handshake()
if err != nil {
@ -110,3 +116,11 @@ func printCertificates(certs []*x509.Certificate) {
fmt.Println("Allowed domains: ", cert.DNSNames)
}
}
func showCert() func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
hash := GenerateCertChainHash(rawCerts)
fmt.Println("Certificate Chain Hash: ", base64.StdEncoding.EncodeToString(hash))
return nil
}
}

View file

@ -13,5 +13,6 @@ var CmdTLS = &base.Command{
Commands: []*base.Command{
cmdCert,
cmdPing,
cmdCertChainHash,
},
}