github.com/xraypb/xray-core@v1.6.6/proxy/shadowsocks_2022/inbound_multi.go (about)

     1  package shadowsocks_2022
     2  
     3  import (
     4  	"context"
     5  	"encoding/base64"
     6  	"strconv"
     7  
     8  	"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
     9  	C "github.com/sagernet/sing/common"
    10  	A "github.com/sagernet/sing/common/auth"
    11  	B "github.com/sagernet/sing/common/buf"
    12  	"github.com/sagernet/sing/common/bufio"
    13  	E "github.com/sagernet/sing/common/exceptions"
    14  	M "github.com/sagernet/sing/common/metadata"
    15  	N "github.com/sagernet/sing/common/network"
    16  	"github.com/xraypb/xray-core/common"
    17  	"github.com/xraypb/xray-core/common/buf"
    18  	"github.com/xraypb/xray-core/common/log"
    19  	"github.com/xraypb/xray-core/common/net"
    20  	"github.com/xraypb/xray-core/common/protocol"
    21  	"github.com/xraypb/xray-core/common/session"
    22  	"github.com/xraypb/xray-core/common/uuid"
    23  	"github.com/xraypb/xray-core/features/routing"
    24  	"github.com/xraypb/xray-core/transport/internet/stat"
    25  )
    26  
    27  func init() {
    28  	common.Must(common.RegisterConfig((*MultiUserServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
    29  		return NewMultiServer(ctx, config.(*MultiUserServerConfig))
    30  	}))
    31  }
    32  
    33  type MultiUserInbound struct {
    34  	networks []net.Network
    35  	users    []*User
    36  	service  *shadowaead_2022.MultiService[int]
    37  }
    38  
    39  func NewMultiServer(ctx context.Context, config *MultiUserServerConfig) (*MultiUserInbound, error) {
    40  	networks := config.Network
    41  	if len(networks) == 0 {
    42  		networks = []net.Network{
    43  			net.Network_TCP,
    44  			net.Network_UDP,
    45  		}
    46  	}
    47  	inbound := &MultiUserInbound{
    48  		networks: networks,
    49  		users:    config.Users,
    50  	}
    51  	if config.Key == "" {
    52  		return nil, newError("missing key")
    53  	}
    54  	psk, err := base64.StdEncoding.DecodeString(config.Key)
    55  	if err != nil {
    56  		return nil, newError("parse config").Base(err)
    57  	}
    58  	service, err := shadowaead_2022.NewMultiService[int](config.Method, psk, 500, inbound)
    59  	if err != nil {
    60  		return nil, newError("create service").Base(err)
    61  	}
    62  
    63  	for i, user := range config.Users {
    64  		if user.Email == "" {
    65  			u := uuid.New()
    66  			user.Email = "unnamed-user-" + strconv.Itoa(i) + "-" + u.String()
    67  		}
    68  	}
    69  	err = service.UpdateUsersWithPasswords(
    70  		C.MapIndexed(config.Users, func(index int, it *User) int { return index }),
    71  		C.Map(config.Users, func(it *User) string { return it.Key }),
    72  	)
    73  	if err != nil {
    74  		return nil, newError("create service").Base(err)
    75  	}
    76  
    77  	inbound.service = service
    78  	return inbound, nil
    79  }
    80  
    81  func (i *MultiUserInbound) Network() []net.Network {
    82  	return i.networks
    83  }
    84  
    85  func (i *MultiUserInbound) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error {
    86  	inbound := session.InboundFromContext(ctx)
    87  
    88  	var metadata M.Metadata
    89  	if inbound.Source.IsValid() {
    90  		metadata.Source = M.ParseSocksaddr(inbound.Source.NetAddr())
    91  	}
    92  
    93  	ctx = session.ContextWithDispatcher(ctx, dispatcher)
    94  
    95  	if network == net.Network_TCP {
    96  		return returnError(i.service.NewConnection(ctx, connection, metadata))
    97  	} else {
    98  		reader := buf.NewReader(connection)
    99  		pc := &natPacketConn{connection}
   100  		for {
   101  			mb, err := reader.ReadMultiBuffer()
   102  			if err != nil {
   103  				buf.ReleaseMulti(mb)
   104  				return returnError(err)
   105  			}
   106  			for _, buffer := range mb {
   107  				packet := B.As(buffer.Bytes()).ToOwned()
   108  				err = i.service.NewPacket(ctx, pc, packet, metadata)
   109  				if err != nil {
   110  					packet.Release()
   111  					buf.ReleaseMulti(mb)
   112  					return err
   113  				}
   114  				buffer.Release()
   115  			}
   116  		}
   117  	}
   118  }
   119  
   120  func (i *MultiUserInbound) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
   121  	inbound := session.InboundFromContext(ctx)
   122  	userInt, _ := A.UserFromContext[int](ctx)
   123  	user := i.users[userInt]
   124  	inbound.User = &protocol.MemoryUser{
   125  		Email: user.Email,
   126  		Level: uint32(user.Level),
   127  	}
   128  	ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
   129  		From:   metadata.Source,
   130  		To:     metadata.Destination,
   131  		Status: log.AccessAccepted,
   132  		Email:  user.Email,
   133  	})
   134  	newError("tunnelling request to tcp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
   135  	dispatcher := session.DispatcherFromContext(ctx)
   136  	link, err := dispatcher.Dispatch(ctx, toDestination(metadata.Destination, net.Network_TCP))
   137  	if err != nil {
   138  		return err
   139  	}
   140  	outConn := &pipeConnWrapper{
   141  		&buf.BufferedReader{Reader: link.Reader},
   142  		link.Writer,
   143  		conn,
   144  	}
   145  	return bufio.CopyConn(ctx, conn, outConn)
   146  }
   147  
   148  func (i *MultiUserInbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
   149  	inbound := session.InboundFromContext(ctx)
   150  	userInt, _ := A.UserFromContext[int](ctx)
   151  	user := i.users[userInt]
   152  	inbound.User = &protocol.MemoryUser{
   153  		Email: user.Email,
   154  		Level: uint32(user.Level),
   155  	}
   156  	ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
   157  		From:   metadata.Source,
   158  		To:     metadata.Destination,
   159  		Status: log.AccessAccepted,
   160  		Email:  user.Email,
   161  	})
   162  	newError("tunnelling request to udp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
   163  	dispatcher := session.DispatcherFromContext(ctx)
   164  	destination := toDestination(metadata.Destination, net.Network_UDP)
   165  	link, err := dispatcher.Dispatch(ctx, destination)
   166  	if err != nil {
   167  		return err
   168  	}
   169  	outConn := &packetConnWrapper{
   170  		Reader: link.Reader,
   171  		Writer: link.Writer,
   172  		Dest:   destination,
   173  	}
   174  	return bufio.CopyPacketConn(ctx, conn, outConn)
   175  }
   176  
   177  func (i *MultiUserInbound) NewError(ctx context.Context, err error) {
   178  	if E.IsClosed(err) {
   179  		return
   180  	}
   181  	newError(err).AtWarning().WriteToLog()
   182  }