diff --git a/transport/internet/tls/utls/config.proto b/transport/internet/tls/utls/config.proto index 33557a4b8..0b5702f67 100644 --- a/transport/internet/tls/utls/config.proto +++ b/transport/internet/tls/utls/config.proto @@ -9,6 +9,12 @@ option java_multiple_files = true; import "common/protoext/extensions.proto"; import "transport/internet/tls/config.proto"; +enum ForcedALPN{ + TRANSPORT_PREFERENCE_TAKE_PRIORITY = 0; + NO_ALPN = 1; + UTLS_PRESET = 2; +} + message Config { option (v2ray.core.common.protoext.message_opt).type = "security"; 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; string imitate = 2; bool noSNI = 3; + ForcedALPN force_alpn = 4; } \ No newline at end of file diff --git a/transport/internet/tls/utls/utls.go b/transport/internet/tls/utls/utls.go index d6071a243..29349fbda 100644 --- a/transport/internet/tls/utls/utls.go +++ b/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 { switch s := v.(type) { 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: options = append(options, tls.WithDestination(s.Dest)) 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 // BuildHandshakeState, so we need to check the original tls settings. if tlsConfig.NextProtos != nil { - for _, v := range utlsClientConn.Extensions { + for n, v := range utlsClientConn.Extensions { 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 + } } } }