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