github.com/v2fly/v2ray-core/v4@v4.45.2/proxy/vless/inbound/inbound.go (about)

     1  //go:build !confonly
     2  // +build !confonly
     3  
     4  package inbound
     5  
     6  //go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
     7  
     8  import (
     9  	"context"
    10  	"io"
    11  	"strconv"
    12  	"time"
    13  
    14  	core "github.com/v2fly/v2ray-core/v4"
    15  	"github.com/v2fly/v2ray-core/v4/common"
    16  	"github.com/v2fly/v2ray-core/v4/common/buf"
    17  	"github.com/v2fly/v2ray-core/v4/common/errors"
    18  	"github.com/v2fly/v2ray-core/v4/common/log"
    19  	"github.com/v2fly/v2ray-core/v4/common/net"
    20  	"github.com/v2fly/v2ray-core/v4/common/protocol"
    21  	"github.com/v2fly/v2ray-core/v4/common/retry"
    22  	"github.com/v2fly/v2ray-core/v4/common/session"
    23  	"github.com/v2fly/v2ray-core/v4/common/signal"
    24  	"github.com/v2fly/v2ray-core/v4/common/task"
    25  	"github.com/v2fly/v2ray-core/v4/features/dns"
    26  	feature_inbound "github.com/v2fly/v2ray-core/v4/features/inbound"
    27  	"github.com/v2fly/v2ray-core/v4/features/policy"
    28  	"github.com/v2fly/v2ray-core/v4/features/routing"
    29  	"github.com/v2fly/v2ray-core/v4/proxy/vless"
    30  	"github.com/v2fly/v2ray-core/v4/proxy/vless/encoding"
    31  	"github.com/v2fly/v2ray-core/v4/transport/internet"
    32  	"github.com/v2fly/v2ray-core/v4/transport/internet/tls"
    33  )
    34  
    35  func init() {
    36  	common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
    37  		var dc dns.Client
    38  		if err := core.RequireFeatures(ctx, func(d dns.Client) error {
    39  			dc = d
    40  			return nil
    41  		}); err != nil {
    42  			return nil, err
    43  		}
    44  		return New(ctx, config.(*Config), dc)
    45  	}))
    46  }
    47  
    48  // Handler is an inbound connection handler that handles messages in VLess protocol.
    49  type Handler struct {
    50  	inboundHandlerManager feature_inbound.Manager
    51  	policyManager         policy.Manager
    52  	validator             *vless.Validator
    53  	dns                   dns.Client
    54  	fallbacks             map[string]map[string]*Fallback // or nil
    55  	// regexps               map[string]*regexp.Regexp       // or nil
    56  }
    57  
    58  // New creates a new VLess inbound handler.
    59  func New(ctx context.Context, config *Config, dc dns.Client) (*Handler, error) {
    60  	v := core.MustFromContext(ctx)
    61  	handler := &Handler{
    62  		inboundHandlerManager: v.GetFeature(feature_inbound.ManagerType()).(feature_inbound.Manager),
    63  		policyManager:         v.GetFeature(policy.ManagerType()).(policy.Manager),
    64  		validator:             new(vless.Validator),
    65  		dns:                   dc,
    66  	}
    67  
    68  	for _, user := range config.Clients {
    69  		u, err := user.ToMemoryUser()
    70  		if err != nil {
    71  			return nil, newError("failed to get VLESS user").Base(err).AtError()
    72  		}
    73  		if err := handler.AddUser(ctx, u); err != nil {
    74  			return nil, newError("failed to initiate user").Base(err).AtError()
    75  		}
    76  	}
    77  
    78  	if config.Fallbacks != nil {
    79  		handler.fallbacks = make(map[string]map[string]*Fallback)
    80  		// handler.regexps = make(map[string]*regexp.Regexp)
    81  		for _, fb := range config.Fallbacks {
    82  			if handler.fallbacks[fb.Alpn] == nil {
    83  				handler.fallbacks[fb.Alpn] = make(map[string]*Fallback)
    84  			}
    85  			handler.fallbacks[fb.Alpn][fb.Path] = fb
    86  			/*
    87  				if fb.Path != "" {
    88  					if r, err := regexp.Compile(fb.Path); err != nil {
    89  						return nil, newError("invalid path regexp").Base(err).AtError()
    90  					} else {
    91  						handler.regexps[fb.Path] = r
    92  					}
    93  				}
    94  			*/
    95  		}
    96  		if handler.fallbacks[""] != nil {
    97  			for alpn, pfb := range handler.fallbacks {
    98  				if alpn != "" { // && alpn != "h2" {
    99  					for path, fb := range handler.fallbacks[""] {
   100  						if pfb[path] == nil {
   101  							pfb[path] = fb
   102  						}
   103  					}
   104  				}
   105  			}
   106  		}
   107  	}
   108  
   109  	return handler, nil
   110  }
   111  
   112  // Close implements common.Closable.Close().
   113  func (h *Handler) Close() error {
   114  	return errors.Combine(common.Close(h.validator))
   115  }
   116  
   117  // AddUser implements proxy.UserManager.AddUser().
   118  func (h *Handler) AddUser(ctx context.Context, u *protocol.MemoryUser) error {
   119  	return h.validator.Add(u)
   120  }
   121  
   122  // RemoveUser implements proxy.UserManager.RemoveUser().
   123  func (h *Handler) RemoveUser(ctx context.Context, e string) error {
   124  	return h.validator.Del(e)
   125  }
   126  
   127  // Network implements proxy.Inbound.Network().
   128  func (*Handler) Network() []net.Network {
   129  	return []net.Network{net.Network_TCP, net.Network_UNIX}
   130  }
   131  
   132  // Process implements proxy.Inbound.Process().
   133  func (h *Handler) Process(ctx context.Context, network net.Network, connection internet.Connection, dispatcher routing.Dispatcher) error {
   134  	sid := session.ExportIDToError(ctx)
   135  
   136  	iConn := connection
   137  	statConn, ok := iConn.(*internet.StatCouterConnection)
   138  	if ok {
   139  		iConn = statConn.Connection
   140  	}
   141  
   142  	sessionPolicy := h.policyManager.ForLevel(0)
   143  	if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
   144  		return newError("unable to set read deadline").Base(err).AtWarning()
   145  	}
   146  
   147  	first := buf.New()
   148  	defer first.Release()
   149  
   150  	firstLen, _ := first.ReadFrom(connection)
   151  	newError("firstLen = ", firstLen).AtInfo().WriteToLog(sid)
   152  
   153  	reader := &buf.BufferedReader{
   154  		Reader: buf.NewReader(connection),
   155  		Buffer: buf.MultiBuffer{first},
   156  	}
   157  
   158  	var request *protocol.RequestHeader
   159  	var requestAddons *encoding.Addons
   160  	var err error
   161  
   162  	apfb := h.fallbacks
   163  	isfb := apfb != nil
   164  
   165  	if isfb && firstLen < 18 {
   166  		err = newError("fallback directly")
   167  	} else {
   168  		request, requestAddons, isfb, err = encoding.DecodeRequestHeader(isfb, first, reader, h.validator)
   169  	}
   170  
   171  	if err != nil {
   172  		if isfb {
   173  			if err := connection.SetReadDeadline(time.Time{}); err != nil {
   174  				newError("unable to set back read deadline").Base(err).AtWarning().WriteToLog(sid)
   175  			}
   176  			newError("fallback starts").Base(err).AtInfo().WriteToLog(sid)
   177  
   178  			alpn := ""
   179  			if len(apfb) > 1 || apfb[""] == nil {
   180  				if tlsConn, ok := iConn.(*tls.Conn); ok {
   181  					alpn = tlsConn.ConnectionState().NegotiatedProtocol
   182  					newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
   183  				}
   184  				if apfb[alpn] == nil {
   185  					alpn = ""
   186  				}
   187  			}
   188  			pfb := apfb[alpn]
   189  			if pfb == nil {
   190  				return newError(`failed to find the default "alpn" config`).AtWarning()
   191  			}
   192  
   193  			path := ""
   194  			if len(pfb) > 1 || pfb[""] == nil {
   195  				/*
   196  					if lines := bytes.Split(firstBytes, []byte{'\r', '\n'}); len(lines) > 1 {
   197  						if s := bytes.Split(lines[0], []byte{' '}); len(s) == 3 {
   198  							if len(s[0]) < 8 && len(s[1]) > 0 && len(s[2]) == 8 {
   199  								newError("realPath = " + string(s[1])).AtInfo().WriteToLog(sid)
   200  								for _, fb := range pfb {
   201  									if fb.Path != "" && h.regexps[fb.Path].Match(s[1]) {
   202  										path = fb.Path
   203  										break
   204  									}
   205  								}
   206  							}
   207  						}
   208  					}
   209  				*/
   210  				if firstLen >= 18 && first.Byte(4) != '*' { // not h2c
   211  					firstBytes := first.Bytes()
   212  					for i := 4; i <= 8; i++ { // 5 -> 9
   213  						if firstBytes[i] == '/' && firstBytes[i-1] == ' ' {
   214  							search := len(firstBytes)
   215  							if search > 64 {
   216  								search = 64 // up to about 60
   217  							}
   218  							for j := i + 1; j < search; j++ {
   219  								k := firstBytes[j]
   220  								if k == '\r' || k == '\n' { // avoid logging \r or \n
   221  									break
   222  								}
   223  								if k == ' ' {
   224  									path = string(firstBytes[i:j])
   225  									newError("realPath = " + path).AtInfo().WriteToLog(sid)
   226  									if pfb[path] == nil {
   227  										path = ""
   228  									}
   229  									break
   230  								}
   231  							}
   232  							break
   233  						}
   234  					}
   235  				}
   236  			}
   237  			fb := pfb[path]
   238  			if fb == nil {
   239  				return newError(`failed to find the default "path" config`).AtWarning()
   240  			}
   241  
   242  			ctx, cancel := context.WithCancel(ctx)
   243  			timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
   244  			ctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer)
   245  
   246  			var conn net.Conn
   247  			if err := retry.ExponentialBackoff(5, 100).On(func() error {
   248  				var dialer net.Dialer
   249  				conn, err = dialer.DialContext(ctx, fb.Type, fb.Dest)
   250  				if err != nil {
   251  					return err
   252  				}
   253  				return nil
   254  			}); err != nil {
   255  				return newError("failed to dial to " + fb.Dest).Base(err).AtWarning()
   256  			}
   257  			defer conn.Close()
   258  
   259  			serverReader := buf.NewReader(conn)
   260  			serverWriter := buf.NewWriter(conn)
   261  
   262  			postRequest := func() error {
   263  				defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
   264  				if fb.Xver != 0 {
   265  					remoteAddr, remotePort, err := net.SplitHostPort(connection.RemoteAddr().String())
   266  					if err != nil {
   267  						return err
   268  					}
   269  					localAddr, localPort, err := net.SplitHostPort(connection.LocalAddr().String())
   270  					if err != nil {
   271  						return err
   272  					}
   273  					ipv4 := true
   274  					for i := 0; i < len(remoteAddr); i++ {
   275  						if remoteAddr[i] == ':' {
   276  							ipv4 = false
   277  							break
   278  						}
   279  					}
   280  					pro := buf.New()
   281  					defer pro.Release()
   282  					switch fb.Xver {
   283  					case 1:
   284  						if ipv4 {
   285  							pro.Write([]byte("PROXY TCP4 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n"))
   286  						} else {
   287  							pro.Write([]byte("PROXY TCP6 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n"))
   288  						}
   289  
   290  					case 2:
   291  						pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x21")) // signature + v2 + PROXY
   292  						if ipv4 {
   293  							pro.Write([]byte("\x11\x00\x0C")) // AF_INET + STREAM + 12 bytes
   294  							pro.Write(net.ParseIP(remoteAddr).To4())
   295  							pro.Write(net.ParseIP(localAddr).To4())
   296  						} else {
   297  							pro.Write([]byte("\x21\x00\x24")) // AF_INET6 + STREAM + 36 bytes
   298  							pro.Write(net.ParseIP(remoteAddr).To16())
   299  							pro.Write(net.ParseIP(localAddr).To16())
   300  						}
   301  						p1, _ := strconv.ParseUint(remotePort, 10, 16)
   302  						p2, _ := strconv.ParseUint(localPort, 10, 16)
   303  						pro.Write([]byte{byte(p1 >> 8), byte(p1), byte(p2 >> 8), byte(p2)})
   304  					}
   305  					if err := serverWriter.WriteMultiBuffer(buf.MultiBuffer{pro}); err != nil {
   306  						return newError("failed to set PROXY protocol v", fb.Xver).Base(err).AtWarning()
   307  					}
   308  				}
   309  				if err := buf.Copy(reader, serverWriter, buf.UpdateActivity(timer)); err != nil {
   310  					return newError("failed to fallback request payload").Base(err).AtInfo()
   311  				}
   312  				return nil
   313  			}
   314  
   315  			writer := buf.NewWriter(connection)
   316  
   317  			getResponse := func() error {
   318  				defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
   319  				if err := buf.Copy(serverReader, writer, buf.UpdateActivity(timer)); err != nil {
   320  					return newError("failed to deliver response payload").Base(err).AtInfo()
   321  				}
   322  				return nil
   323  			}
   324  
   325  			if err := task.Run(ctx, task.OnSuccess(postRequest, task.Close(serverWriter)), task.OnSuccess(getResponse, task.Close(writer))); err != nil {
   326  				common.Interrupt(serverReader)
   327  				common.Interrupt(serverWriter)
   328  				return newError("fallback ends").Base(err).AtInfo()
   329  			}
   330  			return nil
   331  		}
   332  
   333  		if errors.Cause(err) != io.EOF {
   334  			log.Record(&log.AccessMessage{
   335  				From:   connection.RemoteAddr(),
   336  				To:     "",
   337  				Status: log.AccessRejected,
   338  				Reason: err,
   339  			})
   340  			err = newError("invalid request from ", connection.RemoteAddr()).Base(err).AtInfo()
   341  		}
   342  		return err
   343  	}
   344  
   345  	if err := connection.SetReadDeadline(time.Time{}); err != nil {
   346  		newError("unable to set back read deadline").Base(err).AtWarning().WriteToLog(sid)
   347  	}
   348  	newError("received request for ", request.Destination()).AtInfo().WriteToLog(sid)
   349  
   350  	inbound := session.InboundFromContext(ctx)
   351  	if inbound == nil {
   352  		panic("no inbound metadata")
   353  	}
   354  	inbound.User = request.User
   355  
   356  	responseAddons := &encoding.Addons{}
   357  
   358  	if request.Command != protocol.RequestCommandMux {
   359  		ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
   360  			From:   connection.RemoteAddr(),
   361  			To:     request.Destination(),
   362  			Status: log.AccessAccepted,
   363  			Reason: "",
   364  			Email:  request.User.Email,
   365  		})
   366  	}
   367  
   368  	sessionPolicy = h.policyManager.ForLevel(request.User.Level)
   369  	ctx, cancel := context.WithCancel(ctx)
   370  	timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
   371  	ctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer)
   372  
   373  	link, err := dispatcher.Dispatch(ctx, request.Destination())
   374  	if err != nil {
   375  		return newError("failed to dispatch request to ", request.Destination()).Base(err).AtWarning()
   376  	}
   377  
   378  	serverReader := link.Reader // .(*pipe.Reader)
   379  	serverWriter := link.Writer // .(*pipe.Writer)
   380  
   381  	postRequest := func() error {
   382  		defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
   383  
   384  		// default: clientReader := reader
   385  		clientReader := encoding.DecodeBodyAddons(reader, request, requestAddons)
   386  
   387  		// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBufer
   388  		if err := buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer)); err != nil {
   389  			return newError("failed to transfer request payload").Base(err).AtInfo()
   390  		}
   391  
   392  		return nil
   393  	}
   394  
   395  	getResponse := func() error {
   396  		defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
   397  
   398  		bufferWriter := buf.NewBufferedWriter(buf.NewWriter(connection))
   399  		if err := encoding.EncodeResponseHeader(bufferWriter, request, responseAddons); err != nil {
   400  			return newError("failed to encode response header").Base(err).AtWarning()
   401  		}
   402  
   403  		// default: clientWriter := bufferWriter
   404  		clientWriter := encoding.EncodeBodyAddons(bufferWriter, request, responseAddons)
   405  		{
   406  			multiBuffer, err := serverReader.ReadMultiBuffer()
   407  			if err != nil {
   408  				return err // ...
   409  			}
   410  			if err := clientWriter.WriteMultiBuffer(multiBuffer); err != nil {
   411  				return err // ...
   412  			}
   413  		}
   414  
   415  		// Flush; bufferWriter.WriteMultiBufer now is bufferWriter.writer.WriteMultiBuffer
   416  		if err := bufferWriter.SetBuffered(false); err != nil {
   417  			return newError("failed to write A response payload").Base(err).AtWarning()
   418  		}
   419  
   420  		// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBufer
   421  		if err := buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer)); err != nil {
   422  			return newError("failed to transfer response payload").Base(err).AtInfo()
   423  		}
   424  
   425  		return nil
   426  	}
   427  
   428  	if err := task.Run(ctx, task.OnSuccess(postRequest, task.Close(serverWriter)), getResponse); err != nil {
   429  		common.Interrupt(serverReader)
   430  		common.Interrupt(serverWriter)
   431  		return newError("connection ends").Base(err).AtInfo()
   432  	}
   433  
   434  	return nil
   435  }