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  }