github.com/sagernet/sing-box@v1.9.0-rc.20/inbound/vmess.go (about)

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