github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/inbound/shadowsocks_relay.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/shadowaead_2022" 13 "github.com/sagernet/sing/common" 14 "github.com/sagernet/sing/common/auth" 15 "github.com/sagernet/sing/common/buf" 16 F "github.com/sagernet/sing/common/format" 17 N "github.com/sagernet/sing/common/network" 18 ) 19 20 var ( 21 _ adapter.Inbound = (*ShadowsocksRelay)(nil) 22 _ adapter.InjectableInbound = (*ShadowsocksRelay)(nil) 23 ) 24 25 type ShadowsocksRelay struct { 26 myInboundAdapter 27 service *shadowaead_2022.RelayService[int] 28 destinations []option.ShadowsocksDestination 29 } 30 31 func newShadowsocksRelay(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksInboundOptions) (*ShadowsocksRelay, error) { 32 inbound := &ShadowsocksRelay{ 33 myInboundAdapter: myInboundAdapter{ 34 protocol: C.TypeShadowsocks, 35 network: options.Network.Build(), 36 ctx: ctx, 37 router: router, 38 logger: logger, 39 tag: tag, 40 listenOptions: options.ListenOptions, 41 }, 42 destinations: options.Destinations, 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 service, err := shadowaead_2022.NewRelayServiceWithPassword[int]( 53 options.Method, 54 options.Password, 55 udpTimeout, 56 adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound), 57 ) 58 if err != nil { 59 return nil, err 60 } 61 err = service.UpdateUsersWithPasswords(common.MapIndexed(options.Destinations, func(index int, user option.ShadowsocksDestination) int { 62 return index 63 }), common.Map(options.Destinations, func(user option.ShadowsocksDestination) string { 64 return user.Password 65 }), common.Map(options.Destinations, option.ShadowsocksDestination.Build)) 66 if err != nil { 67 return nil, err 68 } 69 inbound.service = service 70 inbound.packetUpstream = service 71 return inbound, err 72 } 73 74 func (h *ShadowsocksRelay) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { 75 return h.service.NewConnection(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, adapter.UpstreamMetadata(metadata)) 76 } 77 78 func (h *ShadowsocksRelay) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error { 79 return h.service.NewPacket(adapter.WithContext(ctx, &metadata), conn, buffer, adapter.UpstreamMetadata(metadata)) 80 } 81 82 func (h *ShadowsocksRelay) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { 83 return os.ErrInvalid 84 } 85 86 func (h *ShadowsocksRelay) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { 87 destinationIndex, loaded := auth.UserFromContext[int](ctx) 88 if !loaded { 89 return os.ErrInvalid 90 } 91 destination := h.destinations[destinationIndex].Name 92 if destination == "" { 93 destination = F.ToString(destinationIndex) 94 } else { 95 metadata.User = destination 96 } 97 h.logger.InfoContext(ctx, "[", destination, "] inbound connection to ", metadata.Destination) 98 return h.router.RouteConnection(ctx, conn, metadata) 99 } 100 101 func (h *ShadowsocksRelay) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { 102 destinationIndex, loaded := auth.UserFromContext[int](ctx) 103 if !loaded { 104 return os.ErrInvalid 105 } 106 destination := h.destinations[destinationIndex].Name 107 if destination == "" { 108 destination = F.ToString(destinationIndex) 109 } else { 110 metadata.User = destination 111 } 112 ctx = log.ContextWithNewID(ctx) 113 h.logger.InfoContext(ctx, "[", destination, "] inbound packet connection from ", metadata.Source) 114 h.logger.InfoContext(ctx, "[", destination, "] inbound packet connection to ", metadata.Destination) 115 return h.router.RoutePacketConnection(ctx, conn, metadata) 116 }