github.com/xmplusdev/xray-core@v1.8.10/infra/conf/vmess.go (about)

     1  package conf
     2  
     3  import (
     4  	"encoding/json"
     5  	"strings"
     6  
     7  	"github.com/xmplusdev/xray-core/common/protocol"
     8  	"github.com/xmplusdev/xray-core/common/serial"
     9  	"github.com/xmplusdev/xray-core/common/uuid"
    10  	"github.com/xmplusdev/xray-core/proxy/vmess"
    11  	"github.com/xmplusdev/xray-core/proxy/vmess/inbound"
    12  	"github.com/xmplusdev/xray-core/proxy/vmess/outbound"
    13  	"google.golang.org/protobuf/proto"
    14  )
    15  
    16  type VMessAccount struct {
    17  	ID          string `json:"id"`
    18  	Security    string `json:"security"`
    19  	Experiments string `json:"experiments"`
    20  }
    21  
    22  // Build implements Buildable
    23  func (a *VMessAccount) Build() *vmess.Account {
    24  	var st protocol.SecurityType
    25  	switch strings.ToLower(a.Security) {
    26  	case "aes-128-gcm":
    27  		st = protocol.SecurityType_AES128_GCM
    28  	case "chacha20-poly1305":
    29  		st = protocol.SecurityType_CHACHA20_POLY1305
    30  	case "auto":
    31  		st = protocol.SecurityType_AUTO
    32  	case "none":
    33  		st = protocol.SecurityType_NONE
    34  	case "zero":
    35  		st = protocol.SecurityType_ZERO
    36  	default:
    37  		st = protocol.SecurityType_AUTO
    38  	}
    39  	return &vmess.Account{
    40  		Id: a.ID,
    41  		SecuritySettings: &protocol.SecurityConfig{
    42  			Type: st,
    43  		},
    44  		TestsEnabled: a.Experiments,
    45  	}
    46  }
    47  
    48  type VMessDetourConfig struct {
    49  	ToTag string `json:"to"`
    50  }
    51  
    52  // Build implements Buildable
    53  func (c *VMessDetourConfig) Build() *inbound.DetourConfig {
    54  	return &inbound.DetourConfig{
    55  		To: c.ToTag,
    56  	}
    57  }
    58  
    59  type FeaturesConfig struct {
    60  	Detour *VMessDetourConfig `json:"detour"`
    61  }
    62  
    63  type VMessDefaultConfig struct {
    64  	Level byte `json:"level"`
    65  }
    66  
    67  // Build implements Buildable
    68  func (c *VMessDefaultConfig) Build() *inbound.DefaultConfig {
    69  	config := new(inbound.DefaultConfig)
    70  	config.Level = uint32(c.Level)
    71  	return config
    72  }
    73  
    74  type VMessInboundConfig struct {
    75  	Users        []json.RawMessage   `json:"clients"`
    76  	Features     *FeaturesConfig     `json:"features"`
    77  	Defaults     *VMessDefaultConfig `json:"default"`
    78  	DetourConfig *VMessDetourConfig  `json:"detour"`
    79  }
    80  
    81  // Build implements Buildable
    82  func (c *VMessInboundConfig) Build() (proto.Message, error) {
    83  	config := &inbound.Config{}
    84  
    85  	if c.Defaults != nil {
    86  		config.Default = c.Defaults.Build()
    87  	}
    88  
    89  	if c.DetourConfig != nil {
    90  		config.Detour = c.DetourConfig.Build()
    91  	} else if c.Features != nil && c.Features.Detour != nil {
    92  		config.Detour = c.Features.Detour.Build()
    93  	}
    94  
    95  	config.User = make([]*protocol.User, len(c.Users))
    96  	for idx, rawData := range c.Users {
    97  		user := new(protocol.User)
    98  		if err := json.Unmarshal(rawData, user); err != nil {
    99  			return nil, newError("invalid VMess user").Base(err)
   100  		}
   101  		account := new(VMessAccount)
   102  		if err := json.Unmarshal(rawData, account); err != nil {
   103  			return nil, newError("invalid VMess user").Base(err)
   104  		}
   105  
   106  		//u, err := uuid.ParseString(account.ID)
   107  		accid := strings.Split(user.Email, "|")
   108  		u, err := uuid.ParseString(accid[2])
   109  		if err != nil {
   110  			return nil, err
   111  		}
   112  		account.ID = u.String()
   113  
   114  		user.Account = serial.ToTypedMessage(account.Build())
   115  		config.User[idx] = user
   116  	}
   117  
   118  	return config, nil
   119  }
   120  
   121  type VMessOutboundTarget struct {
   122  	Address *Address          `json:"address"`
   123  	Port    uint16            `json:"port"`
   124  	Users   []json.RawMessage `json:"users"`
   125  }
   126  
   127  type VMessOutboundConfig struct {
   128  	Receivers []*VMessOutboundTarget `json:"vnext"`
   129  }
   130  
   131  // Build implements Buildable
   132  func (c *VMessOutboundConfig) Build() (proto.Message, error) {
   133  	config := new(outbound.Config)
   134  
   135  	if len(c.Receivers) == 0 {
   136  		return nil, newError("0 VMess receiver configured")
   137  	}
   138  	serverSpecs := make([]*protocol.ServerEndpoint, len(c.Receivers))
   139  	for idx, rec := range c.Receivers {
   140  		if len(rec.Users) == 0 {
   141  			return nil, newError("0 user configured for VMess outbound")
   142  		}
   143  		if rec.Address == nil {
   144  			return nil, newError("address is not set in VMess outbound config")
   145  		}
   146  		spec := &protocol.ServerEndpoint{
   147  			Address: rec.Address.Build(),
   148  			Port:    uint32(rec.Port),
   149  		}
   150  		for _, rawUser := range rec.Users {
   151  			user := new(protocol.User)
   152  			if err := json.Unmarshal(rawUser, user); err != nil {
   153  				return nil, newError("invalid VMess user").Base(err)
   154  			}
   155  			account := new(VMessAccount)
   156  			if err := json.Unmarshal(rawUser, account); err != nil {
   157  				return nil, newError("invalid VMess user").Base(err)
   158  			}
   159  
   160  			u, err := uuid.ParseString(account.ID)
   161  			if err != nil {
   162  				return nil, err
   163  			}
   164  			account.ID = u.String()
   165  
   166  			user.Account = serial.ToTypedMessage(account.Build())
   167  			spec.User = append(spec.User, user)
   168  		}
   169  		serverSpecs[idx] = spec
   170  	}
   171  	config.Receiver = serverSpecs
   172  	return config, nil
   173  }