github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/app/proxyman/inbound/always.go (about)

     1  package inbound
     2  
     3  import (
     4  	"context"
     5  
     6  	"v2ray.com/core"
     7  	"v2ray.com/core/app/proxyman"
     8  	"v2ray.com/core/common"
     9  	"v2ray.com/core/common/dice"
    10  	"v2ray.com/core/common/errors"
    11  	"v2ray.com/core/common/mux"
    12  	"v2ray.com/core/common/net"
    13  	"v2ray.com/core/features/policy"
    14  	"v2ray.com/core/features/stats"
    15  	"v2ray.com/core/proxy"
    16  	"v2ray.com/core/transport/internet"
    17  )
    18  
    19  func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
    20  	var uplinkCounter stats.Counter
    21  	var downlinkCounter stats.Counter
    22  
    23  	policy := v.GetFeature(policy.ManagerType()).(policy.Manager)
    24  	if len(tag) > 0 && policy.ForSystem().Stats.InboundUplink {
    25  		statsManager := v.GetFeature(stats.ManagerType()).(stats.Manager)
    26  		name := "inbound>>>" + tag + ">>>traffic>>>uplink"
    27  		c, _ := stats.GetOrRegisterCounter(statsManager, name)
    28  		if c != nil {
    29  			uplinkCounter = c
    30  		}
    31  	}
    32  	if len(tag) > 0 && policy.ForSystem().Stats.InboundDownlink {
    33  		statsManager := v.GetFeature(stats.ManagerType()).(stats.Manager)
    34  		name := "inbound>>>" + tag + ">>>traffic>>>downlink"
    35  		c, _ := stats.GetOrRegisterCounter(statsManager, name)
    36  		if c != nil {
    37  			downlinkCounter = c
    38  		}
    39  	}
    40  
    41  	return uplinkCounter, downlinkCounter
    42  }
    43  
    44  type AlwaysOnInboundHandler struct {
    45  	proxy   proxy.Inbound
    46  	workers []worker
    47  	mux     *mux.Server
    48  	tag     string
    49  }
    50  
    51  func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*AlwaysOnInboundHandler, error) {
    52  	rawProxy, err := common.CreateObject(ctx, proxyConfig)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  	p, ok := rawProxy.(proxy.Inbound)
    57  	if !ok {
    58  		return nil, newError("not an inbound proxy.")
    59  	}
    60  
    61  	h := &AlwaysOnInboundHandler{
    62  		proxy: p,
    63  		mux:   mux.NewServer(ctx),
    64  		tag:   tag,
    65  	}
    66  
    67  	uplinkCounter, downlinkCounter := getStatCounter(core.MustFromContext(ctx), tag)
    68  
    69  	nl := p.Network()
    70  	pr := receiverConfig.PortRange
    71  	address := receiverConfig.Listen.AsAddress()
    72  	if address == nil {
    73  		address = net.AnyIP
    74  	}
    75  
    76  	mss, err := internet.ToMemoryStreamConfig(receiverConfig.StreamSettings)
    77  	if err != nil {
    78  		return nil, newError("failed to parse stream config").Base(err).AtWarning()
    79  	}
    80  
    81  	if receiverConfig.ReceiveOriginalDestination {
    82  		if mss.SocketSettings == nil {
    83  			mss.SocketSettings = &internet.SocketConfig{}
    84  		}
    85  		if mss.SocketSettings.Tproxy == internet.SocketConfig_Off {
    86  			mss.SocketSettings.Tproxy = internet.SocketConfig_Redirect
    87  		}
    88  		mss.SocketSettings.ReceiveOriginalDestAddress = true
    89  	}
    90  
    91  	for port := pr.From; port <= pr.To; port++ {
    92  		if net.HasNetwork(nl, net.Network_TCP) {
    93  			newError("creating stream worker on ", address, ":", port).AtDebug().WriteToLog()
    94  
    95  			worker := &tcpWorker{
    96  				address:         address,
    97  				port:            net.Port(port),
    98  				proxy:           p,
    99  				stream:          mss,
   100  				recvOrigDest:    receiverConfig.ReceiveOriginalDestination,
   101  				tag:             tag,
   102  				dispatcher:      h.mux,
   103  				sniffingConfig:  receiverConfig.GetEffectiveSniffingSettings(),
   104  				uplinkCounter:   uplinkCounter,
   105  				downlinkCounter: downlinkCounter,
   106  				ctx:             ctx,
   107  			}
   108  			h.workers = append(h.workers, worker)
   109  		}
   110  
   111  		if net.HasNetwork(nl, net.Network_UDP) {
   112  			worker := &udpWorker{
   113  				tag:             tag,
   114  				proxy:           p,
   115  				address:         address,
   116  				port:            net.Port(port),
   117  				dispatcher:      h.mux,
   118  				uplinkCounter:   uplinkCounter,
   119  				downlinkCounter: downlinkCounter,
   120  				stream:          mss,
   121  			}
   122  			h.workers = append(h.workers, worker)
   123  		}
   124  	}
   125  
   126  	return h, nil
   127  }
   128  
   129  // Start implements common.Runnable.
   130  func (h *AlwaysOnInboundHandler) Start() error {
   131  	for _, worker := range h.workers {
   132  		if err := worker.Start(); err != nil {
   133  			return err
   134  		}
   135  	}
   136  	return nil
   137  }
   138  
   139  // Close implements common.Closable.
   140  func (h *AlwaysOnInboundHandler) Close() error {
   141  	var errs []error
   142  	for _, worker := range h.workers {
   143  		errs = append(errs, worker.Close())
   144  	}
   145  	errs = append(errs, h.mux.Close())
   146  	if err := errors.Combine(errs...); err != nil {
   147  		return newError("failed to close all resources").Base(err)
   148  	}
   149  	return nil
   150  }
   151  
   152  func (h *AlwaysOnInboundHandler) GetRandomInboundProxy() (interface{}, net.Port, int) {
   153  	if len(h.workers) == 0 {
   154  		return nil, 0, 0
   155  	}
   156  	w := h.workers[dice.Roll(len(h.workers))]
   157  	return w.Proxy(), w.Port(), 9999
   158  }
   159  
   160  func (h *AlwaysOnInboundHandler) Tag() string {
   161  	return h.tag
   162  }
   163  
   164  func (h *AlwaysOnInboundHandler) GetInbound() proxy.Inbound {
   165  	return h.proxy
   166  }