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

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