Skip to content

Commit

Permalink
netxlite: utls for TLS parroting
Browse files Browse the repository at this point in the history
This is the ground work for ooni/probe#1424.
  • Loading branch information
kelmenhorst authored and bassosimone committed Jul 2, 2021
1 parent 17bfb05 commit 9c5cae7
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ require (
github.com/sirupsen/logrus v1.7.0 // indirect
github.com/ziutek/mymysql v1.5.4 // indirect
gitlab.com/yawning/obfs4.git v0.0.0-20210511220700-e330d1b7024b
gitlab.com/yawning/utls.git v0.0.12-1
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf // indirect
golang.org/x/net v0.0.0-20210510120150-4163338589ed
golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744
Expand Down
39 changes: 39 additions & 0 deletions internal/netxlite/tlshandshaker.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"crypto/tls"
"net"
"time"

utls "gitlab.com/yawning/utls.git"
)

// TLSHandshaker is the generic TLS handshaker.
Expand Down Expand Up @@ -105,4 +107,41 @@ func (h *TLSHandshakerLogger) Handshake(
return tlsconn, state, nil
}

// UTLSConn implements TLSConn and uses a utls UConn as its underlying connection
type UTLSConn struct {
*utls.UConn
}

// NewConnUTLS creates a NewConn function creating a utls connection with a specified ClientHelloID
func NewConnUTLS(clientHello *utls.ClientHelloID) func(conn net.Conn, config *tls.Config) TLSConn {
return func(conn net.Conn, config *tls.Config) TLSConn {
uConfig := &utls.Config{
RootCAs: config.RootCAs,
NextProtos: config.NextProtos,
ServerName: config.ServerName,
InsecureSkipVerify: config.InsecureSkipVerify,
DynamicRecordSizingDisabled: config.DynamicRecordSizingDisabled,
}
tlsConn := utls.UClient(conn, uConfig, *clientHello)
return &UTLSConn{tlsConn}
}
}

func (c *UTLSConn) ConnectionState() tls.ConnectionState {
uState := c.Conn.ConnectionState()
return tls.ConnectionState{
Version: uState.Version,
HandshakeComplete: uState.HandshakeComplete,
DidResume: uState.DidResume,
CipherSuite: uState.CipherSuite,
NegotiatedProtocol: uState.NegotiatedProtocol,
ServerName: uState.ServerName,
PeerCertificates: uState.PeerCertificates,
VerifiedChains: uState.VerifiedChains,
SignedCertificateTimestamps: uState.SignedCertificateTimestamps,
OCSPResponse: uState.OCSPResponse,
TLSUnique: uState.TLSUnique,
}
}

var _ TLSHandshaker = &TLSHandshakerLogger{}
16 changes: 16 additions & 0 deletions internal/netxlite/tlshandshaker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"github.com/apex/log"
"github.com/ooni/probe-cli/v3/internal/netxmocks"
utls "gitlab.com/yawning/utls.git"
)

func TestTLSHandshakerConfigurableWithError(t *testing.T) {
Expand Down Expand Up @@ -177,3 +178,18 @@ func TestTLSHandshakerLoggerFailure(t *testing.T) {
t.Fatal("expected zero ConnectionState here")
}
}

func TestUTLSHandshakerChrome(t *testing.T) {
h := &TLSHandshakerConfigurable{
NewConn: NewConnUTLS(&utls.HelloChrome_Auto),
}
cfg := &tls.Config{ServerName: "google.com"}
conn, err := net.Dial("tcp", "google.com:443")
conn, _, err = h.Handshake(context.Background(), conn, cfg)
if err != nil {
t.Fatal("unexpected error", err)
}
if conn == nil {
t.Fatal("nil connection")
}
}

0 comments on commit 9c5cae7

Please sign in to comment.