certificate pinning for websocket

This commit is contained in:
luyuhuang 2020-08-13 11:38:56 +08:00
parent 2707a8f0a9
commit 5e620e8e8f

41
ws.go
View File

@ -1,13 +1,16 @@
package gost package gost
import ( import (
"context"
"crypto/rand" "crypto/rand"
"crypto/sha1" "crypto/sha1"
"crypto/tls" "crypto/tls"
"crypto/x509"
"encoding/base64" "encoding/base64"
"io" "io"
"net" "net"
"net/http" "net/http"
"net/http/httptrace"
"net/http/httputil" "net/http/httputil"
"sync" "sync"
"time" "time"
@ -749,10 +752,46 @@ func websocketClientConn(url string, conn net.Conn, tlsConfig *tls.Config, optio
if options.UserAgent != "" { if options.UserAgent != "" {
header.Set("User-Agent", options.UserAgent) header.Set("User-Agent", options.UserAgent)
} }
c, resp, err := dialer.Dial(url, header)
var verifyErr error = nil
trace := &httptrace.ClientTrace{
TLSHandshakeDone: func(state tls.ConnectionState, err error) {
if tlsConfig.RootCAs == nil {
return
}
opts := x509.VerifyOptions{
Roots: tlsConfig.RootCAs,
CurrentTime: time.Now(),
DNSName: "",
Intermediates: x509.NewCertPool(),
}
certs := state.PeerCertificates
for i, cert := range certs {
if i == 0 {
continue
}
opts.Intermediates.AddCert(cert)
}
_, err = certs[0].Verify(opts)
if err != nil {
verifyErr = err
}
},
}
ctx := httptrace.WithClientTrace(context.Background(), trace)
c, resp, err := dialer.DialContext(ctx, url, header)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if verifyErr != nil {
return nil, verifyErr
}
resp.Body.Close() resp.Body.Close()
return &websocketConn{conn: c}, nil return &websocketConn{conn: c}, nil
} }