github.com/sagernet/sing-box@v1.2.7/inbound/shadowsocks_multi.go (about) 1 package inbound 2 3 import ( 4 "context" 5 "net" 6 "os" 7 8 "github.com/sagernet/sing-box/adapter" 9 C "github.com/sagernet/sing-box/constant" 10 "github.com/sagernet/sing-box/log" 11 "github.com/sagernet/sing-box/option" 12 "github.com/sagernet/sing-shadowsocks/shadowaead_2022" 13 "github.com/sagernet/sing/common" 14 "github.com/sagernet/sing/common/auth" 15 "github.com/sagernet/sing/common/buf" 16 E "github.com/sagernet/sing/common/exceptions" 17 F "github.com/sagernet/sing/common/format" 18 N "github.com/sagernet/sing/common/network" 19 ) 20 21 var ( 22 _ adapter.Inbound = (*ShadowsocksMulti)(nil) 23 _ adapter.InjectableInbound = (*ShadowsocksMulti)(nil) 24 ) 25 26 type ShadowsocksMulti struct { 27 myInboundAdapter 28 service *shadowaead_2022.MultiService[int] 29 users []option.ShadowsocksUser 30 } 31 32 func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksInboundOptions) (*ShadowsocksMulti, error) { 33 inbound := &ShadowsocksMulti{ 34 myInboundAdapter: myInboundAdapter{ 35 protocol: C.TypeShadowsocks, 36 network: options.Network.Build(), 37 ctx: ctx, 38 router: router, 39 logger: logger, 40 tag: tag, 41 listenOptions: options.ListenOptions, 42 }, 43 } 44 inbound.connHandler = inbound 45 inbound.packetHandler = inbound 46 var udpTimeout int64 47 if options.UDPTimeout != 0 { 48 udpTimeout = options.UDPTimeout 49 } else { 50 udpTimeout = int64(C.UDPTimeout.Seconds()) 51 } 52 if !common.Contains(shadowaead_2022.List, options.Method) { 53 return nil, E.New("unsupported method: " + options.Method) 54 } 55 service, err := shadowaead_2022.NewMultiServiceWithPassword[int]( 56 options.Method, 57 options.Password, 58 udpTimeout, 59 adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound), 60 router.TimeFunc(), 61 ) 62 if err != nil { 63 return nil, err 64 } 65 err = service.UpdateUsersWithPasswords(common.MapIndexed(options.Users, func(index int, user option.ShadowsocksUser) int { 66 return index 67 }), common.Map(options.Users, func(user option.ShadowsocksUser) string { 68 return user.Password 69 })) 70 if err != nil { 71 return nil, err 72 } 73 inbound.service = service 74 inbound.packetUpstream = service 75 inbound.users = options.Users 76 return inbound, err 77 } 78 79 func (h *ShadowsocksMulti) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { 80 return h.service.NewConnection(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, adapter.UpstreamMetadata(metadata)) 81 } 82 83 func (h *ShadowsocksMulti) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error { 84 return h.service.NewPacket(adapter.WithContext(ctx, &metadata), conn, buffer, adapter.UpstreamMetadata(metadata)) 85 } 86 87 func (h *ShadowsocksMulti) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { 88 return os.ErrInvalid 89 } 90 91 func (h *ShadowsocksMulti) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { 92 userIndex, loaded := auth.UserFromContext[int](ctx) 93 if !loaded { 94 return os.ErrInvalid 95 } 96 user := h.users[userIndex].Name 97 if user == "" { 98 user = F.ToString(userIndex) 99 } else { 100 metadata.User = user 101 } 102 h.logger.InfoContext(ctx, "[", user, "] inbound connection to ", metadata.Destination) 103 return h.router.RouteConnection(ctx, conn, metadata) 104 } 105 106 func (h *ShadowsocksMulti) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { 107 userIndex, loaded := auth.UserFromContext[int](ctx) 108 if !loaded { 109 return os.ErrInvalid 110 } 111 user := h.users[userIndex].Name 112 if user == "" { 113 user = F.ToString(userIndex) 114 } else { 115 metadata.User = user 116 } 117 ctx = log.ContextWithNewID(ctx) 118 h.logger.InfoContext(ctx, "[", user, "] inbound packet connection from ", metadata.Source) 119 h.logger.InfoContext(ctx, "[", user, "] inbound packet connection to ", metadata.Destination) 120 return h.router.RoutePacketConnection(ctx, conn, metadata) 121 }