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

     1  //go:build !confonly
     2  // +build !confonly
     3  
     4  package freedom
     5  
     6  //go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
     7  
     8  import (
     9  	"context"
    10  	"time"
    11  
    12  	core "github.com/v2fly/v2ray-core/v4"
    13  	"github.com/v2fly/v2ray-core/v4/common"
    14  	"github.com/v2fly/v2ray-core/v4/common/buf"
    15  	"github.com/v2fly/v2ray-core/v4/common/dice"
    16  	"github.com/v2fly/v2ray-core/v4/common/net"
    17  	"github.com/v2fly/v2ray-core/v4/common/retry"
    18  	"github.com/v2fly/v2ray-core/v4/common/session"
    19  	"github.com/v2fly/v2ray-core/v4/common/signal"
    20  	"github.com/v2fly/v2ray-core/v4/common/task"
    21  	"github.com/v2fly/v2ray-core/v4/features/dns"
    22  	"github.com/v2fly/v2ray-core/v4/features/policy"
    23  	"github.com/v2fly/v2ray-core/v4/transport"
    24  	"github.com/v2fly/v2ray-core/v4/transport/internet"
    25  )
    26  
    27  func init() {
    28  	common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
    29  		h := new(Handler)
    30  		if err := core.RequireFeatures(ctx, func(pm policy.Manager, d dns.Client) error {
    31  			return h.Init(config.(*Config), pm, d)
    32  		}); err != nil {
    33  			return nil, err
    34  		}
    35  		return h, nil
    36  	}))
    37  }
    38  
    39  // Handler handles Freedom connections.
    40  type Handler struct {
    41  	policyManager policy.Manager
    42  	dns           dns.Client
    43  	config        *Config
    44  }
    45  
    46  // Init initializes the Handler with necessary parameters.
    47  func (h *Handler) Init(config *Config, pm policy.Manager, d dns.Client) error {
    48  	h.config = config
    49  	h.policyManager = pm
    50  	h.dns = d
    51  
    52  	return nil
    53  }
    54  
    55  func (h *Handler) policy() policy.Session {
    56  	p := h.policyManager.ForLevel(h.config.UserLevel)
    57  	if h.config.Timeout > 0 && h.config.UserLevel == 0 {
    58  		p.Timeouts.ConnectionIdle = time.Duration(h.config.Timeout) * time.Second
    59  	}
    60  	return p
    61  }
    62  
    63  func (h *Handler) resolveIP(ctx context.Context, domain string, localAddr net.Address) net.Address {
    64  	if c, ok := h.dns.(dns.ClientWithIPOption); ok {
    65  		c.SetFakeDNSOption(false) // Skip FakeDNS
    66  	} else {
    67  		newError("DNS client doesn't implement ClientWithIPOption")
    68  	}
    69  
    70  	lookupFunc := h.dns.LookupIP
    71  	if h.config.DomainStrategy == Config_USE_IP4 || (localAddr != nil && localAddr.Family().IsIPv4()) {
    72  		if lookupIPv4, ok := h.dns.(dns.IPv4Lookup); ok {
    73  			lookupFunc = lookupIPv4.LookupIPv4
    74  		}
    75  	} else if h.config.DomainStrategy == Config_USE_IP6 || (localAddr != nil && localAddr.Family().IsIPv6()) {
    76  		if lookupIPv6, ok := h.dns.(dns.IPv6Lookup); ok {
    77  			lookupFunc = lookupIPv6.LookupIPv6
    78  		}
    79  	}
    80  
    81  	ips, err := lookupFunc(domain)
    82  	if err != nil {
    83  		newError("failed to get IP address for domain ", domain).Base(err).WriteToLog(session.ExportIDToError(ctx))
    84  	}
    85  	if len(ips) == 0 {
    86  		return nil
    87  	}
    88  	return net.IPAddress(ips[dice.Roll(len(ips))])
    89  }
    90  
    91  func isValidAddress(addr *net.IPOrDomain) bool {
    92  	if addr == nil {
    93  		return false
    94  	}
    95  
    96  	a := addr.AsAddress()
    97  	return a != net.AnyIP
    98  }
    99  
   100  // Process implements proxy.Outbound.
   101  func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
   102  	outbound := session.OutboundFromContext(ctx)
   103  	if outbound == nil || !outbound.Target.IsValid() {
   104  		return newError("target not specified.")
   105  	}
   106  	destination := outbound.Target
   107  	if h.config.DestinationOverride != nil {
   108  		server := h.config.DestinationOverride.Server
   109  		if isValidAddress(server.Address) {
   110  			destination.Address = server.Address.AsAddress()
   111  		}
   112  		if server.Port != 0 {
   113  			destination.Port = net.Port(server.Port)
   114  		}
   115  	}
   116  	newError("opening connection to ", destination).WriteToLog(session.ExportIDToError(ctx))
   117  
   118  	input := link.Reader
   119  	output := link.Writer
   120  
   121  	var conn internet.Connection
   122  	err := retry.ExponentialBackoff(5, 100).On(func() error {
   123  		dialDest := destination
   124  		if h.config.useIP() && dialDest.Address.Family().IsDomain() {
   125  			ip := h.resolveIP(ctx, dialDest.Address.Domain(), dialer.Address())
   126  			if ip != nil {
   127  				dialDest = net.Destination{
   128  					Network: dialDest.Network,
   129  					Address: ip,
   130  					Port:    dialDest.Port,
   131  				}
   132  				newError("dialing to ", dialDest).WriteToLog(session.ExportIDToError(ctx))
   133  			}
   134  		}
   135  
   136  		rawConn, err := dialer.Dial(ctx, dialDest)
   137  		if err != nil {
   138  			return err
   139  		}
   140  		conn = rawConn
   141  		return nil
   142  	})
   143  	if err != nil {
   144  		return newError("failed to open connection to ", destination).Base(err)
   145  	}
   146  	defer conn.Close()
   147  
   148  	plcy := h.policy()
   149  	ctx, cancel := context.WithCancel(ctx)
   150  	timer := signal.CancelAfterInactivity(ctx, cancel, plcy.Timeouts.ConnectionIdle)
   151  
   152  	requestDone := func() error {
   153  		defer timer.SetTimeout(plcy.Timeouts.DownlinkOnly)
   154  
   155  		var writer buf.Writer
   156  		if destination.Network == net.Network_TCP {
   157  			writer = buf.NewWriter(conn)
   158  		} else {
   159  			writer = &buf.SequentialWriter{Writer: conn}
   160  		}
   161  
   162  		if err := buf.Copy(input, writer, buf.UpdateActivity(timer)); err != nil {
   163  			return newError("failed to process request").Base(err)
   164  		}
   165  
   166  		return nil
   167  	}
   168  
   169  	responseDone := func() error {
   170  		defer timer.SetTimeout(plcy.Timeouts.UplinkOnly)
   171  
   172  		var reader buf.Reader
   173  		if destination.Network == net.Network_TCP {
   174  			reader = buf.NewReader(conn)
   175  		} else {
   176  			reader = buf.NewPacketReader(conn)
   177  		}
   178  		if err := buf.Copy(reader, output, buf.UpdateActivity(timer)); err != nil {
   179  			return newError("failed to process response").Base(err)
   180  		}
   181  
   182  		return nil
   183  	}
   184  
   185  	if err := task.Run(ctx, requestDone, task.OnSuccess(responseDone, task.Close(output))); err != nil {
   186  		return newError("connection ends").Base(err)
   187  	}
   188  
   189  	return nil
   190  }