github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/inbound/shadowsocks_multi.go (about) 1 package inbound 2 3 import ( 4 "context" 5 "net" 6 "os" 7 8 "github.com/inazumav/sing-box/adapter" 9 C "github.com/inazumav/sing-box/constant" 10 "github.com/inazumav/sing-box/log" 11 "github.com/inazumav/sing-box/option" 12 "github.com/sagernet/sing-shadowsocks" 13 "github.com/sagernet/sing-shadowsocks/shadowaead" 14 "github.com/sagernet/sing-shadowsocks/shadowaead_2022" 15 "github.com/sagernet/sing/common" 16 "github.com/sagernet/sing/common/auth" 17 "github.com/sagernet/sing/common/buf" 18 E "github.com/sagernet/sing/common/exceptions" 19 F "github.com/sagernet/sing/common/format" 20 N "github.com/sagernet/sing/common/network" 21 "github.com/sagernet/sing/common/ntp" 22 ) 23 24 var ( 25 _ adapter.Inbound = (*ShadowsocksMulti)(nil) 26 _ adapter.InjectableInbound = (*ShadowsocksMulti)(nil) 27 ) 28 29 type ShadowsocksMulti struct { 30 myInboundAdapter 31 service shadowsocks.MultiService[int] 32 users []option.ShadowsocksUser 33 } 34 35 func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksInboundOptions) (*ShadowsocksMulti, error) { 36 inbound := &ShadowsocksMulti{ 37 myInboundAdapter: myInboundAdapter{ 38 protocol: C.TypeShadowsocks, 39 network: options.Network.Build(), 40 ctx: ctx, 41 router: router, 42 logger: logger, 43 tag: tag, 44 listenOptions: options.ListenOptions, 45 }, 46 } 47 inbound.connHandler = inbound 48 inbound.packetHandler = inbound 49 var udpTimeout int64 50 if options.UDPTimeout != 0 { 51 udpTimeout = options.UDPTimeout 52 } else { 53 udpTimeout = int64(C.UDPTimeout.Seconds()) 54 } 55 var ( 56 service shadowsocks.MultiService[int] 57 err error 58 ) 59 if common.Contains(shadowaead_2022.List, options.Method) { 60 service, err = shadowaead_2022.NewMultiServiceWithPassword[int]( 61 options.Method, 62 options.Password, 63 udpTimeout, 64 adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound), 65 ntp.TimeFuncFromContext(ctx), 66 ) 67 } else if common.Contains(shadowaead.List, options.Method) { 68 service, err = shadowaead.NewMultiService[int]( 69 options.Method, 70 udpTimeout, 71 adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound)) 72 } else { 73 return nil, E.New("unsupported method: " + options.Method) 74 } 75 if err != nil { 76 return nil, err 77 } 78 err = service.UpdateUsersWithPasswords(common.MapIndexed(options.Users, func(index int, user option.ShadowsocksUser) int { 79 return index 80 }), common.Map(options.Users, func(user option.ShadowsocksUser) string { 81 return user.Password 82 })) 83 if err != nil { 84 return nil, err 85 } 86 inbound.service = service 87 inbound.packetUpstream = service 88 inbound.users = options.Users 89 return inbound, err 90 } 91 92 func (h *ShadowsocksMulti) AddUsers(users []option.ShadowsocksUser) error { 93 if cap(h.users)-len(h.users) >= len(users) { 94 h.users = append(h.users, users...) 95 } else { 96 tmp := make([]option.ShadowsocksUser, 0, len(h.users)+len(users)+10) 97 tmp = append(tmp, h.users...) 98 tmp = append(tmp, users...) 99 h.users = tmp 100 } 101 err := h.service.UpdateUsersWithPasswords(common.MapIndexed(h.users, func(index int, user option.ShadowsocksUser) int { 102 return index 103 }), common.Map(h.users, func(user option.ShadowsocksUser) string { 104 return user.Password 105 })) 106 if err != nil { 107 return err 108 } 109 return nil 110 } 111 112 func (h *ShadowsocksMulti) DelUsers(name []string) error { 113 is := make([]int, 0, len(name)) 114 ulen := len(name) 115 for i := range h.users { 116 for _, n := range name { 117 if h.users[i].Name == n { 118 is = append(is, i) 119 ulen-- 120 } 121 if ulen == 0 { 122 break 123 } 124 } 125 } 126 ulen = len(h.users) 127 for _, i := range is { 128 h.users[i] = h.users[ulen-1] 129 h.users[ulen-1] = option.ShadowsocksUser{} 130 h.users = h.users[:ulen-1] 131 ulen-- 132 } 133 err := h.service.UpdateUsersWithPasswords(common.MapIndexed(h.users, func(index int, user option.ShadowsocksUser) int { 134 return index 135 }), common.Map(h.users, func(user option.ShadowsocksUser) string { 136 return user.Password 137 })) 138 return err 139 } 140 141 func (h *ShadowsocksMulti) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { 142 return h.service.NewConnection(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, adapter.UpstreamMetadata(metadata)) 143 } 144 145 func (h *ShadowsocksMulti) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error { 146 return h.service.NewPacket(adapter.WithContext(ctx, &metadata), conn, buffer, adapter.UpstreamMetadata(metadata)) 147 } 148 149 func (h *ShadowsocksMulti) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { 150 return os.ErrInvalid 151 } 152 153 func (h *ShadowsocksMulti) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { 154 userIndex, loaded := auth.UserFromContext[int](ctx) 155 if !loaded { 156 return os.ErrInvalid 157 } 158 user := h.users[userIndex].Name 159 if user == "" { 160 user = F.ToString(userIndex) 161 } else { 162 metadata.User = user 163 } 164 h.logger.InfoContext(ctx, "[", user, "] inbound connection to ", metadata.Destination) 165 return h.router.RouteConnection(ctx, conn, metadata) 166 } 167 168 func (h *ShadowsocksMulti) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { 169 userIndex, loaded := auth.UserFromContext[int](ctx) 170 if !loaded { 171 return os.ErrInvalid 172 } 173 user := h.users[userIndex].Name 174 if user == "" { 175 user = F.ToString(userIndex) 176 } else { 177 metadata.User = user 178 } 179 ctx = log.ContextWithNewID(ctx) 180 h.logger.InfoContext(ctx, "[", user, "] inbound packet connection from ", metadata.Source) 181 h.logger.InfoContext(ctx, "[", user, "] inbound packet connection to ", metadata.Destination) 182 return h.router.RoutePacketConnection(ctx, conn, metadata) 183 }