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 }