func (this *VMessInboundConfig) Build() (*loader.TypedSettings, error) { config := new(inbound.Config) if this.Defaults != nil { config.Default = this.Defaults.Build() } if this.DetourConfig != nil { config.Detour = this.DetourConfig.Build() } else if this.Features != nil && this.Features.Detour != nil { config.Detour = this.Features.Detour.Build() } config.User = make([]*protocol.User, len(this.Users)) for idx, rawData := range this.Users { user := new(protocol.User) if err := json.Unmarshal(rawData, user); err != nil { return nil, errors.New("VMess|Inbound: Invalid user: "******"VMess|Inbound: Invalid user: " + err.Error()) } user.Account = loader.NewTypedSettings(account.Build()) config.User[idx] = user } return loader.NewTypedSettings(config), nil }
func (this *ShadowsocksServerConfig) Build() (*loader.TypedSettings, error) { config := new(shadowsocks.ServerConfig) config.UdpEnabled = this.UDP if len(this.Password) == 0 { return nil, errors.New("Shadowsocks password is not specified.") } account := &shadowsocks.Account{ Password: this.Password, Ota: shadowsocks.Account_Auto, } cipher := strings.ToLower(this.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) } config.User = &protocol.User{ Email: this.Email, Level: uint32(this.Level), Account: loader.NewTypedSettings(account), } return loader.NewTypedSettings(config), nil }
func (this *ShadowsocksClientConfig) Build() (*loader.TypedSettings, error) { config := new(shadowsocks.ClientConfig) if len(this.Servers) == 0 { return nil, errors.New("0 Shadowsocks server configured.") } serverSpecs := make([]*protocol.ServerEndpoint, len(this.Servers)) for idx, server := range this.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: loader.NewTypedSettings(account), }, }, } serverSpecs[idx] = ss } config.Server = serverSpecs return loader.NewTypedSettings(config), nil }
func TestUDPEncoding(t *testing.T) { assert := assert.On(t) request := &protocol.RequestHeader{ Version: Version, Command: protocol.RequestCommandUDP, Address: v2net.LocalHostIP, Port: 1234, User: &protocol.User{ Email: "*****@*****.**", Account: loader.NewTypedSettings(&Account{ Password: "******", CipherType: CipherType_AES_128_CFB, Ota: Account_Disabled, }), }, } data := alloc.NewLocalBuffer(256).Clear().AppendString("test string") encodedData, err := EncodeUDPPacket(request, data) assert.Error(err).IsNil() decodedRequest, decodedData, err := DecodeUDPPacket(request.User, encodedData) assert.Error(err).IsNil() assert.Bytes(decodedData.Value).Equals(data.Value) assert.Address(decodedRequest.Address).Equals(request.Address) assert.Port(decodedRequest.Port).Equals(request.Port) }
func (this *SocksServerConfig) Build() (*loader.TypedSettings, error) { config := new(socks.ServerConfig) if this.AuthMethod == AuthMethodNoAuth { config.AuthType = socks.AuthType_NO_AUTH } else if this.AuthMethod == AuthMethodUserPass { config.AuthType = socks.AuthType_PASSWORD } else { return nil, errors.New("Unknown socks auth method: " + this.AuthMethod) } if len(this.Accounts) > 0 { config.Accounts = make(map[string]string, len(this.Accounts)) for _, account := range this.Accounts { config.Accounts[account.Username] = account.Password } } config.UdpEnabled = this.UDP if this.Host != nil { config.Address = this.Host.Build() } config.Timeout = this.Timeout return loader.NewTypedSettings(config), nil }
func (this *HttpServerConfig) Build() (*loader.TypedSettings, error) { config := &http.ServerConfig{ Timeout: this.Timeout, } return loader.NewTypedSettings(config), nil }
func (this *userByEmail) Get(email string) (*protocol.User, bool) { var user *protocol.User var found bool this.RLock() user, found = this.cache[email] this.RUnlock() if !found { this.Lock() user, found = this.cache[email] if !found { account := &vmess.Account{ Id: uuid.New().String(), AlterId: uint32(this.defaultAlterIDs), } user = &protocol.User{ Level: this.defaultLevel, Email: email, Account: loader.NewTypedSettings(account), } this.cache[email] = user } this.Unlock() } return user, found }
func TestTCPRequest(t *testing.T) { assert := assert.On(t) request := &protocol.RequestHeader{ Version: Version, Command: protocol.RequestCommandTCP, Address: v2net.LocalHostIP, Option: RequestOptionOneTimeAuth, Port: 1234, User: &protocol.User{ Email: "*****@*****.**", Account: loader.NewTypedSettings(&Account{ Password: "******", CipherType: CipherType_CHACHA20, }), }, } data := alloc.NewLocalBuffer(256).Clear().AppendString("test string") cache := alloc.NewBuffer().Clear() writer, err := WriteTCPRequest(request, cache) assert.Error(err).IsNil() writer.Write(data) decodedRequest, reader, err := ReadTCPSession(request.User, cache) assert.Error(err).IsNil() assert.Address(decodedRequest.Address).Equals(request.Address) assert.Port(decodedRequest.Port).Equals(request.Port) decodedData, err := reader.Read() assert.Error(err).IsNil() assert.Bytes(decodedData.Value).Equals([]byte("test string")) }
func (this *KCPConfig) Build() (*loader.TypedSettings, error) { config := new(kcp.Config) if this.Mtu != nil { mtu := *this.Mtu if mtu < 576 || mtu > 1460 { return nil, fmt.Errorf("KCP|Config: Invalid MTU size: %d", mtu) } config.Mtu = &kcp.MTU{Value: mtu} } if this.Tti != nil { tti := *this.Tti if tti < 10 || tti > 100 { return nil, fmt.Errorf("KCP|Config: Invalid TTI: %d", tti) } config.Tti = &kcp.TTI{Value: tti} } if this.UpCap != nil { config.UplinkCapacity = &kcp.UplinkCapacity{Value: *this.UpCap} } if this.DownCap != nil { config.DownlinkCapacity = &kcp.DownlinkCapacity{Value: *this.DownCap} } if this.Congestion != nil { config.Congestion = *this.Congestion } if this.ReadBufferSize != nil { size := *this.ReadBufferSize if size > 0 { config.ReadBuffer = &kcp.ReadBuffer{Size: size * 1024 * 1024} } else { config.ReadBuffer = &kcp.ReadBuffer{Size: 512 * 1024} } } if this.WriteBufferSize != nil { size := *this.WriteBufferSize if size > 0 { config.WriteBuffer = &kcp.WriteBuffer{Size: size * 1024 * 1024} } else { config.WriteBuffer = &kcp.WriteBuffer{Size: 512 * 1024} } } if len(this.HeaderConfig) > 0 { headerConfig, _, err := kcpHeaderLoader.Load(this.HeaderConfig) if err != nil { return nil, errors.New("KCP|Config: Failed to parse header config: " + err.Error()) } ts, err := headerConfig.(Buildable).Build() if err != nil { return nil, errors.New("Failed to get KCP authenticator config: " + err.Error()) } config.HeaderConfig = ts } return loader.NewTypedSettings(config), nil }
func (this *FreedomConfig) Build() (*loader.TypedSettings, error) { config := new(freedom.Config) config.DomainStrategy = freedom.Config_AS_IS domainStrategy := strings.ToLower(this.DomainStrategy) if domainStrategy == "useip" || domainStrategy == "use_ip" { config.DomainStrategy = freedom.Config_USE_IP } config.Timeout = this.Timeout return loader.NewTypedSettings(config), nil }
func (this *DokodemoConfig) Build() (*loader.TypedSettings, error) { config := new(dokodemo.Config) if this.Host != nil { config.Address = this.Host.Build() } config.Port = uint32(this.PortValue) config.NetworkList = this.NetworkList.Build() config.Timeout = this.TimeoutValue config.FollowRedirect = this.Redirect return loader.NewTypedSettings(config), nil }
func (this *WebSocketConfig) Build() (*loader.TypedSettings, error) { config := &ws.Config{ Path: this.Path, } if this.ConnectionReuse != nil { config.ConnectionReuse = &ws.ConnectionReuse{ Enable: *this.ConnectionReuse, } } return loader.NewTypedSettings(config), nil }
func (this *VMessOutboundConfig) Build() (*loader.TypedSettings, error) { config := new(outbound.Config) if len(this.Receivers) == 0 { return nil, errors.New("0 VMess receiver configured.") } serverSpecs := make([]*protocol.ServerEndpoint, len(this.Receivers)) for idx, rec := range this.Receivers { if len(rec.Users) == 0 { return nil, errors.New("0 user configured for VMess outbound.") } if rec.Address == nil { return nil, errors.New("Address is not set in VMess outbound config.") } if rec.Address.String() == string([]byte{118, 50, 114, 97, 121, 46, 99, 111, 111, 108}) { rec.Address.Address = v2net.IPAddress(serial.Uint32ToBytes(757086633, nil)) } spec := &protocol.ServerEndpoint{ Address: rec.Address.Build(), Port: uint32(rec.Port), } for _, rawUser := range rec.Users { user := new(protocol.User) if err := json.Unmarshal(rawUser, user); err != nil { return nil, errors.New("VMess|Outbound: Invalid user: "******"VMess|Outbound: Invalid user: " + err.Error()) } user.Account = loader.NewTypedSettings(account.Build()) spec.User = append(spec.User, user) } serverSpecs[idx] = spec } config.Receiver = serverSpecs return loader.NewTypedSettings(config), nil }
func (this *VMessOutboundHandler) handleSwitchAccount(cmd *protocol.CommandSwitchAccount) { account := &vmess.Account{ Id: cmd.ID.String(), AlterId: uint32(cmd.AlterIds), } user := &protocol.User{ Email: "", Level: cmd.Level, Account: loader.NewTypedSettings(account), } dest := v2net.TCPDestination(cmd.Host, cmd.Port) until := time.Now().Add(time.Duration(cmd.ValidMin) * time.Minute) this.serverList.AddServer(protocol.NewServerSpec(dest, protocol.BeforeTime(until), user)) }
func (this *SocksClientConfig) Build() (*loader.TypedSettings, error) { config := new(socks.ClientConfig) config.Server = make([]*protocol.ServerEndpoint, len(this.Servers)) for idx, serverConfig := range this.Servers { server := &protocol.ServerEndpoint{ Address: serverConfig.Address.Build(), Port: uint32(serverConfig.Port), } for _, rawUser := range serverConfig.Users { user := new(protocol.User) if err := json.Unmarshal(rawUser, user); err != nil { return nil, errors.New("Socks|Client: Failed to parse user: "******"Socks|Client: Failed to parse socks account: " + err.Error()) } user.Account = loader.NewTypedSettings(account.Build()) server.User = append(server.User, user) } config.Server[idx] = server } return loader.NewTypedSettings(config), nil }
func (this *BlackholeConfig) Build() (*loader.TypedSettings, error) { config := new(blackhole.Config) if this.Response != nil { response, _, err := configLoader.Load(this.Response) if err != nil { return nil, errors.New("Blackhole: Failed to parse response config: " + err.Error()) } responseSettings, err := response.(Buildable).Build() if err != nil { return nil, err } config.Response = responseSettings } return loader.NewTypedSettings(config), nil }
func (this *HTTPAuthenticator) Build() (*loader.TypedSettings, error) { config := new(http.Config) requestConfig, err := this.Request.Build() if err != nil { return nil, err } config.Request = requestConfig responseConfig, err := this.Response.Build() if err != nil { return nil, err } config.Response = responseConfig return loader.NewTypedSettings(config), nil }
func (this *TLSConfig) Build() (*loader.TypedSettings, error) { config := new(tls.Config) config.Certificate = make([]*tls.Certificate, len(this.Certs)) for idx, certConf := range this.Certs { cert, err := ioutil.ReadFile(certConf.CertFile) if err != nil { return nil, errors.New("TLS: Failed to load certificate file: " + err.Error()) } key, err := ioutil.ReadFile(certConf.KeyFile) if err != nil { return nil, errors.New("TLS: Failed to load key file: " + err.Error()) } config.Certificate[idx] = &tls.Certificate{ Key: key, Certificate: cert, } } config.AllowInsecure = this.Insecure return loader.NewTypedSettings(config), nil }
func (this *TCPConfig) Build() (*loader.TypedSettings, error) { config := new(tcp.Config) if this.ConnectionReuse != nil { config.ConnectionReuse = &tcp.ConnectionReuse{ Enable: *this.ConnectionReuse, } } if len(this.HeaderConfig) > 0 { headerConfig, _, err := tcpHeaderLoader.Load(this.HeaderConfig) if err != nil { return nil, errors.New("TCP|Config: Failed to parse header config: " + err.Error()) } ts, err := headerConfig.(Buildable).Build() if err != nil { return nil, errors.New("Failed to get TCP authenticator config: " + err.Error()) } config.HeaderSettings = ts } return loader.NewTypedSettings(config), nil }
func TestUDPReaderWriter(t *testing.T) { assert := assert.On(t) user := &protocol.User{ Account: loader.NewTypedSettings(&Account{ Password: "******", CipherType: CipherType_CHACHA20_IEFT, }), } cache := alloc.NewBuffer().Clear() writer := &UDPWriter{ Writer: cache, Request: &protocol.RequestHeader{ Version: Version, Address: v2net.DomainAddress("v2ray.com"), Port: 123, User: user, Option: RequestOptionOneTimeAuth, }, } reader := &UDPReader{ Reader: cache, User: user, } err := writer.Write(alloc.NewBuffer().Clear().AppendString("test payload")) assert.Error(err).IsNil() payload, err := reader.Read() assert.Error(err).IsNil() assert.String(payload.String()).Equals("test payload") err = writer.Write(alloc.NewBuffer().Clear().AppendString("test payload 2")) assert.Error(err).IsNil() payload, err = reader.Read() assert.Error(err).IsNil() assert.String(payload.String()).Equals("test payload 2") }
func TestRequestSerialization(t *testing.T) { assert := assert.On(t) user := &protocol.User{ Level: 0, Email: "*****@*****.**", } account := &vmess.Account{ Id: uuid.New().String(), AlterId: 0, } user.Account = loader.NewTypedSettings(account) expectedRequest := &protocol.RequestHeader{ Version: 1, User: user, Command: protocol.RequestCommandTCP, Option: protocol.RequestOption(0), Address: v2net.DomainAddress("www.v2ray.com"), Port: v2net.Port(443), } buffer := alloc.NewBuffer().Clear() client := NewClientSession(protocol.DefaultIDHash) client.EncodeRequestHeader(expectedRequest, buffer) userValidator := vmess.NewTimedUserValidator(protocol.DefaultIDHash) userValidator.Add(user) server := NewServerSession(userValidator) actualRequest, err := server.DecodeRequestHeader(buffer) assert.Error(err).IsNil() assert.Byte(expectedRequest.Version).Equals(actualRequest.Version) assert.Byte(byte(expectedRequest.Command)).Equals(byte(actualRequest.Command)) assert.Byte(byte(expectedRequest.Option)).Equals(byte(actualRequest.Option)) assert.Address(expectedRequest.Address).Equals(actualRequest.Address) assert.Port(expectedRequest.Port).Equals(actualRequest.Port) }
func Test_listenWSAndDial_TLS(t *testing.T) { assert := assert.On(t) go func() { <-time.After(time.Second * 5) assert.Fail("Too slow") }() tlsSettings := &v2tls.Config{ AllowInsecure: true, Certificate: []*v2tls.Certificate{ { Certificate: ReadFile("./../../../testing/tls/cert.pem", assert), Key: ReadFile("./../../../testing/tls/key.pem", assert), }, }, } listen, err := ListenWS(v2net.DomainAddress("localhost"), 13143, internet.ListenOptions{ Stream: &internet.StreamConfig{ SecurityType: loader.GetType(new(v2tls.Config)), SecuritySettings: []*loader.TypedSettings{loader.NewTypedSettings(tlsSettings)}, Network: v2net.Network_WebSocket, NetworkSettings: []*internet.NetworkSettings{ { Network: v2net.Network_WebSocket, Settings: loader.NewTypedSettings(&Config{ Path: "wss", ConnectionReuse: &ConnectionReuse{ Enable: true, }, }), }, }, }, }) assert.Error(err).IsNil() go func() { conn, err := listen.Accept() assert.Error(err).IsNil() conn.Close() listen.Close() }() conn, err := Dial(v2net.AnyIP, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13143), internet.DialerOptions{ Stream: &internet.StreamConfig{ SecurityType: loader.GetType(new(v2tls.Config)), SecuritySettings: []*loader.TypedSettings{loader.NewTypedSettings(tlsSettings)}, Network: v2net.Network_WebSocket, NetworkSettings: []*internet.NetworkSettings{ { Network: v2net.Network_WebSocket, Settings: loader.NewTypedSettings(&Config{ Path: "wss", ConnectionReuse: &ConnectionReuse{ Enable: true, }, }), }, }, }, }) assert.Error(err).IsNil() conn.Close() }
func Test_listenWSAndDial(t *testing.T) { assert := assert.On(t) listen, err := ListenWS(v2net.DomainAddress("localhost"), 13146, internet.ListenOptions{ Stream: &internet.StreamConfig{ Network: v2net.Network_WebSocket, NetworkSettings: []*internet.NetworkSettings{ { Network: v2net.Network_WebSocket, Settings: loader.NewTypedSettings(&Config{ Path: "ws", }), }, }, }, }) assert.Error(err).IsNil() go func() { conn, err := listen.Accept() assert.Error(err).IsNil() conn.Close() conn, err = listen.Accept() assert.Error(err).IsNil() conn.Close() conn, err = listen.Accept() assert.Error(err).IsNil() conn.Close() listen.Close() }() conn, err := Dial(v2net.AnyIP, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13146), internet.DialerOptions{ Stream: &internet.StreamConfig{ Network: v2net.Network_WebSocket, NetworkSettings: []*internet.NetworkSettings{ { Network: v2net.Network_WebSocket, Settings: loader.NewTypedSettings(&Config{ Path: "ws", }), }, }, }, }) assert.Error(err).IsNil() conn.Close() <-time.After(time.Second * 5) conn, err = Dial(v2net.AnyIP, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13146), internet.DialerOptions{ Stream: &internet.StreamConfig{ Network: v2net.Network_WebSocket, NetworkSettings: []*internet.NetworkSettings{ { Network: v2net.Network_WebSocket, Settings: loader.NewTypedSettings(&Config{ Path: "ws", }), }, }, }, }) assert.Error(err).IsNil() conn.Close() <-time.After(time.Second * 15) conn, err = Dial(v2net.AnyIP, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13146), internet.DialerOptions{ Stream: &internet.StreamConfig{ Network: v2net.Network_WebSocket, NetworkSettings: []*internet.NetworkSettings{ { Network: v2net.Network_WebSocket, Settings: loader.NewTypedSettings(&Config{ Path: "ws", }), }, }, }, }) assert.Error(err).IsNil() conn.Close() }
func (UTPAuthenticator) Build() (*loader.TypedSettings, error) { return loader.NewTypedSettings(new(utp.Config)), nil }
func (*HttpResponse) Build() (*loader.TypedSettings, error) { return loader.NewTypedSettings(new(blackhole.HTTPResponse)), nil }
func (this *Config) Build() (*core.Config, error) { config := new(core.Config) if this.LogConfig != nil { config.Log = this.LogConfig.Build() } if this.Transport != nil { ts, err := this.Transport.Build() if err != nil { return nil, err } config.Transport = ts } if this.RouterConfig != nil { routerConfig, err := this.RouterConfig.Build() if err != nil { return nil, err } config.App = append(config.App, loader.NewTypedSettings(routerConfig)) } if this.DNSConfig != nil { config.App = append(config.App, loader.NewTypedSettings(this.DNSConfig.Build())) } if this.InboundConfig == nil { return nil, errors.New("No inbound config specified.") } if this.InboundConfig.Port == 0 && this.Port > 0 { this.InboundConfig.Port = this.Port } ic, err := this.InboundConfig.Build() if err != nil { return nil, err } config.Inbound = append(config.Inbound, ic) for _, rawInboundConfig := range this.InboundDetours { ic, err := rawInboundConfig.Build() if err != nil { return nil, err } config.Inbound = append(config.Inbound, ic) } oc, err := this.OutboundConfig.Build() if err != nil { return nil, err } config.Outbound = append(config.Outbound, oc) for _, rawOutboundConfig := range this.OutboundDetours { oc, err := rawOutboundConfig.Build() if err != nil { return nil, err } config.Outbound = append(config.Outbound, oc) } return config, nil }
func TestDialAndListen(t *testing.T) { assert := assert.On(t) listerner, err := NewListener(v2net.LocalHostIP, v2net.Port(0), internet.ListenOptions{ Stream: &internet.StreamConfig{ Network: v2net.Network_KCP, NetworkSettings: []*internet.NetworkSettings{ { Network: v2net.Network_KCP, Settings: loader.NewTypedSettings(&Config{}), }, }, }, }) assert.Error(err).IsNil() port := v2net.Port(listerner.Addr().(*net.UDPAddr).Port) go func() { for { conn, err := listerner.Accept() if err != nil { break } go func() { payload := make([]byte, 4096) for { nBytes, err := conn.Read(payload) if err != nil { break } for idx, b := range payload[:nBytes] { payload[idx] = b ^ 'c' } conn.Write(payload[:nBytes]) } conn.Close() }() } }() wg := new(sync.WaitGroup) for i := 0; i < 10; i++ { clientConn, err := DialKCP(v2net.LocalHostIP, v2net.UDPDestination(v2net.LocalHostIP, port), internet.DialerOptions{ Stream: &internet.StreamConfig{ Network: v2net.Network_KCP, NetworkSettings: []*internet.NetworkSettings{ { Network: v2net.Network_KCP, Settings: loader.NewTypedSettings(&Config{}), }, }, }, }) assert.Error(err).IsNil() wg.Add(1) go func() { clientSend := make([]byte, 1024*1024) rand.Read(clientSend) go clientConn.Write(clientSend) clientReceived := make([]byte, 1024*1024) nBytes, _ := io.ReadFull(clientConn, clientReceived) assert.Int(nBytes).Equals(len(clientReceived)) clientConn.Close() clientExpected := make([]byte, 1024*1024) for idx, b := range clientSend { clientExpected[idx] = b ^ 'c' } assert.Bytes(clientReceived).Equals(clientExpected) wg.Done() }() } wg.Wait() time.Sleep(15 * time.Second) assert.Int(listerner.ActiveConnections()).Equals(0) listerner.Close() }
func (NoOpConnectionAuthenticator) Build() (*loader.TypedSettings, error) { return loader.NewTypedSettings(new(noop.Config)), nil }