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