github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/proxy/freedom/freedom.go (about)

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