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