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