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 }