Skip to content

Commit 2146d42

Browse files
authored
Merge pull request #232 from SenseUnit/alpn_for_utls
Handle ALPN for uTLS connections properly
2 parents 2d0bc36 + ee59a07 commit 2146d42

1 file changed

Lines changed: 33 additions & 9 deletions

File tree

‎dialer/h2.go‎

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ import (
1414
"strings"
1515
"time"
1616

17-
"github.com/SenseUnit/dumbproxy/tlsutil"
17+
utls "github.com/refraction-networking/utls"
1818
"golang.org/x/net/http2"
1919
xproxy "golang.org/x/net/proxy"
20+
21+
"github.com/SenseUnit/dumbproxy/tlsutil"
2022
)
2123

2224
type h1RedeemError struct {
23-
conn *tls.Conn
25+
conn net.Conn
2426
}
2527

2628
const alpnNegErrorText = "HTTP/2 was not negotiated via ALPN"
@@ -50,6 +52,18 @@ func h1FallbackFromContext(ctx context.Context) bool {
5052
return h1Fallback
5153
}
5254

55+
type handshaker interface {
56+
HandshakeContext(context.Context) error
57+
}
58+
59+
type connStater interface {
60+
ConnectionState() tls.ConnectionState
61+
}
62+
63+
type utlsConnStater interface {
64+
ConnectionState() utls.ConnectionState
65+
}
66+
5367
type H2ProxyDialer struct {
5468
address string
5569
tlsConfig *tls.Config
@@ -185,19 +199,29 @@ func H2ProxyDialerFromURL(u *url.URL, next xproxy.Dialer) (xproxy.Dialer, error)
185199
ctc.NextProtos = append(ctc.NextProtos[0:len(ctc.NextProtos):len(ctc.NextProtos)], "http/1.1")
186200
}
187201
conn = tlsFactory(conn, ctc)
188-
if tlsConn, ok := conn.(*tls.Conn); ok {
189-
// it's a crypto/tls connection, we ought to see how ALPN went
190-
if err := tlsConn.HandshakeContext(ctx); err != nil {
191-
tlsConn.Close()
202+
if hs, ok := conn.(handshaker); ok {
203+
if err := hs.HandshakeContext(ctx); err != nil {
204+
conn.Close()
192205
return nil, err
193206
}
194-
if tlsConn.ConnectionState().NegotiatedProtocol != "h2" {
207+
var negProto string
208+
switch c := conn.(type) {
209+
case connStater:
210+
negProto = c.ConnectionState().NegotiatedProtocol
211+
case utlsConnStater:
212+
negProto = c.ConnectionState().NegotiatedProtocol
213+
default:
214+
// can't access TLS extensions of conn, ALPN is not available
215+
return conn, nil
216+
}
217+
// it's a TLS connection with ALPN, we ought to see how negotiation went
218+
if negProto != "h2" {
195219
if h1Fallback {
196220
// HTTP/2 was NOT negotiated! abort, but save the connection
197221
// for potential redemption via HTTP/1 dialer
198-
return nil, h1RedeemError{tlsConn}
222+
return nil, h1RedeemError{conn}
199223
} else {
200-
tlsConn.Close()
224+
conn.Close()
201225
return nil, errors.New(alpnNegErrorText)
202226
}
203227
}

0 commit comments

Comments
 (0)