mirror of
https://github.com/v2fly/v2ray-core.git
synced 2026-10-09 12:11:45 -07:00
introduce in-memory user
This commit is contained in:
@@ -27,7 +27,11 @@ type Client struct {
|
||||
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||
serverList := protocol.NewServerList()
|
||||
for _, rec := range config.Server {
|
||||
serverList.AddServer(protocol.NewServerSpecFromPB(*rec))
|
||||
s, err := protocol.NewServerSpecFromPB(*rec)
|
||||
if err != nil {
|
||||
return nil, newError("failed to parse server spec").Base(err)
|
||||
}
|
||||
serverList.AddServer(s)
|
||||
}
|
||||
if serverList.Size() == 0 {
|
||||
return nil, newError("0 server")
|
||||
@@ -81,11 +85,10 @@ func (c *Client) Process(ctx context.Context, link *core.Link, dialer proxy.Dial
|
||||
}
|
||||
|
||||
user := server.PickUser()
|
||||
rawAccount, err := user.GetTypedAccount()
|
||||
if err != nil {
|
||||
return newError("failed to get a valid user account").AtWarning().Base(err)
|
||||
account, ok := user.Account.(*MemoryAccount)
|
||||
if !ok {
|
||||
return newError("user account is not valid")
|
||||
}
|
||||
account := rawAccount.(*MemoryAccount)
|
||||
request.User = user
|
||||
|
||||
if account.OneTimeAuth == Account_Auto || account.OneTimeAuth == Account_Enabled {
|
||||
|
||||
@@ -27,12 +27,8 @@ var addrParser = protocol.NewAddressParser(
|
||||
)
|
||||
|
||||
// ReadTCPSession reads a Shadowsocks TCP session from the given reader, returns its header and remaining parts.
|
||||
func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) {
|
||||
rawAccount, err := user.GetTypedAccount()
|
||||
if err != nil {
|
||||
return nil, nil, newError("failed to parse account").Base(err).AtError()
|
||||
}
|
||||
account := rawAccount.(*MemoryAccount)
|
||||
func ReadTCPSession(user *protocol.MemoryUser, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) {
|
||||
account := user.Account.(*MemoryAccount)
|
||||
|
||||
buffer := buf.New()
|
||||
defer buffer.Release()
|
||||
@@ -116,11 +112,7 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea
|
||||
// WriteTCPRequest writes Shadowsocks request into the given writer, and returns a writer for body.
|
||||
func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Writer, error) {
|
||||
user := request.User
|
||||
rawAccount, err := user.GetTypedAccount()
|
||||
if err != nil {
|
||||
return nil, newError("failed to parse account").Base(err).AtError()
|
||||
}
|
||||
account := rawAccount.(*MemoryAccount)
|
||||
account := user.Account.(*MemoryAccount)
|
||||
|
||||
if account.Cipher.IsAEAD() {
|
||||
request.Option.Clear(RequestOptionOneTimeAuth)
|
||||
@@ -167,17 +159,13 @@ func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Wri
|
||||
return chunkWriter, nil
|
||||
}
|
||||
|
||||
func ReadTCPResponse(user *protocol.User, reader io.Reader) (buf.Reader, error) {
|
||||
rawAccount, err := user.GetTypedAccount()
|
||||
if err != nil {
|
||||
return nil, newError("failed to parse account").Base(err).AtError()
|
||||
}
|
||||
account := rawAccount.(*MemoryAccount)
|
||||
func ReadTCPResponse(user *protocol.MemoryUser, reader io.Reader) (buf.Reader, error) {
|
||||
account := user.Account.(*MemoryAccount)
|
||||
|
||||
var iv []byte
|
||||
if account.Cipher.IVSize() > 0 {
|
||||
iv = make([]byte, account.Cipher.IVSize())
|
||||
if _, err = io.ReadFull(reader, iv); err != nil {
|
||||
if _, err := io.ReadFull(reader, iv); err != nil {
|
||||
return nil, newError("failed to read IV").Base(err)
|
||||
}
|
||||
}
|
||||
@@ -187,11 +175,7 @@ func ReadTCPResponse(user *protocol.User, reader io.Reader) (buf.Reader, error)
|
||||
|
||||
func WriteTCPResponse(request *protocol.RequestHeader, writer io.Writer) (buf.Writer, error) {
|
||||
user := request.User
|
||||
rawAccount, err := user.GetTypedAccount()
|
||||
if err != nil {
|
||||
return nil, newError("failed to parse account.").Base(err).AtError()
|
||||
}
|
||||
account := rawAccount.(*MemoryAccount)
|
||||
account := user.Account.(*MemoryAccount)
|
||||
|
||||
var iv []byte
|
||||
if account.Cipher.IVSize() > 0 {
|
||||
@@ -207,11 +191,7 @@ func WriteTCPResponse(request *protocol.RequestHeader, writer io.Writer) (buf.Wr
|
||||
|
||||
func EncodeUDPPacket(request *protocol.RequestHeader, payload []byte) (*buf.Buffer, error) {
|
||||
user := request.User
|
||||
rawAccount, err := user.GetTypedAccount()
|
||||
if err != nil {
|
||||
return nil, newError("failed to parse account.").Base(err).AtError()
|
||||
}
|
||||
account := rawAccount.(*MemoryAccount)
|
||||
account := user.Account.(*MemoryAccount)
|
||||
|
||||
buffer := buf.New()
|
||||
ivLen := account.Cipher.IVSize()
|
||||
@@ -239,12 +219,8 @@ func EncodeUDPPacket(request *protocol.RequestHeader, payload []byte) (*buf.Buff
|
||||
return buffer, nil
|
||||
}
|
||||
|
||||
func DecodeUDPPacket(user *protocol.User, payload *buf.Buffer) (*protocol.RequestHeader, *buf.Buffer, error) {
|
||||
rawAccount, err := user.GetTypedAccount()
|
||||
if err != nil {
|
||||
return nil, nil, newError("failed to parse account").Base(err).AtError()
|
||||
}
|
||||
account := rawAccount.(*MemoryAccount)
|
||||
func DecodeUDPPacket(user *protocol.MemoryUser, payload *buf.Buffer) (*protocol.RequestHeader, *buf.Buffer, error) {
|
||||
account := user.Account.(*MemoryAccount)
|
||||
|
||||
var iv []byte
|
||||
if !account.Cipher.IsAEAD() && account.Cipher.IVSize() > 0 {
|
||||
@@ -306,7 +282,7 @@ func DecodeUDPPacket(user *protocol.User, payload *buf.Buffer) (*protocol.Reques
|
||||
|
||||
type UDPReader struct {
|
||||
Reader io.Reader
|
||||
User *protocol.User
|
||||
User *protocol.MemoryUser
|
||||
}
|
||||
|
||||
func (v *UDPReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
|
||||
@@ -12,6 +12,12 @@ import (
|
||||
. "v2ray.com/ext/assert"
|
||||
)
|
||||
|
||||
func toAccount(a *Account) protocol.Account {
|
||||
account, err := a.AsAccount()
|
||||
common.Must(err)
|
||||
return account
|
||||
}
|
||||
|
||||
func TestUDPEncoding(t *testing.T) {
|
||||
assert := With(t)
|
||||
|
||||
@@ -20,9 +26,9 @@ func TestUDPEncoding(t *testing.T) {
|
||||
Command: protocol.RequestCommandUDP,
|
||||
Address: net.LocalHostIP,
|
||||
Port: 1234,
|
||||
User: &protocol.User{
|
||||
User: &protocol.MemoryUser{
|
||||
Email: "love@v2ray.com",
|
||||
Account: serial.ToTypedMessage(&Account{
|
||||
Account: toAccount(&Account{
|
||||
Password: "shadowsocks-password",
|
||||
CipherType: CipherType_AES_128_CFB,
|
||||
Ota: Account_Disabled,
|
||||
@@ -57,9 +63,9 @@ func TestTCPRequest(t *testing.T) {
|
||||
Address: net.LocalHostIP,
|
||||
Option: RequestOptionOneTimeAuth,
|
||||
Port: 1234,
|
||||
User: &protocol.User{
|
||||
User: &protocol.MemoryUser{
|
||||
Email: "love@v2ray.com",
|
||||
Account: serial.ToTypedMessage(&Account{
|
||||
Account: toAccount(&Account{
|
||||
Password: "tcp-password",
|
||||
CipherType: CipherType_CHACHA20,
|
||||
}),
|
||||
@@ -74,9 +80,9 @@ func TestTCPRequest(t *testing.T) {
|
||||
Address: net.LocalHostIPv6,
|
||||
Option: RequestOptionOneTimeAuth,
|
||||
Port: 1234,
|
||||
User: &protocol.User{
|
||||
User: &protocol.MemoryUser{
|
||||
Email: "love@v2ray.com",
|
||||
Account: serial.ToTypedMessage(&Account{
|
||||
Account: toAccount(&Account{
|
||||
Password: "password",
|
||||
CipherType: CipherType_AES_256_CFB,
|
||||
}),
|
||||
@@ -91,9 +97,9 @@ func TestTCPRequest(t *testing.T) {
|
||||
Address: net.DomainAddress("v2ray.com"),
|
||||
Option: RequestOptionOneTimeAuth,
|
||||
Port: 1234,
|
||||
User: &protocol.User{
|
||||
User: &protocol.MemoryUser{
|
||||
Email: "love@v2ray.com",
|
||||
Account: serial.ToTypedMessage(&Account{
|
||||
Account: toAccount(&Account{
|
||||
Password: "password",
|
||||
CipherType: CipherType_CHACHA20_IETF,
|
||||
}),
|
||||
@@ -135,8 +141,8 @@ func TestTCPRequest(t *testing.T) {
|
||||
func TestUDPReaderWriter(t *testing.T) {
|
||||
assert := With(t)
|
||||
|
||||
user := &protocol.User{
|
||||
Account: serial.ToTypedMessage(&Account{
|
||||
user := &protocol.MemoryUser{
|
||||
Account: toAccount(&Account{
|
||||
Password: "test-password",
|
||||
CipherType: CipherType_CHACHA20_IETF,
|
||||
}),
|
||||
|
||||
+12
-13
@@ -20,10 +20,9 @@ import (
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
config ServerConfig
|
||||
user *protocol.User
|
||||
account *MemoryAccount
|
||||
v *core.Instance
|
||||
config ServerConfig
|
||||
user *protocol.MemoryUser
|
||||
v *core.Instance
|
||||
}
|
||||
|
||||
// NewServer create a new Shadowsocks server.
|
||||
@@ -32,17 +31,15 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
||||
return nil, newError("user is not specified")
|
||||
}
|
||||
|
||||
rawAccount, err := config.User.GetTypedAccount()
|
||||
mUser, err := config.User.ToMemoryUser()
|
||||
if err != nil {
|
||||
return nil, newError("failed to get user account").Base(err)
|
||||
return nil, newError("failed to parse user account").Base(err)
|
||||
}
|
||||
account := rawAccount.(*MemoryAccount)
|
||||
|
||||
s := &Server{
|
||||
config: *config,
|
||||
user: config.GetUser(),
|
||||
account: account,
|
||||
v: core.MustFromContext(ctx),
|
||||
config: *config,
|
||||
user: mUser,
|
||||
v: core.MustFromContext(ctx),
|
||||
}
|
||||
|
||||
return s, nil
|
||||
@@ -90,6 +87,8 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
|
||||
conn.Write(data.Bytes())
|
||||
})
|
||||
|
||||
account := s.user.Account.(*MemoryAccount)
|
||||
|
||||
reader := buf.NewReader(conn)
|
||||
for {
|
||||
mpayload, err := reader.ReadMultiBuffer()
|
||||
@@ -113,13 +112,13 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
|
||||
continue
|
||||
}
|
||||
|
||||
if request.Option.Has(RequestOptionOneTimeAuth) && s.account.OneTimeAuth == Account_Disabled {
|
||||
if request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Disabled {
|
||||
newError("client payload enables OTA but server doesn't allow it").WriteToLog(session.ExportIDToError(ctx))
|
||||
payload.Release()
|
||||
continue
|
||||
}
|
||||
|
||||
if !request.Option.Has(RequestOptionOneTimeAuth) && s.account.OneTimeAuth == Account_Enabled {
|
||||
if !request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Enabled {
|
||||
newError("client payload disables OTA but server forces it").WriteToLog(session.ExportIDToError(ctx))
|
||||
payload.Release()
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user