Browse Source

Add uTLS ALPN Control

Shelikhoo 2 years ago
parent
commit
7b434ced58
2 changed files with 19 additions and 3 deletions
  1. 7 0
      transport/internet/tls/utls/config.proto
  2. 12 3
      transport/internet/tls/utls/utls.go

+ 7 - 0
transport/internet/tls/utls/config.proto

@@ -9,6 +9,12 @@ option java_multiple_files = true;
 import "common/protoext/extensions.proto";
 import "common/protoext/extensions.proto";
 import "transport/internet/tls/config.proto";
 import "transport/internet/tls/config.proto";
 
 
+enum ForcedALPN{
+  TRANSPORT_PREFERENCE_TAKE_PRIORITY = 0;
+  NO_ALPN = 1;
+  UTLS_PRESET = 2;
+}
+
 message Config {
 message Config {
   option (v2ray.core.common.protoext.message_opt).type = "security";
   option (v2ray.core.common.protoext.message_opt).type = "security";
   option (v2ray.core.common.protoext.message_opt).short_name = "utls";
   option (v2ray.core.common.protoext.message_opt).short_name = "utls";
@@ -16,4 +22,5 @@ message Config {
   v2ray.core.transport.internet.tls.Config tls_config = 1;
   v2ray.core.transport.internet.tls.Config tls_config = 1;
   string imitate = 2;
   string imitate = 2;
   bool noSNI = 3;
   bool noSNI = 3;
+  ForcedALPN force_alpn = 4;
 }
 }

+ 12 - 3
transport/internet/tls/utls/utls.go

@@ -30,7 +30,9 @@ func (e Engine) Client(conn net.Conn, opts ...security.Option) (security.Conn, e
 	for _, v := range opts {
 	for _, v := range opts {
 		switch s := v.(type) {
 		switch s := v.(type) {
 		case security.OptionWithALPN:
 		case security.OptionWithALPN:
-			options = append(options, tls.WithNextProto(s.ALPNs...))
+			if e.config.ForceAlpn == ForcedALPN_TRANSPORT_PREFERENCE_TAKE_PRIORITY {
+				options = append(options, tls.WithNextProto(s.ALPNs...))
+			}
 		case security.OptionWithDestination:
 		case security.OptionWithDestination:
 			options = append(options, tls.WithDestination(s.Dest))
 			options = append(options, tls.WithDestination(s.Dest))
 		default:
 		default:
@@ -65,9 +67,16 @@ func (e Engine) Client(conn net.Conn, opts ...security.Option) (security.Conn, e
 	// ALPN is necessary for protocols like websocket to work. The uTLS setting may be overwritten on call into
 	// ALPN is necessary for protocols like websocket to work. The uTLS setting may be overwritten on call into
 	// BuildHandshakeState, so we need to check the original tls settings.
 	// BuildHandshakeState, so we need to check the original tls settings.
 	if tlsConfig.NextProtos != nil {
 	if tlsConfig.NextProtos != nil {
-		for _, v := range utlsClientConn.Extensions {
+		for n, v := range utlsClientConn.Extensions {
 			if aplnExtension, ok := v.(*utls.ALPNExtension); ok {
 			if aplnExtension, ok := v.(*utls.ALPNExtension); ok {
-				aplnExtension.AlpnProtocols = tlsConfig.NextProtos
+				if e.config.ForceAlpn == ForcedALPN_TRANSPORT_PREFERENCE_TAKE_PRIORITY {
+					aplnExtension.AlpnProtocols = tlsConfig.NextProtos
+					break
+				}
+				if e.config.ForceAlpn == ForcedALPN_NO_ALPN {
+					utlsClientConn.Extensions = append(utlsClientConn.Extensions[:n], utlsClientConn.Extensions[n+1:]...)
+					break
+				}
 			}
 			}
 		}
 		}
 	}
 	}