github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/inbound/vmess.go (about)

     1  package inbound
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  	"os"
     7  
     8  	"github.com/inazumav/sing-box/adapter"
     9  	"github.com/inazumav/sing-box/common/tls"
    10  	C "github.com/inazumav/sing-box/constant"
    11  	"github.com/inazumav/sing-box/log"
    12  	"github.com/inazumav/sing-box/option"
    13  	"github.com/inazumav/sing-box/transport/v2ray"
    14  	"github.com/sagernet/sing-vmess"
    15  	"github.com/sagernet/sing-vmess/packetaddr"
    16  	"github.com/sagernet/sing/common"
    17  	"github.com/sagernet/sing/common/auth"
    18  	E "github.com/sagernet/sing/common/exceptions"
    19  	F "github.com/sagernet/sing/common/format"
    20  	M "github.com/sagernet/sing/common/metadata"
    21  	N "github.com/sagernet/sing/common/network"
    22  	"github.com/sagernet/sing/common/ntp"
    23  )
    24  
    25  var (
    26  	_ adapter.Inbound           = (*VMess)(nil)
    27  	_ adapter.InjectableInbound = (*VMess)(nil)
    28  )
    29  
    30  type VMess struct {
    31  	myInboundAdapter
    32  	ctx       context.Context
    33  	service   *vmess.Service[int]
    34  	users     []option.VMessUser
    35  	tlsConfig tls.ServerConfig
    36  	transport adapter.V2RayServerTransport
    37  }
    38  
    39  func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.VMessInboundOptions) (*VMess, error) {
    40  	inbound := &VMess{
    41  		myInboundAdapter: myInboundAdapter{
    42  			protocol:      C.TypeVMess,
    43  			network:       []string{N.NetworkTCP},
    44  			ctx:           ctx,
    45  			router:        router,
    46  			logger:        logger,
    47  			tag:           tag,
    48  			listenOptions: options.ListenOptions,
    49  		},
    50  		ctx:   ctx,
    51  		users: options.Users,
    52  	}
    53  	var serviceOptions []vmess.ServiceOption
    54  	if timeFunc := ntp.TimeFuncFromContext(ctx); timeFunc != nil {
    55  		serviceOptions = append(serviceOptions, vmess.ServiceWithTimeFunc(timeFunc))
    56  	}
    57  	if options.Transport != nil && options.Transport.Type != "" {
    58  		serviceOptions = append(serviceOptions, vmess.ServiceWithDisableHeaderProtection())
    59  	}
    60  	service := vmess.NewService[int](adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound), serviceOptions...)
    61  	inbound.service = service
    62  	err := service.UpdateUsers(common.MapIndexed(options.Users, func(index int, it option.VMessUser) int {
    63  		return index
    64  	}), common.Map(options.Users, func(it option.VMessUser) string {
    65  		return it.UUID
    66  	}), common.Map(options.Users, func(it option.VMessUser) int {
    67  		return it.AlterId
    68  	}))
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  	if options.TLS != nil {
    73  		inbound.tlsConfig, err = tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
    74  		if err != nil {
    75  			return nil, err
    76  		}
    77  	}
    78  	if options.Transport != nil {
    79  		inbound.transport, err = v2ray.NewServerTransport(ctx, common.PtrValueOrDefault(options.Transport), inbound.tlsConfig, (*vmessTransportHandler)(inbound))
    80  		if err != nil {
    81  			return nil, E.Cause(err, "create server transport: ", options.Transport.Type)
    82  		}
    83  	}
    84  	inbound.connHandler = inbound
    85  	return inbound, nil
    86  }
    87  
    88  func (h *VMess) Start() error {
    89  	err := common.Start(
    90  		h.service,
    91  		h.tlsConfig,
    92  	)
    93  	if err != nil {
    94  		return err
    95  	}
    96  	if h.transport == nil {
    97  		return h.myInboundAdapter.Start()
    98  	}
    99  	if common.Contains(h.transport.Network(), N.NetworkTCP) {
   100  		tcpListener, err := h.myInboundAdapter.ListenTCP()
   101  		if err != nil {
   102  			return err
   103  		}
   104  		go func() {
   105  			sErr := h.transport.Serve(tcpListener)
   106  			if sErr != nil && !E.IsClosed(sErr) {
   107  				h.logger.Error("transport serve error: ", sErr)
   108  			}
   109  		}()
   110  	}
   111  	if common.Contains(h.transport.Network(), N.NetworkUDP) {
   112  		udpConn, err := h.myInboundAdapter.ListenUDP()
   113  		if err != nil {
   114  			return err
   115  		}
   116  		go func() {
   117  			sErr := h.transport.ServePacket(udpConn)
   118  			if sErr != nil && !E.IsClosed(sErr) {
   119  				h.logger.Error("transport serve error: ", sErr)
   120  			}
   121  		}()
   122  	}
   123  	return nil
   124  }
   125  
   126  func (h *VMess) AddUsers(users []option.VMessUser) error {
   127  	if cap(h.users)-len(h.users) >= len(users) {
   128  		h.users = append(h.users, users...)
   129  	} else {
   130  		tmp := make([]option.VMessUser, 0, len(h.users)+len(users)+10)
   131  		tmp = append(tmp, h.users...)
   132  		tmp = append(tmp, users...)
   133  		h.users = tmp
   134  	}
   135  	err := h.service.UpdateUsers(common.MapIndexed(h.users, func(index int, it option.VMessUser) int {
   136  		return index
   137  	}), common.Map(h.users, func(it option.VMessUser) string {
   138  		return it.UUID
   139  	}), common.Map(h.users, func(it option.VMessUser) int {
   140  		return it.AlterId
   141  	}))
   142  	if err != nil {
   143  		return err
   144  	}
   145  	return nil
   146  }
   147  
   148  func (h *VMess) DelUsers(name []string) error {
   149  	is := make([]int, 0, len(name))
   150  	ulen := len(name)
   151  	for i := range h.users {
   152  		for _, u := range name {
   153  			if h.users[i].Name == u {
   154  				is = append(is, i)
   155  				ulen--
   156  			}
   157  			if ulen == 0 {
   158  				break
   159  			}
   160  		}
   161  	}
   162  	ulen = len(h.users)
   163  	for _, i := range is {
   164  		h.users[i] = h.users[ulen-1]
   165  		h.users[ulen-1] = option.VMessUser{}
   166  		h.users = h.users[:ulen-1]
   167  		ulen--
   168  	}
   169  	err := h.service.UpdateUsers(common.MapIndexed(h.users, func(index int, it option.VMessUser) int {
   170  		return index
   171  	}), common.Map(h.users, func(it option.VMessUser) string {
   172  		return it.UUID
   173  	}), common.Map(h.users, func(it option.VMessUser) int {
   174  		return it.AlterId
   175  	}))
   176  	if err != nil {
   177  		return err
   178  	}
   179  	return nil
   180  }
   181  
   182  func (h *VMess) Close() error {
   183  	return common.Close(
   184  		h.service,
   185  		&h.myInboundAdapter,
   186  		h.tlsConfig,
   187  		h.transport,
   188  	)
   189  }
   190  
   191  func (h *VMess) newTransportConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
   192  	h.injectTCP(conn, metadata)
   193  	return nil
   194  }
   195  
   196  func (h *VMess) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
   197  	var err error
   198  	if h.tlsConfig != nil && h.transport == nil {
   199  		conn, err = tls.ServerHandshake(ctx, conn, h.tlsConfig)
   200  		if err != nil {
   201  			return err
   202  		}
   203  	}
   204  	return h.service.NewConnection(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, adapter.UpstreamMetadata(metadata))
   205  }
   206  
   207  func (h *VMess) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
   208  	return os.ErrInvalid
   209  }
   210  
   211  func (h *VMess) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
   212  	userIndex, loaded := auth.UserFromContext[int](ctx)
   213  	if !loaded {
   214  		return os.ErrInvalid
   215  	}
   216  	user := h.users[userIndex].Name
   217  	if user == "" {
   218  		user = F.ToString(userIndex)
   219  	} else {
   220  		metadata.User = user
   221  	}
   222  	h.logger.InfoContext(ctx, "[", user, "] inbound connection to ", metadata.Destination)
   223  	return h.router.RouteConnection(ctx, conn, metadata)
   224  }
   225  
   226  func (h *VMess) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
   227  	userIndex, loaded := auth.UserFromContext[int](ctx)
   228  	if !loaded {
   229  		return os.ErrInvalid
   230  	}
   231  	user := h.users[userIndex].Name
   232  	if user == "" {
   233  		user = F.ToString(userIndex)
   234  	} else {
   235  		metadata.User = user
   236  	}
   237  	if metadata.Destination.Fqdn == packetaddr.SeqPacketMagicAddress {
   238  		metadata.Destination = M.Socksaddr{}
   239  		conn = packetaddr.NewConn(conn.(vmess.PacketConn), metadata.Destination)
   240  		h.logger.InfoContext(ctx, "[", user, "] inbound packet addr connection")
   241  	} else {
   242  		h.logger.InfoContext(ctx, "[", user, "] inbound packet connection to ", metadata.Destination)
   243  	}
   244  	return h.router.RoutePacketConnection(ctx, conn, metadata)
   245  }
   246  
   247  var _ adapter.V2RayServerTransportHandler = (*vmessTransportHandler)(nil)
   248  
   249  type vmessTransportHandler VMess
   250  
   251  func (t *vmessTransportHandler) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
   252  	return (*VMess)(t).newTransportConnection(ctx, conn, adapter.InboundContext{
   253  		Source:      metadata.Source,
   254  		Destination: metadata.Destination,
   255  	})
   256  }
   257  
   258  func (t *vmessTransportHandler) FallbackConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
   259  	return os.ErrInvalid
   260  }