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 }