github.com/xmplusdev/xray-core@v1.8.10/proxy/vmess/inbound/inbound.go (about) 1 package inbound 2 3 //go:generate go run github.com/xmplusdev/xray-core/common/errors/errorgen 4 5 import ( 6 "context" 7 "io" 8 "strings" 9 "sync" 10 "time" 11 12 "github.com/xmplusdev/xray-core/common" 13 "github.com/xmplusdev/xray-core/common/buf" 14 "github.com/xmplusdev/xray-core/common/errors" 15 "github.com/xmplusdev/xray-core/common/log" 16 "github.com/xmplusdev/xray-core/common/net" 17 "github.com/xmplusdev/xray-core/common/protocol" 18 "github.com/xmplusdev/xray-core/common/session" 19 "github.com/xmplusdev/xray-core/common/signal" 20 "github.com/xmplusdev/xray-core/common/task" 21 "github.com/xmplusdev/xray-core/common/uuid" 22 "github.com/xmplusdev/xray-core/core" 23 feature_inbound "github.com/xmplusdev/xray-core/features/inbound" 24 "github.com/xmplusdev/xray-core/features/policy" 25 "github.com/xmplusdev/xray-core/features/routing" 26 "github.com/xmplusdev/xray-core/proxy/vmess" 27 "github.com/xmplusdev/xray-core/proxy/vmess/encoding" 28 "github.com/xmplusdev/xray-core/transport/internet/stat" 29 ) 30 31 type userByEmail struct { 32 sync.Mutex 33 cache map[string]*protocol.MemoryUser 34 defaultLevel uint32 35 } 36 37 func newUserByEmail(config *DefaultConfig) *userByEmail { 38 return &userByEmail{ 39 cache: make(map[string]*protocol.MemoryUser), 40 defaultLevel: config.Level, 41 } 42 } 43 44 func (v *userByEmail) addNoLock(u *protocol.MemoryUser) bool { 45 email := strings.ToLower(u.Email) 46 _, found := v.cache[email] 47 if found { 48 return false 49 } 50 v.cache[email] = u 51 return true 52 } 53 54 func (v *userByEmail) Add(u *protocol.MemoryUser) bool { 55 v.Lock() 56 defer v.Unlock() 57 58 return v.addNoLock(u) 59 } 60 61 func (v *userByEmail) Get(email string) (*protocol.MemoryUser, bool) { 62 email = strings.ToLower(email) 63 64 v.Lock() 65 defer v.Unlock() 66 67 user, found := v.cache[email] 68 if !found { 69 id := uuid.New() 70 rawAccount := &vmess.Account{ 71 Id: id.String(), 72 } 73 account, err := rawAccount.AsAccount() 74 common.Must(err) 75 user = &protocol.MemoryUser{ 76 Level: v.defaultLevel, 77 Email: email, 78 Account: account, 79 } 80 v.cache[email] = user 81 } 82 return user, found 83 } 84 85 func (v *userByEmail) Remove(email string) bool { 86 email = strings.ToLower(email) 87 88 v.Lock() 89 defer v.Unlock() 90 91 if _, found := v.cache[email]; !found { 92 return false 93 } 94 delete(v.cache, email) 95 return true 96 } 97 98 // Handler is an inbound connection handler that handles messages in VMess protocol. 99 type Handler struct { 100 policyManager policy.Manager 101 inboundHandlerManager feature_inbound.Manager 102 clients *vmess.TimedUserValidator 103 usersByEmail *userByEmail 104 detours *DetourConfig 105 sessionHistory *encoding.SessionHistory 106 } 107 108 // New creates a new VMess inbound handler. 109 func New(ctx context.Context, config *Config) (*Handler, error) { 110 v := core.MustFromContext(ctx) 111 handler := &Handler{ 112 policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager), 113 inboundHandlerManager: v.GetFeature(feature_inbound.ManagerType()).(feature_inbound.Manager), 114 clients: vmess.NewTimedUserValidator(), 115 detours: config.Detour, 116 usersByEmail: newUserByEmail(config.GetDefaultValue()), 117 sessionHistory: encoding.NewSessionHistory(), 118 } 119 120 for _, user := range config.User { 121 mUser, err := user.ToMemoryUser() 122 if err != nil { 123 return nil, newError("failed to get VMess user").Base(err) 124 } 125 126 if err := handler.AddUser(ctx, mUser); err != nil { 127 return nil, newError("failed to initiate user").Base(err) 128 } 129 } 130 131 return handler, nil 132 } 133 134 // Close implements common.Closable. 135 func (h *Handler) Close() error { 136 return errors.Combine( 137 h.sessionHistory.Close(), 138 common.Close(h.usersByEmail)) 139 } 140 141 // Network implements proxy.Inbound.Network(). 142 func (*Handler) Network() []net.Network { 143 return []net.Network{net.Network_TCP, net.Network_UNIX} 144 } 145 146 func (h *Handler) GetUser(email string) *protocol.MemoryUser { 147 user, existing := h.usersByEmail.Get(email) 148 if !existing { 149 h.clients.Add(user) 150 } 151 return user 152 } 153 154 func (h *Handler) AddUser(ctx context.Context, user *protocol.MemoryUser) error { 155 if len(user.Email) > 0 && !h.usersByEmail.Add(user) { 156 return newError("User ", user.Email, " already exists.") 157 } 158 return h.clients.Add(user) 159 } 160 161 func (h *Handler) RemoveUser(ctx context.Context, email string) error { 162 if email == "" { 163 return newError("Email must not be empty.") 164 } 165 if !h.usersByEmail.Remove(email) { 166 return newError("User ", email, " not found.") 167 } 168 h.clients.Remove(email) 169 return nil 170 } 171 172 func transferResponse(timer signal.ActivityUpdater, session *encoding.ServerSession, request *protocol.RequestHeader, response *protocol.ResponseHeader, input buf.Reader, output *buf.BufferedWriter) error { 173 session.EncodeResponseHeader(response, output) 174 175 bodyWriter, err := session.EncodeResponseBody(request, output) 176 if err != nil { 177 return newError("failed to start decoding response").Base(err) 178 } 179 { 180 // Optimize for small response packet 181 data, err := input.ReadMultiBuffer() 182 if err != nil { 183 return err 184 } 185 186 if err := bodyWriter.WriteMultiBuffer(data); err != nil { 187 return err 188 } 189 } 190 191 if err := output.SetBuffered(false); err != nil { 192 return err 193 } 194 195 if err := buf.Copy(input, bodyWriter, buf.UpdateActivity(timer)); err != nil { 196 return err 197 } 198 199 account := request.User.Account.(*vmess.MemoryAccount) 200 201 if request.Option.Has(protocol.RequestOptionChunkStream) && !account.NoTerminationSignal { 202 if err := bodyWriter.WriteMultiBuffer(buf.MultiBuffer{}); err != nil { 203 return err 204 } 205 } 206 207 return nil 208 } 209 210 // Process implements proxy.Inbound.Process(). 211 func (h *Handler) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error { 212 sessionPolicy := h.policyManager.ForLevel(0) 213 if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil { 214 return newError("unable to set read deadline").Base(err).AtWarning() 215 } 216 217 iConn := connection 218 if statConn, ok := iConn.(*stat.CounterConnection); ok { 219 iConn = statConn.Connection 220 } 221 _, isDrain := iConn.(*net.TCPConn) 222 if !isDrain { 223 _, isDrain = iConn.(*net.UnixConn) 224 } 225 226 reader := &buf.BufferedReader{Reader: buf.NewReader(connection)} 227 svrSession := encoding.NewServerSession(h.clients, h.sessionHistory) 228 request, err := svrSession.DecodeRequestHeader(reader, isDrain) 229 if err != nil { 230 if errors.Cause(err) != io.EOF { 231 log.Record(&log.AccessMessage{ 232 From: connection.RemoteAddr(), 233 To: "", 234 Status: log.AccessRejected, 235 Reason: err, 236 }) 237 err = newError("invalid request from ", connection.RemoteAddr()).Base(err).AtInfo() 238 } 239 return err 240 } 241 242 if request.Command != protocol.RequestCommandMux { 243 ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{ 244 From: connection.RemoteAddr(), 245 To: request.Destination(), 246 Status: log.AccessAccepted, 247 Reason: "", 248 Email: request.User.Email, 249 }) 250 } 251 252 newError("received request for ", request.Destination()).WriteToLog(session.ExportIDToError(ctx)) 253 254 if err := connection.SetReadDeadline(time.Time{}); err != nil { 255 newError("unable to set back read deadline").Base(err).WriteToLog(session.ExportIDToError(ctx)) 256 } 257 258 inbound := session.InboundFromContext(ctx) 259 inbound.Name = "vmess" 260 inbound.SetCanSpliceCopy(3) 261 inbound.User = request.User 262 263 sessionPolicy = h.policyManager.ForLevel(request.User.Level) 264 265 ctx, cancel := context.WithCancel(ctx) 266 timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) 267 268 ctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer) 269 link, err := dispatcher.Dispatch(ctx, request.Destination()) 270 if err != nil { 271 return newError("failed to dispatch request to ", request.Destination()).Base(err) 272 } 273 274 requestDone := func() error { 275 defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly) 276 277 bodyReader, err := svrSession.DecodeRequestBody(request, reader) 278 if err != nil { 279 return newError("failed to start decoding").Base(err) 280 } 281 if err := buf.Copy(bodyReader, link.Writer, buf.UpdateActivity(timer)); err != nil { 282 return newError("failed to transfer request").Base(err) 283 } 284 return nil 285 } 286 287 responseDone := func() error { 288 defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly) 289 290 writer := buf.NewBufferedWriter(buf.NewWriter(connection)) 291 defer writer.Flush() 292 293 response := &protocol.ResponseHeader{ 294 Command: h.generateCommand(ctx, request), 295 } 296 return transferResponse(timer, svrSession, request, response, link.Reader, writer) 297 } 298 299 requestDonePost := task.OnSuccess(requestDone, task.Close(link.Writer)) 300 if err := task.Run(ctx, requestDonePost, responseDone); err != nil { 301 common.Interrupt(link.Reader) 302 common.Interrupt(link.Writer) 303 return newError("connection ends").Base(err) 304 } 305 306 return nil 307 } 308 309 func (h *Handler) generateCommand(ctx context.Context, request *protocol.RequestHeader) protocol.ResponseCommand { 310 if h.detours != nil { 311 tag := h.detours.To 312 if h.inboundHandlerManager != nil { 313 handler, err := h.inboundHandlerManager.GetHandler(ctx, tag) 314 if err != nil { 315 newError("failed to get detour handler: ", tag).Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx)) 316 return nil 317 } 318 proxyHandler, port, availableMin := handler.GetRandomInboundProxy() 319 inboundHandler, ok := proxyHandler.(*Handler) 320 if ok && inboundHandler != nil { 321 if availableMin > 255 { 322 availableMin = 255 323 } 324 325 newError("pick detour handler for port ", port, " for ", availableMin, " minutes.").AtDebug().WriteToLog(session.ExportIDToError(ctx)) 326 user := inboundHandler.GetUser(request.User.Email) 327 if user == nil { 328 return nil 329 } 330 account := user.Account.(*vmess.MemoryAccount) 331 return &protocol.CommandSwitchAccount{ 332 Port: port, 333 ID: account.ID.UUID(), 334 Level: user.Level, 335 ValidMin: byte(availableMin), 336 } 337 } 338 } 339 } 340 341 return nil 342 } 343 344 func init() { 345 common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { 346 return New(ctx, config.(*Config)) 347 })) 348 }