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  }