示例#1
0
func New(ctx context.Context, config *Config) (*VMessInboundHandler, error) {
	space := app.SpaceFromContext(ctx)
	if space == nil {
		return nil, errors.New("VMess|Inbound: No space in context.")
	}

	allowedClients := vmess.NewTimedUserValidator(protocol.DefaultIDHash)
	for _, user := range config.User {
		allowedClients.Add(user)
	}

	handler := &VMessInboundHandler{
		clients:      allowedClients,
		detours:      config.Detour,
		usersByEmail: NewUserByEmail(config.User, config.GetDefaultValue()),
	}

	space.OnInitialize(func() error {
		handler.packetDispatcher = dispatcher.FromSpace(space)
		if handler.packetDispatcher == nil {
			return errors.New("VMess|Inbound: Dispatcher is not found in space.")
		}
		handler.inboundHandlerManager = proxyman.InboundHandlerManagerFromSpace(space)
		if handler.inboundHandlerManager == nil {
			return errors.New("VMess|Inbound: InboundHandlerManager is not found is space.")
		}
		return nil
	})

	return handler, nil
}
示例#2
0
func Dial(ctx context.Context, dest v2net.Destination) (Connection, error) {
	if dest.Network == v2net.Network_TCP {
		streamSettings, _ := StreamSettingsFromContext(ctx)
		protocol := streamSettings.GetEffectiveProtocol()
		transportSettings, err := streamSettings.GetEffectiveTransportSettings()
		if err != nil {
			return nil, err
		}
		ctx = ContextWithTransportSettings(ctx, transportSettings)
		if streamSettings != nil && streamSettings.HasSecuritySettings() {
			securitySettings, err := streamSettings.GetEffectiveSecuritySettings()
			if err != nil {
				return nil, err
			}
			ctx = ContextWithSecuritySettings(ctx, securitySettings)
		}
		dialer := transportDialerCache[protocol]
		if dialer == nil {
			return nil, errors.New("Internet|Dialer: ", protocol, " dialer not registered.")
		}
		return dialer(ctx, dest)
	}

	udpDialer := transportDialerCache[TransportProtocol_UDP]
	if udpDialer == nil {
		return nil, errors.New("Internet|Dialer: UDP dialer not registered.")
	}
	return udpDialer(ctx, dest)
}
示例#3
0
func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
	space := app.SpaceFromContext(ctx)
	if space == nil {
		return nil, errors.New("Shadowsocks|Server: No space in context.")
	}
	if config.GetUser() == nil {
		return nil, protocol.ErrUserMissing
	}

	rawAccount, err := config.User.GetTypedAccount()
	if err != nil {
		return nil, errors.Base(err).Message("Shadowsocks|Server: Failed to get user account.")
	}
	account := rawAccount.(*ShadowsocksAccount)

	s := &Server{
		config:  config,
		user:    config.GetUser(),
		account: account,
	}

	space.OnInitialize(func() error {
		s.packetDispatcher = dispatcher.FromSpace(space)
		if s.packetDispatcher == nil {
			return errors.New("Shadowsocks|Server: Dispatcher is not found in space.")
		}
		return nil
	})

	return s, nil
}
示例#4
0
func NewRouter(ctx context.Context, config *Config) (*Router, error) {
	space := app.SpaceFromContext(ctx)
	if space == nil {
		return nil, errors.New("Router: No space in context.")
	}
	r := &Router{
		domainStrategy: config.DomainStrategy,
		rules:          make([]Rule, len(config.Rule)),
	}

	space.OnInitialize(func() error {
		for idx, rule := range config.Rule {
			r.rules[idx].Tag = rule.Tag
			cond, err := rule.BuildCondition()
			if err != nil {
				return err
			}
			r.rules[idx].Condition = cond
		}

		r.dnsServer = dns.FromSpace(space)
		if r.dnsServer == nil {
			return errors.New("Router: DNS is not found in the space.")
		}
		return nil
	})
	return r, nil
}
示例#5
0
func (v *ShadowsocksClientConfig) Build() (*serial.TypedMessage, error) {
	config := new(shadowsocks.ClientConfig)

	if len(v.Servers) == 0 {
		return nil, errors.New("0 Shadowsocks server configured.")
	}

	serverSpecs := make([]*protocol.ServerEndpoint, len(v.Servers))
	for idx, server := range v.Servers {
		if server.Address == nil {
			return nil, errors.New("Shadowsocks server address is not set.")
		}
		if server.Port == 0 {
			return nil, errors.New("Invalid Shadowsocks port.")
		}
		if len(server.Password) == 0 {
			return nil, errors.New("Shadowsocks password is not specified.")
		}
		account := &shadowsocks.Account{
			Password: server.Password,
			Ota:      shadowsocks.Account_Enabled,
		}
		if !server.Ota {
			account.Ota = shadowsocks.Account_Disabled
		}
		cipher := strings.ToLower(server.Cipher)
		switch cipher {
		case "aes-256-cfb":
			account.CipherType = shadowsocks.CipherType_AES_256_CFB
		case "aes-128-cfb":
			account.CipherType = shadowsocks.CipherType_AES_128_CFB
		case "chacha20":
			account.CipherType = shadowsocks.CipherType_CHACHA20
		case "chacha20-ietf":
			account.CipherType = shadowsocks.CipherType_CHACHA20_IEFT
		default:
			return nil, errors.New("Unknown cipher method: " + cipher)
		}

		ss := &protocol.ServerEndpoint{
			Address: server.Address.Build(),
			Port:    uint32(server.Port),
			User: []*protocol.User{
				{
					Email:   server.Email,
					Account: serial.ToTypedMessage(account),
				},
			},
		}

		serverSpecs[idx] = ss
	}

	config.Server = serverSpecs

	return serial.ToTypedMessage(config), nil
}
示例#6
0
文件: udp.go 项目: v2ray/v2ray-core
func ReadUDPRequest(packet []byte) (*Socks5UDPRequest, error) {
	if len(packet) < 5 {
		return nil, errors.New("Socks|UDP: Insufficient length of packet.")
	}
	request := new(Socks5UDPRequest)

	// packet[0] and packet[1] are reserved
	request.Fragment = packet[2]

	addrType := packet[3]
	var dataBegin int

	switch addrType {
	case AddrTypeIPv4:
		if len(packet) < 10 {
			return nil, errors.New("Socks|UDP: Insufficient length of packet.")
		}
		ip := packet[4:8]
		request.Port = v2net.PortFromBytes(packet[8:10])
		request.Address = v2net.IPAddress(ip)
		dataBegin = 10
	case AddrTypeIPv6:
		if len(packet) < 22 {
			return nil, errors.New("Socks|UDP: Insufficient length of packet.")
		}
		ip := packet[4:20]
		request.Port = v2net.PortFromBytes(packet[20:22])
		request.Address = v2net.IPAddress(ip)
		dataBegin = 22
	case AddrTypeDomain:
		domainLength := int(packet[4])
		if len(packet) < 5+domainLength+2 {
			return nil, errors.New("Socks|UDP: Insufficient length of packet.")
		}
		domain := string(packet[5 : 5+domainLength])
		request.Port = v2net.PortFromBytes(packet[5+domainLength : 5+domainLength+2])
		request.Address = v2net.ParseAddress(domain)
		dataBegin = 5 + domainLength + 2
	default:
		return nil, errors.Format("Socks|UDP: Unknown address type %d", addrType)
	}

	if len(packet) > dataBegin {
		b := buf.NewSmall()
		b.Append(packet[dataBegin:])
		request.Data = b
	}

	return request, nil
}
示例#7
0
func (v *InboundDetourConfig) Build() (*proxyman.InboundHandlerConfig, error) {
	receiverSettings := &proxyman.ReceiverConfig{
		AllowPassiveConnection: v.AllowPassive,
	}

	if v.PortRange == nil {
		return nil, errors.New("Port range not specified in InboundDetour.")
	}
	receiverSettings.PortRange = v.PortRange.Build()

	if v.ListenOn != nil {
		if v.ListenOn.Family().IsDomain() {
			return nil, errors.New("Unable to listen on domain address: ", v.ListenOn.Domain())
		}
		receiverSettings.Listen = v.ListenOn.Build()
	}
	if v.Allocation != nil {
		as, err := v.Allocation.Build()
		if err != nil {
			return nil, err
		}
		receiverSettings.AllocationStrategy = as
	}
	if v.StreamSetting != nil {
		ss, err := v.StreamSetting.Build()
		if err != nil {
			return nil, err
		}
		receiverSettings.StreamSettings = ss
	}

	rawConfig, err := inboundConfigLoader.LoadWithID(v.Settings, v.Protocol)
	if err != nil {
		return nil, errors.Base(err).Message("Failed to load inbound detour config.")
	}
	if dokodemoConfig, ok := rawConfig.(*DokodemoConfig); ok {
		receiverSettings.ReceiveOriginalDestination = dokodemoConfig.Redirect
	}
	ts, err := rawConfig.(Buildable).Build()
	if err != nil {
		return nil, err
	}

	return &proxyman.InboundHandlerConfig{
		Tag:              v.Tag,
		ReceiverSettings: serial.ToTypedMessage(receiverSettings),
		ProxySettings:    ts,
	}, nil
}
示例#8
0
func (m *DefaultInboundHandlerManager) GetHandler(ctx context.Context, tag string) (proxyman.InboundHandler, error) {
	handler, found := m.taggedHandlers[tag]
	if !found {
		return nil, errors.New("Proxymand|DefaultInboundHandlerManager: Handler not found: ", tag)
	}
	return handler, nil
}
示例#9
0
func RegisterTransportDialer(protocol TransportProtocol, dialer Dialer) error {
	if _, found := transportDialerCache[protocol]; found {
		return errors.New("Internet|Dialer: ", protocol, " dialer already registered.")
	}
	transportDialerCache[protocol] = dialer
	return nil
}
示例#10
0
func NewCacheServer(space app.Space, config *dns.Config) *CacheServer {
	server := &CacheServer{
		records: make(map[string]*DomainRecord),
		servers: make([]NameServer, len(config.NameServers)),
		hosts:   config.GetInternalHosts(),
	}
	space.InitializeApplication(func() error {
		if !space.HasApp(dispatcher.APP_ID) {
			return errors.New("DNS: Dispatcher is not found in the space.")
		}

		dispatcher := space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
		for idx, destPB := range config.NameServers {
			address := destPB.Address.AsAddress()
			if address.Family().IsDomain() && address.Domain() == "localhost" {
				server.servers[idx] = &LocalNameServer{}
			} else {
				dest := destPB.AsDestination()
				if dest.Network == v2net.Network_Unknown {
					dest.Network = v2net.Network_UDP
				}
				if dest.Network == v2net.Network_UDP {
					server.servers[idx] = NewUDPNameServer(dest, dispatcher)
				}
			}
		}
		if len(config.NameServers) == 0 {
			server.servers = append(server.servers, &LocalNameServer{})
		}
		return nil
	})
	return server
}
示例#11
0
func NewRouter(config *Config, space app.Space) *Router {
	r := &Router{
		domainStrategy: config.DomainStrategy,
		//cache:          NewRoutingTable(),
		rules: make([]Rule, len(config.Rule)),
	}

	space.InitializeApplication(func() error {
		for idx, rule := range config.Rule {
			r.rules[idx].Tag = rule.Tag
			cond, err := rule.BuildCondition()
			if err != nil {
				return err
			}
			r.rules[idx].Condition = cond
		}

		if !space.HasApp(dns.APP_ID) {
			return errors.New("Router: DNS is not found in the space.")
		}
		r.dnsServer = space.GetApp(dns.APP_ID).(dns.Server)
		return nil
	})
	return r
}
示例#12
0
文件: ota.go 项目: v2ray/v2ray-core
func (v *ChunkReader) Read() (*buf.Buffer, error) {
	buffer := buf.New()
	if err := buffer.AppendSupplier(buf.ReadFullFrom(v.reader, 2)); err != nil {
		buffer.Release()
		return nil, err
	}
	// There is a potential buffer overflow here. Large buffer is 64K bytes,
	// while uin16 + 10 will be more than that
	length := serial.BytesToUint16(buffer.BytesTo(2)) + AuthSize
	if length > buf.Size {
		// Theoretically the size of a chunk is 64K, but most Shadowsocks implementations used <4K buffer.
		buffer.Release()
		buffer = buf.NewLocal(int(length) + 128)
	}

	buffer.Clear()
	if err := buffer.AppendSupplier(buf.ReadFullFrom(v.reader, int(length))); err != nil {
		buffer.Release()
		return nil, err
	}

	authBytes := buffer.BytesTo(AuthSize)
	payload := buffer.BytesFrom(AuthSize)

	actualAuthBytes := make([]byte, AuthSize)
	v.auth.Authenticate(payload)(actualAuthBytes)
	if !bytes.Equal(authBytes, actualAuthBytes) {
		buffer.Release()
		return nil, errors.New("Shadowsocks|AuthenticationReader: Invalid auth.")
	}
	buffer.SliceFrom(AuthSize)

	return buffer, nil
}
示例#13
0
func CreateTransportConfig(protocol TransportProtocol) (interface{}, error) {
	creator, ok := globalTransportConfigCreatorCache[protocol]
	if !ok {
		return nil, errors.New("Internet: Unknown transport protocol: ", protocol)
	}
	return creator(), nil
}
示例#14
0
文件: socks.go 项目: v2ray/v2ray-core
func (v *SocksServerConfig) Build() (*serial.TypedMessage, error) {
	config := new(socks.ServerConfig)
	if v.AuthMethod == AuthMethodNoAuth {
		config.AuthType = socks.AuthType_NO_AUTH
	} else if v.AuthMethod == AuthMethodUserPass {
		config.AuthType = socks.AuthType_PASSWORD
	} else {
		return nil, errors.New("Unknown socks auth method: " + v.AuthMethod)
	}

	if len(v.Accounts) > 0 {
		config.Accounts = make(map[string]string, len(v.Accounts))
		for _, account := range v.Accounts {
			config.Accounts[account.Username] = account.Password
		}
	}

	config.UdpEnabled = v.UDP
	if v.Host != nil {
		config.Address = v.Host.Build()
	}

	config.Timeout = v.Timeout
	return serial.ToTypedMessage(config), nil
}
示例#15
0
func NewServer(config *ServerConfig, space app.Space, meta *proxy.InboundHandlerMeta) (*Server, error) {
	if config.GetUser() == nil {
		return nil, protocol.ErrUserMissing
	}

	rawAccount, err := config.User.GetTypedAccount()
	if err != nil {
		return nil, errors.Base(err).Message("Shadowsocks|Server: Failed to get user account.")
	}
	account := rawAccount.(*ShadowsocksAccount)

	s := &Server{
		config:  config,
		meta:    meta,
		user:    config.GetUser(),
		account: account,
	}

	space.InitializeApplication(func() error {
		if !space.HasApp(dispatcher.APP_ID) {
			return errors.New("Shadowsocks|Server: Dispatcher is not found in space.")
		}
		s.packetDispatcher = space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
		return nil
	})

	return s, nil
}
示例#16
0
func NewDefaultDispatcher(ctx context.Context, config *dispatcher.Config) (*DefaultDispatcher, error) {
	space := app.SpaceFromContext(ctx)
	if space == nil {
		return nil, errors.New("DefaultDispatcher: No space in context.")
	}
	d := &DefaultDispatcher{}
	space.OnInitialize(func() error {
		d.ohm = proxyman.OutboundHandlerManagerFromSpace(space)
		if d.ohm == nil {
			return errors.New("DefaultDispatcher: OutboundHandlerManager is not found in the space.")
		}
		d.router = router.FromSpace(space)
		return nil
	})
	return d, nil
}
示例#17
0
文件: v2ray.go 项目: v2ray/v2ray-core
func (v *InboundConnectionConfig) Build() (*core.InboundConnectionConfig, error) {
	config := new(core.InboundConnectionConfig)
	config.PortRange = &v2net.PortRange{
		From: uint32(v.Port),
		To:   uint32(v.Port),
	}
	if v.Listen != nil {
		if v.Listen.Family().IsDomain() {
			return nil, errors.New("Point: Unable to listen on domain address: " + v.Listen.Domain())
		}
		config.ListenOn = v.Listen.Build()
	}
	if v.StreamSetting != nil {
		ts, err := v.StreamSetting.Build()
		if err != nil {
			return nil, err
		}
		config.StreamSettings = ts
	}
	config.AllowPassiveConnection = v.AllowPassive

	jsonConfig, err := inboundConfigLoader.LoadWithID(v.Settings, v.Protocol)
	if err != nil {
		return nil, errors.Base(err).Message("Failed to load inbound config.")
	}
	ts, err := jsonConfig.(Buildable).Build()
	if err != nil {
		return nil, err
	}
	config.Settings = ts
	if len(v.Tag) > 0 {
		config.Tag = v.Tag
	}
	return config, nil
}
示例#18
0
func RegisterTransportListener(protocol TransportProtocol, listener ListenFunc) error {
	if _, found := transportListenerCache[protocol]; found {
		return errors.New("Internet|TCPHub: ", protocol, " listener already registered.")
	}
	transportListenerCache[protocol] = listener
	return nil
}
示例#19
0
文件: v2ray.go 项目: v2ray/v2ray-core
func (v *InboundDetourAllocationConfig) Build() (*core.AllocationStrategy, error) {
	config := new(core.AllocationStrategy)
	switch strings.ToLower(v.Strategy) {
	case "always":
		config.Type = core.AllocationStrategy_Always
	case "random":
		config.Type = core.AllocationStrategy_Random
	case "external":
		config.Type = core.AllocationStrategy_External
	default:
		return nil, errors.New("Unknown allocation strategy: ", v.Strategy)
	}
	if v.Concurrency != nil {
		config.Concurrency = &core.AllocationStrategyConcurrency{
			Value: *v.Concurrency,
		}
	}

	if v.RefreshMin != nil {
		config.Refresh = &core.AllocationStrategyRefresh{
			Value: *v.RefreshMin,
		}
	}

	return config, nil
}
示例#20
0
文件: uuid.go 项目: v2ray/v2ray-core
// ParseString converts an UUID in string form to object.
func ParseString(str string) (*UUID, error) {
	text := []byte(str)
	if len(text) < 32 {
		return nil, errors.New("Invalid UUID: ", str)
	}

	uuid := new(UUID)
	b := uuid.Bytes()

	for _, byteGroup := range byteGroups {
		if text[0] == '-' {
			text = text[1:]
		}

		_, err := hex.Decode(b[:byteGroup/2], text[:byteGroup])

		if err != nil {
			return nil, err
		}

		text = text[byteGroup:]
		b = b[byteGroup/2:]
	}

	return uuid, nil
}
示例#21
0
func (v *ProxyConfig) Build() (*internet.ProxyConfig, error) {
	if len(v.Tag) == 0 {
		return nil, errors.New("Proxy tag is not set.")
	}
	return &internet.ProxyConfig{
		Tag: v.Tag,
	}, nil
}
示例#22
0
func waitForData(wdi *waitDataInspector) func() error {
	return func() error {
		if wdi.WaitForData() {
			return nil
		}
		return errors.New("DefaultDispatcher: No data.")
	}
}
示例#23
0
// NewServer creates a new HTTP inbound handler.
func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
	space := app.SpaceFromContext(ctx)
	if space == nil {
		return nil, errors.New("HTTP|Server: No space in context.")
	}
	s := &Server{
		config: config,
	}
	space.OnInitialize(func() error {
		s.packetDispatcher = dispatcher.FromSpace(space)
		if s.packetDispatcher == nil {
			return errors.New("HTTP|Server: Dispatcher not found in space.")
		}
		return nil
	})
	return s, nil
}
示例#24
0
文件: uuid.go 项目: v2ray/v2ray-core
// PraseBytes converts an UUID in byte form to object.
func ParseBytes(b []byte) (*UUID, error) {
	if len(b) != 16 {
		return nil, errors.New("Invalid UUID: ", b)
	}
	uuid := new(UUID)
	copy(uuid[:], b)
	return uuid, nil
}
示例#25
0
func CreateOutboundHandler(name string, space app.Space, config interface{}, meta *OutboundHandlerMeta) (OutboundHandler, error) {
	creator, found := outboundFactories[name]
	if !found {
		return nil, errors.New("Proxy: Unknown outbound name: " + name)
	}
	if meta.StreamSettings == nil {
		meta.StreamSettings = &internet.StreamConfig{
			Network: creator.StreamCapability().Get(0),
		}
	} else {
		if !creator.StreamCapability().HasNetwork(meta.StreamSettings.Network) {
			return nil, errors.New("Proxy: Invalid network: " + meta.StreamSettings.Network.String())
		}
	}

	return creator.Create(space, config, meta)
}
示例#26
0
func (v *spaceImpl) AddApplication(app Application) error {
	if v == nil {
		return errors.New("App: Nil space.")
	}
	appType := reflect.TypeOf(app.Interface())
	v.cache[appType] = app
	return nil
}
func (v *HTTPAuthenticatorResponse) Build() (*http.ResponseConfig, error) {
	config := &http.ResponseConfig{
		Header: []*http.Header{
			{
				Name:  "Content-Type",
				Value: []string{"application/octet-stream", "video/mpeg"},
			},
			{
				Name:  "Transfer-Encoding",
				Value: []string{"chunked"},
			},
			{
				Name:  "Connection",
				Value: []string{"keep-alive"},
			},
			{
				Name:  "Pragma",
				Value: []string{"no-cache"},
			},
			{
				Name:  "Cache-Control",
				Value: []string{"private", "no-cache"},
			},
		},
	}

	if len(v.Version) > 0 {
		config.Version = &http.Version{Value: v.Version}
	}

	if len(v.Status) > 0 || len(v.Reason) > 0 {
		config.Status = &http.Status{
			Code:   "200",
			Reason: "OK",
		}
		if len(v.Status) > 0 {
			config.Status.Code = v.Status
		}
		if len(v.Reason) > 0 {
			config.Status.Reason = v.Reason
		}
	}

	if len(v.Headers) > 0 {
		config.Header = make([]*http.Header, 0, len(v.Headers))
		for key, value := range v.Headers {
			if value == nil {
				return nil, errors.New("Empty HTTP header value: " + key)
			}
			config.Header = append(config.Header, &http.Header{
				Name:  key,
				Value: append([]string(nil), (*value)...),
			})
		}
	}

	return config, nil
}
func (v *HTTPAuthenticatorRequest) Build() (*http.RequestConfig, error) {
	config := &http.RequestConfig{
		Uri: []string{"/"},
		Header: []*http.Header{
			{
				Name:  "Host",
				Value: []string{"www.baidu.com", "www.bing.com"},
			},
			{
				Name: "User-Agent",
				Value: []string{
					"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
					"Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46",
				},
			},
			{
				Name:  "Accept-Encoding",
				Value: []string{"gzip, deflate"},
			},
			{
				Name:  "Connection",
				Value: []string{"keep-alive"},
			},
			{
				Name:  "Pragma",
				Value: []string{"no-cache"},
			},
		},
	}

	if len(v.Version) > 0 {
		config.Version = &http.Version{Value: v.Version}
	}

	if len(v.Method) > 0 {
		config.Method = &http.Method{Value: v.Method}
	}

	if len(v.Path) > 0 {
		config.Uri = append([]string(nil), (v.Path)...)
	}

	if len(v.Headers) > 0 {
		config.Header = make([]*http.Header, 0, len(v.Headers))
		for key, value := range v.Headers {
			if value == nil {
				return nil, errors.New("Empty HTTP header value: " + key)
			}
			config.Header = append(config.Header, &http.Header{
				Name:  key,
				Value: append([]string(nil), (*value)...),
			})
		}
	}

	return config, nil
}
示例#29
0
func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection) error {
	switch network {
	case net.Network_TCP:
		return s.processTCP(ctx, conn)
	case net.Network_UDP:
		return s.handleUDPPayload(ctx, conn)
	default:
		return errors.New("Socks|Server: Unknown network: ", network)
	}
}
示例#30
0
func UnmarshalCommand(cmdID byte, data []byte) (protocol.ResponseCommand, error) {
	if len(data) <= 4 {
		return nil, errors.New("VMess|Command: Insufficient length.")
	}
	expectedAuth := Authenticate(data[4:])
	actualAuth := serial.BytesToUint32(data[:4])
	if expectedAuth != actualAuth {
		return nil, errors.New("VMess|Command: Invalid auth.")
	}

	var factory CommandFactory
	switch cmdID {
	case 1:
		factory = new(CommandSwitchAccountFactory)
	default:
		return nil, ErrUnknownCommand
	}
	return factory.Unmarshal(data[4:])
}