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  }