Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ require (
github.com/hashicorp/golang-lru v0.5.4
github.com/mitchellh/panicwrap v1.0.0
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/refraction-networking/utls v1.3.3
github.com/refraction-networking/utls v1.6.7
github.com/refraction-networking/water v0.7.0-alpha
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726
github.com/spaolacci/murmur3 v1.1.0
Expand Down Expand Up @@ -83,13 +83,13 @@ require (
github.com/blang/vfs v1.0.0 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dchest/siphash v1.2.3 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/dvyukov/go-fuzz v0.0.0-20210429054444-fca39067bc72 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/gaukas/godicttls v0.0.3 // indirect
github.com/gaukas/wazerofs v0.1.0 // indirect
github.com/getlantern/algeneva v0.0.0-20240222191137-2b4e88234f59 // indirect
github.com/getlantern/bufconn v0.0.0-20190625204133-a08544339f8d // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
Expand All @@ -74,8 +76,6 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/gaukas/godicttls v0.0.3 h1:YNDIf0d9adcxOijiLrEzpfZGAkNwLRzPaG6OjU7EITk=
github.com/gaukas/godicttls v0.0.3/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
github.com/gaukas/wazerofs v0.1.0 h1:wIkW1bAxSnpaaVkQ5LOb1tm1BXdVap3eKjJpVWIqt2E=
github.com/gaukas/wazerofs v0.1.0/go.mod h1:+JECB9Fwt0taPqSgHckG9lmT3tcoVK+9VJozTsq9UlI=
github.com/getlantern/algeneva v0.0.0-20240222191137-2b4e88234f59 h1:uWNy0b1Wtpsd4n64Kat+fRjvPCBwM2Nykwt71LupJAQ=
Expand Down Expand Up @@ -425,8 +425,8 @@ github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/quic-go/quic-go v0.40.0 h1:GYd1iznlKm7dpHD7pOVpUvItgMPo/jrMgDWZhMCecqw=
github.com/quic-go/quic-go v0.40.0/go.mod h1:PeN7kuVJ4xZbxSv/4OX6S1USOX8MJvydwpTx31vx60c=
github.com/refraction-networking/utls v1.3.3 h1:f/TBLX7KBciRyFH3bwupp+CE4fzoYKCirhdRcC490sw=
github.com/refraction-networking/utls v1.3.3/go.mod h1:DlecWW1LMlMJu+9qpzzQqdHDT/C2LAe03EdpLUz/RL8=
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
github.com/refraction-networking/water v0.7.0-alpha h1:yLMAvIi0lHHD2mvwx63GLnptpjvnmBCWFvTHTWLykLk=
github.com/refraction-networking/water v0.7.0-alpha/go.mod h1:VPQENA6E5+2V5RlX/yaBlTCKeFQ25j49DUc/pmmwkXE=
github.com/refraction-networking/wazero v1.7.1-w h1:z7Ty5PsMkJEDBCsn3ELUjceQGBT0FMVGldOSpDK3giQ=
Expand Down
18 changes: 9 additions & 9 deletions http_proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,16 @@ var (
// TODO: this should be imported from tlsdefaults package, but is not being
// exported there.
preferredCipherSuites = []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_RSA_WITH_RC4_128_SHA,
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
}
)

Expand Down
18 changes: 9 additions & 9 deletions server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,16 @@ var (
// TODO: this should be imported from tlsdefaults package, but is not being
// exported there.
preferredCipherSuites = []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_RSA_WITH_RC4_128_SHA,
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
}
)

Expand Down
20 changes: 7 additions & 13 deletions tlslistener/clienthelloconn.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ func (rrc *clientHelloRecordingConn) processHello(info *tls.ClientHelloInfo) (*t
helloMsg := utls.UnmarshalClientHello(hello)

if helloMsg == nil {
return rrc.helloError("malformed ClientHello", false)
return rrc.helloError("malformed ClientHello")
}

sourceIP := rrc.RemoteAddr().(*net.TCPAddr).IP
Expand All @@ -205,31 +205,25 @@ func (rrc *clientHelloRecordingConn) processHello(info *tls.ClientHelloInfo) (*t
// pre-defined tickets. If it doesn't we should again return some sort of error or just
// close the connection.
if !helloMsg.TicketSupported {
return rrc.helloError("ClientHello does not support session tickets", true)
return rrc.helloError("ClientHello does not support session tickets")
}

if len(helloMsg.SessionTicket) == 0 {
return rrc.helloError("ClientHello has no session ticket", true)
return rrc.helloError("ClientHello has no session ticket")
}

plainText, _ := utls.DecryptTicketWith(helloMsg.SessionTicket, rrc.ticketKeys)
if len(plainText) == 0 {
return rrc.helloError("ClientHello has invalid session ticket", true)
uss, err := rrc.utlsCfg.DecryptTicket(helloMsg.SessionTicket, utls.ConnectionState{})
if err != nil || uss == nil {
return rrc.helloError("ClientHello has invalid session ticket")
}

return nil, nil
}

func (rrc *clientHelloRecordingConn) helloError(errStr string, continueOnError bool) (*tls.Config, error) {
func (rrc *clientHelloRecordingConn) helloError(errStr string) (*tls.Config, error) {
sourceIP := rrc.RemoteAddr().(*net.TCPAddr).IP
rrc.probingError = errStr
rrc.instrument.SuspectedProbing(context.Background(), sourceIP, errStr)
// For now, we just record that there was a problem with the client hello, but we actually
// proceed as if everything is fine.
// See https://github.com/getlantern/engineering/issues/292#issuecomment-1765268377
if continueOnError {
return nil, nil
}
if rrc.missingTicketReaction.handleConn != nil {
rrc.missingTicketReaction.handleConn(rrc)
// at this point the connection has already been closed, returning
Expand Down
85 changes: 42 additions & 43 deletions tlslistener/clienthelloconn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,47 +61,43 @@ func TestAbortOnHello(t *testing.T) {

cfg := &tls.Config{ServerName: "microsoft.com", InsecureSkipVerify: true}
conn, err := tls.Dial("tcp", l.Addr().String(), cfg)
// For now, we expect this to work always, even when we're missing a session ticket
// See https://github.com/getlantern/engineering/issues/292#issuecomment-1765268377
if tc.expectedErr != "" {
require.Error(t, err)
require.Equal(t, tc.expectedErr, err.Error())
} else {
require.NoError(t, err)
defer conn.Close()
require.Equal(t, "microsoft.com", conn.ConnectionState().PeerCertificates[0].Subject.CommonName)
req, _ := http.NewRequest("GET", "https://microsoft.com", nil)
require.NoError(t, req.Write(conn))
resp, err := http.ReadResponse(bufio.NewReader(conn), req)
require.NoError(t, err)
require.Equal(t, http.StatusMovedPermanently, resp.StatusCode)
}

// Now make sure we can't spoof a session ticket.
rawConn, err := net.Dial("tcp", l.Addr().String())
require.NoError(t, err)
conn.Close()
// if tc.expectedErr != "" {
// require.Error(t, err)
// require.Equal(t, tc.expectedErr, err.Error())
// } else {
// require.NoError(t, err)
// defer conn.Close()
// require.Equal(t, "microsoft.com", conn.ConnectionState().PeerCertificates[0].Subject.CommonName)
// req, _ := http.NewRequest("GET", "https://microsoft.com", nil)
// require.NoError(t, req.Write(conn))
// resp, err := http.ReadResponse(bufio.NewReader(conn), req)
// require.NoError(t, err)
// require.Equal(t, http.StatusMovedPermanently, resp.StatusCode)
// }

// // Now make sure we can't spoof a session ticket.
// rawConn, err := net.Dial("tcp", l.Addr().String())
// require.NoError(t, err)
// ucfg := &utls.Config{ServerName: "microsoft.com"}
// maintainSessionTicketKeyFile("../test/testtickets", "",
// func(keys [][32]byte) { ucfg.SetSessionTicketKeys(keys) })
// ss := &utls.ClientSessionState{}
// ticket := make([]byte, 120)
// rand.Read(ticket)
// ss.SetSessionTicket(ticket)
// ss.SetVers(tls.VersionTLS12)

// uconn := utls.UClient(rawConn, ucfg, utls.HelloChrome_Auto)
// uconn.SetSessionState(ss)
// err = uconn.Handshake()
// if tc.expectedErr != "" {
// require.Error(t, err)
// require.Equal(t, tc.expectedErr, err.Error(), tc.response.action)
// } else {
// require.NoError(t, err)
// defer conn.Close()
// require.Equal(t, "microsoft.com", uconn.ConnectionState().PeerCertificates[0].Subject.CommonName)
// }
ucfg := &utls.Config{ServerName: "microsoft.com"}
maintainSessionTicketKeyFile("../test/testtickets", "",
func(keys [][32]byte) { ucfg.SetSessionTicketKeys(keys) })
ss := &utls.ClientSessionState{}
ticket := make([]byte, 120)
rand.Read(ticket)
ss.SetSessionTicket(ticket)
ss.SetVers(tls.VersionTLS12)

uconn := utls.UClient(rawConn, ucfg, utls.HelloChrome_Auto)
uconn.SetSessionState(ss)
err = uconn.Handshake()
if tc.expectedErr != "" {
require.Error(t, err)
require.Equal(t, tc.expectedErr, err.Error(), tc.response.action)
} else {
require.NoError(t, err)
defer conn.Close()
require.Equal(t, "microsoft.com", uconn.ConnectionState().PeerCertificates[0].Subject.CommonName)
}
})
}
}
Expand Down Expand Up @@ -144,7 +140,7 @@ func TestSuccess(t *testing.T) {
// Dial once to obtain a valid session ticket (this is works because we're dialing localhost)
ucfg := &utls.Config{
InsecureSkipVerify: true,
// ClientSessionCache: utls.NewLRUClientSessionCache(10),
ClientSessionCache: utls.NewLRUClientSessionCache(10),
}
conn, err := utls.Dial("tcp", l.Addr().String(), ucfg)
require.NoError(t, err)
Expand Down Expand Up @@ -174,6 +170,9 @@ func TestParseInvalidTicket(t *testing.T) {
rand.Read(tk[:])
ticket := make([]byte, 120)
rand.Read(ticket)
plainText, _ := utls.DecryptTicketWith(ticket, utls.TicketKeys{utls.TicketKeyFromBytes(tk)})
require.Len(t, plainText, 0)

utlsConfig := &utls.Config{}
utlsConfig.SetSessionTicketKeys([][32]byte{tk})
uss, _ := utlsConfig.DecryptTicket(ticket, utls.ConnectionState{})
require.Nil(t, uss)
}
Loading