Browse Source

feat: use security engine in h2 transport
This will enable uTLS support for h2 transport.

pathC 2 years ago
parent
commit
21b7a0046b
2 changed files with 24 additions and 16 deletions
  1. 23 15
      transport/internet/http/dialer.go
  2. 1 1
      transport/internet/tls/tls.go

+ 23 - 15
transport/internet/http/dialer.go

@@ -3,6 +3,7 @@ package http
 import (
 import (
 	"context"
 	"context"
 	gotls "crypto/tls"
 	gotls "crypto/tls"
+	gonet "net"
 	"net/http"
 	"net/http"
 	"net/url"
 	"net/url"
 	"sync"
 	"sync"
@@ -14,7 +15,7 @@ import (
 	"github.com/v2fly/v2ray-core/v5/common/buf"
 	"github.com/v2fly/v2ray-core/v5/common/buf"
 	"github.com/v2fly/v2ray-core/v5/common/net"
 	"github.com/v2fly/v2ray-core/v5/common/net"
 	"github.com/v2fly/v2ray-core/v5/transport/internet"
 	"github.com/v2fly/v2ray-core/v5/transport/internet"
-	"github.com/v2fly/v2ray-core/v5/transport/internet/tls"
+	"github.com/v2fly/v2ray-core/v5/transport/internet/security"
 	"github.com/v2fly/v2ray-core/v5/transport/pipe"
 	"github.com/v2fly/v2ray-core/v5/transport/pipe"
 )
 )
 
 
@@ -25,7 +26,7 @@ var (
 
 
 type dialerCanceller func()
 type dialerCanceller func()
 
 
-func getHTTPClient(ctx context.Context, dest net.Destination, tlsSettings *tls.Config, streamSettings *internet.MemoryStreamConfig) (*http.Client, dialerCanceller) {
+func getHTTPClient(ctx context.Context, dest net.Destination, securityEngine *security.Engine, streamSettings *internet.MemoryStreamConfig) (*http.Client, dialerCanceller) {
 	globalDialerAccess.Lock()
 	globalDialerAccess.Lock()
 	defer globalDialerAccess.Unlock()
 	defer globalDialerAccess.Unlock()
 
 
@@ -44,7 +45,7 @@ func getHTTPClient(ctx context.Context, dest net.Destination, tlsSettings *tls.C
 	}
 	}
 
 
 	transport := &http2.Transport{
 	transport := &http2.Transport{
-		DialTLS: func(network string, addr string, tlsConfig *gotls.Config) (net.Conn, error) {
+		DialTLSContext: func(ctx context.Context, network, addr string, tlsConfig *gotls.Config) (gonet.Conn, error) {
 			rawHost, rawPort, err := net.SplitHostPort(addr)
 			rawHost, rawPort, err := net.SplitHostPort(addr)
 			if err != nil {
 			if err != nil {
 				return nil, err
 				return nil, err
@@ -64,22 +65,26 @@ func getHTTPClient(ctx context.Context, dest net.Destination, tlsSettings *tls.C
 				return nil, err
 				return nil, err
 			}
 			}
 
 
-			cn := gotls.Client(pconn, tlsConfig)
-			if err := cn.Handshake(); err != nil {
+			cn, err := (*securityEngine).Client(pconn,
+				security.OptionWithDestination{Dest: dest})
+			if err != nil {
 				return nil, err
 				return nil, err
 			}
 			}
-			if !tlsConfig.InsecureSkipVerify {
-				if err := cn.VerifyHostname(tlsConfig.ServerName); err != nil {
-					return nil, err
+
+			protocol := ""
+			if connAPLNGetter, ok := cn.(security.ConnectionApplicationProtocol); ok {
+				connectionALPN, err := connAPLNGetter.GetConnectionApplicationProtocol()
+				if err != nil {
+					return nil, newError("failed to get connection ALPN").Base(err).AtWarning()
 				}
 				}
+				protocol = connectionALPN
 			}
 			}
-			state := cn.ConnectionState()
-			if p := state.NegotiatedProtocol; p != http2.NextProtoTLS {
-				return nil, newError("http2: unexpected ALPN protocol " + p + "; want q" + http2.NextProtoTLS).AtError()
+
+			if protocol != http2.NextProtoTLS {
+				return nil, newError("http2: unexpected ALPN protocol " + protocol + "; want q" + http2.NextProtoTLS).AtError()
 			}
 			}
 			return cn, nil
 			return cn, nil
 		},
 		},
-		TLSClientConfig: tlsSettings.GetTLSConfig(tls.WithDestination(dest)),
 	}
 	}
 
 
 	client := &http.Client{
 	client := &http.Client{
@@ -93,11 +98,14 @@ func getHTTPClient(ctx context.Context, dest net.Destination, tlsSettings *tls.C
 // Dial dials a new TCP connection to the given destination.
 // Dial dials a new TCP connection to the given destination.
 func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (internet.Connection, error) {
 func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (internet.Connection, error) {
 	httpSettings := streamSettings.ProtocolSettings.(*Config)
 	httpSettings := streamSettings.ProtocolSettings.(*Config)
-	tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
-	if tlsConfig == nil {
+	securityEngine, err := security.CreateSecurityEngineFromSettings(ctx, streamSettings)
+	if err != nil {
+		return nil, newError("unable to create security engine").Base(err)
+	}
+	if securityEngine == nil {
 		return nil, newError("TLS must be enabled for http transport.").AtWarning()
 		return nil, newError("TLS must be enabled for http transport.").AtWarning()
 	}
 	}
-	client, canceller := getHTTPClient(ctx, dest, tlsConfig, streamSettings)
+	client, canceller := getHTTPClient(ctx, dest, &securityEngine, streamSettings)
 
 
 	opts := pipe.OptionsFromContext(ctx)
 	opts := pipe.OptionsFromContext(ctx)
 	preader, pwriter := pipe.New(opts...)
 	preader, pwriter := pipe.New(opts...)

+ 1 - 1
transport/internet/tls/tls.go

@@ -43,7 +43,7 @@ func (c *Conn) HandshakeAddress() net.Address {
 }
 }
 
 
 // Client initiates a TLS client handshake on the given connection.
 // Client initiates a TLS client handshake on the given connection.
-func Client(c net.Conn, config *tls.Config) net.Conn {
+func Client(c net.Conn, config *tls.Config) *Conn {
 	tlsConn := tls.Client(c, config)
 	tlsConn := tls.Client(c, config)
 	return &Conn{Conn: tlsConn}
 	return &Conn{Conn: tlsConn}
 }
 }