utls.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package utls
  2. import (
  3. "context"
  4. systls "crypto/tls"
  5. utls "github.com/refraction-networking/utls"
  6. "github.com/v2fly/v2ray-core/v5/common"
  7. "github.com/v2fly/v2ray-core/v5/common/net"
  8. "github.com/v2fly/v2ray-core/v5/transport/internet/security"
  9. "github.com/v2fly/v2ray-core/v5/transport/internet/tls"
  10. )
  11. //go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen
  12. func NewUTLSSecurityEngineFromConfig(config *Config) (security.Engine, error) {
  13. if config.TlsConfig == nil {
  14. return nil, newError("mandatory field tls_config is not specified")
  15. }
  16. return &Engine{config: config}, nil
  17. }
  18. type Engine struct {
  19. config *Config
  20. }
  21. func (e Engine) Client(conn net.Conn, opts ...security.Option) (security.Conn, error) {
  22. var options []tls.Option
  23. for _, v := range opts {
  24. switch s := v.(type) {
  25. case security.OptionWithALPN:
  26. options = append(options, tls.WithNextProto(s.ALPNs...))
  27. case security.OptionWithDestination:
  28. options = append(options, tls.WithDestination(s.Dest))
  29. default:
  30. return nil, newError("unknown option")
  31. }
  32. }
  33. tlsConfig := e.config.TlsConfig.GetTLSConfig(options...)
  34. utlsConfig, err := uTLSConfigFromTLSConfig(tlsConfig)
  35. if err != nil {
  36. return nil, newError("unable to generate utls config from tls config").Base(err)
  37. }
  38. preset, err := nameToUTLSPreset(e.config.Imitate)
  39. if err != nil {
  40. return nil, newError("unable to get utls preset from name").Base(err)
  41. }
  42. utlsClientConn := utls.UClient(conn, utlsConfig, *preset)
  43. if e.config.NoSNI {
  44. err = utlsClientConn.RemoveSNIExtension()
  45. if err != nil {
  46. return nil, newError("unable to remove server name indication from utls client hello").Base(err)
  47. }
  48. }
  49. err = utlsClientConn.BuildHandshakeState()
  50. if err != nil {
  51. return nil, newError("unable to build utls handshake state").Base(err)
  52. }
  53. // ALPN is necessary for protocols like websocket to work. The uTLS setting may be overwritten on call into
  54. // BuildHandshakeState, so we need to check the original tls settings.
  55. if tlsConfig.NextProtos != nil {
  56. for _, v := range utlsClientConn.Extensions {
  57. if aplnExtension, ok := v.(*utls.ALPNExtension); ok {
  58. aplnExtension.AlpnProtocols = tlsConfig.NextProtos
  59. }
  60. }
  61. }
  62. err = utlsClientConn.BuildHandshakeState()
  63. if err != nil {
  64. return nil, newError("unable to build utls handshake state after modification").Base(err)
  65. }
  66. err = utlsClientConn.Handshake()
  67. if err != nil {
  68. return nil, newError("unable to finish utls handshake").Base(err)
  69. }
  70. return utlsClientConn, nil
  71. }
  72. func uTLSConfigFromTLSConfig(config *systls.Config) (*utls.Config, error) { // nolint: unparam
  73. uconfig := &utls.Config{
  74. Rand: config.Rand,
  75. Time: config.Time,
  76. RootCAs: config.RootCAs,
  77. NextProtos: config.NextProtos,
  78. ServerName: config.ServerName,
  79. }
  80. return uconfig, nil
  81. }
  82. func init() {
  83. common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
  84. return NewUTLSSecurityEngineFromConfig(config.(*Config))
  85. }))
  86. }