Skip to content

Commit 6d1695a

Browse files
committed
Some refines related to direct/freedom and targetStrategy; More intelligent "useIP"/"ForceIP", enhance "origin" functionality (#5030)
#5009 (comment)
1 parent 3a54924 commit 6d1695a

File tree

11 files changed

+245
-347
lines changed

11 files changed

+245
-347
lines changed

app/proxyman/inbound/worker.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,18 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
322322
outbounds[0].Target = originalDest
323323
}
324324
ctx = session.ContextWithOutbounds(ctx, outbounds)
325+
local := net.DestinationFromAddr(w.hub.Addr())
326+
if local.Address == net.AnyIP || local.Address == net.AnyIPv6 {
327+
if source.Address.Family().IsIPv4() {
328+
local.Address = net.AnyIP
329+
} else if source.Address.Family().IsIPv6() {
330+
local.Address = net.AnyIPv6
331+
}
332+
}
325333

326334
ctx = session.ContextWithInbound(ctx, &session.Inbound{
327335
Source: source,
328-
Local: net.DestinationFromAddr(w.hub.Addr()), // Due to some limitations, in UDP connections, localIP is always equal to listen interface IP
336+
Local: local, // Due to some limitations, in UDP connections, localIP is always equal to listen interface IP
329337
Gateway: net.UDPDestination(w.address, w.port),
330338
Tag: w.tag,
331339
})

app/proxyman/outbound/handler.go

Lines changed: 43 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ import (
44
"context"
55
"crypto/rand"
66
goerrors "errors"
7-
"github.com/xtls/xray-core/common/dice"
87
"io"
98
"math/big"
109
gonet "net"
1110
"os"
1211

12+
"github.com/xtls/xray-core/common/dice"
13+
1314
"github.com/xtls/xray-core/app/proxyman"
1415
"github.com/xtls/xray-core/common"
1516
"github.com/xtls/xray-core/common/buf"
@@ -180,7 +181,11 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
180181
ob := outbounds[len(outbounds)-1]
181182
content := session.ContentFromContext(ctx)
182183
if h.senderSettings != nil && h.senderSettings.TargetStrategy.HasStrategy() && ob.Target.Address.Family().IsDomain() && (content == nil || !content.SkipDNSResolve) {
183-
ips, err := internet.LookupForIP(ob.Target.Address.Domain(), h.senderSettings.TargetStrategy, nil)
184+
strategy := h.senderSettings.TargetStrategy
185+
if ob.Target.Network == net.Network_UDP && ob.OriginalTarget.Address != nil {
186+
strategy = strategy.GetDynamicStrategy(ob.OriginalTarget.Address.Family())
187+
}
188+
ips, err := internet.LookupForIP(ob.Target.Address.Domain(), strategy, nil)
184189
if err != nil {
185190
errors.LogInfoInner(ctx, err, "failed to resolve ip for target ", ob.Target.Address.Domain())
186191
if h.senderSettings.TargetStrategy.ForceIP() {
@@ -251,14 +256,6 @@ out:
251256
common.Interrupt(link.Reader)
252257
}
253258

254-
// Address implements internet.Dialer.
255-
func (h *Handler) Address() net.Address {
256-
if h.senderSettings == nil || h.senderSettings.Via == nil {
257-
return nil
258-
}
259-
return h.senderSettings.Via.AsAddress()
260-
}
261-
262259
func (h *Handler) DestIpAddress() net.IP {
263260
return internet.DestIpAddress()
264261
}
@@ -293,41 +290,16 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
293290
return h.getStatCouterConnection(conn), nil
294291
}
295292

296-
errors.LogWarning(ctx, "failed to get outbound handler with tag: ", tag)
293+
errors.LogError(ctx, "failed to get outbound handler with tag: ", tag)
294+
return nil, errors.New("failed to get outbound handler with tag: " + tag)
297295
}
298296

299297
if h.senderSettings.Via != nil {
300-
301298
outbounds := session.OutboundsFromContext(ctx)
302299
ob := outbounds[len(outbounds)-1]
303-
var domain string
304-
addr := h.senderSettings.Via.AsAddress()
305-
domain = h.senderSettings.Via.GetDomain()
306-
switch {
307-
case h.senderSettings.ViaCidr != "":
308-
ob.Gateway = ParseRandomIP(addr, h.senderSettings.ViaCidr)
309-
310-
case domain == "origin":
311-
if inbound := session.InboundFromContext(ctx); inbound != nil {
312-
if inbound.Local.IsValid() && inbound.Local.Address.Family().IsIP() {
313-
ob.Gateway = inbound.Local.Address
314-
errors.LogDebug(ctx, "use inbound local ip as sendthrough: ", inbound.Local.Address.String())
315-
}
316-
}
317-
case domain == "srcip":
318-
if inbound := session.InboundFromContext(ctx); inbound != nil {
319-
if inbound.Source.IsValid() && inbound.Source.Address.Family().IsIP() {
320-
ob.Gateway = inbound.Source.Address
321-
errors.LogDebug(ctx, "use inbound source ip as sendthrough: ", inbound.Source.Address.String())
322-
}
323-
}
324-
//case addr.Family().IsDomain():
325-
default:
326-
ob.Gateway = addr
327-
328-
}
329-
300+
h.SetOutboundGateway(ctx, ob)
330301
}
302+
331303
}
332304

333305
if conn, err := h.getUoTConnection(ctx, dest); err != os.ErrInvalid {
@@ -342,6 +314,38 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
342314
return conn, err
343315
}
344316

317+
func (h *Handler) SetOutboundGateway(ctx context.Context, ob *session.Outbound) {
318+
if ob.Gateway == nil && h.senderSettings != nil && h.senderSettings.Via != nil && !h.senderSettings.ProxySettings.HasTag() && (h.streamSettings.SocketSettings == nil || len(h.streamSettings.SocketSettings.DialerProxy) == 0) {
319+
var domain string
320+
addr := h.senderSettings.Via.AsAddress()
321+
domain = h.senderSettings.Via.GetDomain()
322+
switch {
323+
case h.senderSettings.ViaCidr != "":
324+
ob.Gateway = ParseRandomIP(addr, h.senderSettings.ViaCidr)
325+
326+
case domain == "origin":
327+
if inbound := session.InboundFromContext(ctx); inbound != nil {
328+
if inbound.Local.IsValid() && inbound.Local.Address.Family().IsIP() {
329+
ob.Gateway = inbound.Local.Address
330+
errors.LogDebug(ctx, "use inbound local ip as sendthrough: ", inbound.Local.Address.String())
331+
}
332+
}
333+
case domain == "srcip":
334+
if inbound := session.InboundFromContext(ctx); inbound != nil {
335+
if inbound.Source.IsValid() && inbound.Source.Address.Family().IsIP() {
336+
ob.Gateway = inbound.Source.Address
337+
errors.LogDebug(ctx, "use inbound source ip as sendthrough: ", inbound.Source.Address.String())
338+
}
339+
}
340+
//case addr.Family().IsDomain():
341+
default:
342+
ob.Gateway = addr
343+
344+
}
345+
346+
}
347+
}
348+
345349
func (h *Handler) getStatCouterConnection(conn stat.Connection) stat.Connection {
346350
if h.uplinkCounter != nil || h.downlinkCounter != nil {
347351
return &stat.CounterConnection{

infra/conf/freedom.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/xtls/xray-core/common/protocol"
1212
"github.com/xtls/xray-core/proxy/freedom"
1313
"google.golang.org/protobuf/proto"
14+
"github.com/xtls/xray-core/transport/internet"
1415
)
1516

1617
type FreedomConfig struct {
@@ -47,27 +48,27 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
4748
}
4849
switch strings.ToLower(targetStrategy) {
4950
case "asis", "":
50-
config.DomainStrategy = freedom.Config_AS_IS
51+
config.DomainStrategy = internet.DomainStrategy_AS_IS
5152
case "useip":
52-
config.DomainStrategy = freedom.Config_USE_IP
53+
config.DomainStrategy = internet.DomainStrategy_USE_IP
5354
case "useipv4":
54-
config.DomainStrategy = freedom.Config_USE_IP4
55+
config.DomainStrategy = internet.DomainStrategy_USE_IP4
5556
case "useipv6":
56-
config.DomainStrategy = freedom.Config_USE_IP6
57+
config.DomainStrategy = internet.DomainStrategy_USE_IP6
5758
case "useipv4v6":
58-
config.DomainStrategy = freedom.Config_USE_IP46
59+
config.DomainStrategy = internet.DomainStrategy_USE_IP46
5960
case "useipv6v4":
60-
config.DomainStrategy = freedom.Config_USE_IP64
61+
config.DomainStrategy = internet.DomainStrategy_USE_IP64
6162
case "forceip":
62-
config.DomainStrategy = freedom.Config_FORCE_IP
63+
config.DomainStrategy = internet.DomainStrategy_FORCE_IP
6364
case "forceipv4":
64-
config.DomainStrategy = freedom.Config_FORCE_IP4
65+
config.DomainStrategy = internet.DomainStrategy_FORCE_IP4
6566
case "forceipv6":
66-
config.DomainStrategy = freedom.Config_FORCE_IP6
67+
config.DomainStrategy = internet.DomainStrategy_FORCE_IP6
6768
case "forceipv4v6":
68-
config.DomainStrategy = freedom.Config_FORCE_IP46
69+
config.DomainStrategy = internet.DomainStrategy_FORCE_IP46
6970
case "forceipv6v4":
70-
config.DomainStrategy = freedom.Config_FORCE_IP64
71+
config.DomainStrategy = internet.DomainStrategy_FORCE_IP64
7172
default:
7273
return nil, errors.New("unsupported domain strategy: ", targetStrategy)
7374
}

infra/conf/freedom_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/xtls/xray-core/common/protocol"
88
. "github.com/xtls/xray-core/infra/conf"
99
"github.com/xtls/xray-core/proxy/freedom"
10+
"github.com/xtls/xray-core/transport/internet"
1011
)
1112

1213
func TestFreedomConfig(t *testing.T) {
@@ -23,7 +24,7 @@ func TestFreedomConfig(t *testing.T) {
2324
}`,
2425
Parser: loadJSON(creator),
2526
Output: &freedom.Config{
26-
DomainStrategy: freedom.Config_AS_IS,
27+
DomainStrategy: internet.DomainStrategy_AS_IS,
2728
DestinationOverride: &freedom.DestinationOverride{
2829
Server: &protocol.ServerEndpoint{
2930
Address: &net.IPOrDomain{

proxy/freedom/config.go

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1 @@
11
package freedom
2-
3-
var strategy = [][]byte{
4-
// name strategy, prefer, fallback
5-
{0, 0, 0}, // AsIs none, /, /
6-
{1, 0, 0}, // UseIP use, both, none
7-
{1, 4, 0}, // UseIPv4 use, 4, none
8-
{1, 6, 0}, // UseIPv6 use, 6, none
9-
{1, 4, 6}, // UseIPv4v6 use, 4, 6
10-
{1, 6, 4}, // UseIPv6v4 use, 6, 4
11-
{2, 0, 0}, // ForceIP force, both, none
12-
{2, 4, 0}, // ForceIPv4 force, 4, none
13-
{2, 6, 0}, // ForceIPv6 force, 6, none
14-
{2, 4, 6}, // ForceIPv4v6 force, 4, 6
15-
{2, 6, 4}, // ForceIPv6v4 force, 6, 4
16-
}
17-
18-
func (c *Config) hasStrategy() bool {
19-
return strategy[c.DomainStrategy][0] != 0
20-
}
21-
22-
func (c *Config) forceIP() bool {
23-
return strategy[c.DomainStrategy][0] == 2
24-
}
25-
26-
func (c *Config) preferIP4() bool {
27-
return strategy[c.DomainStrategy][1] == 4 || strategy[c.DomainStrategy][1] == 0
28-
}
29-
30-
func (c *Config) preferIP6() bool {
31-
return strategy[c.DomainStrategy][1] == 6 || strategy[c.DomainStrategy][1] == 0
32-
}
33-
34-
func (c *Config) hasFallback() bool {
35-
return strategy[c.DomainStrategy][2] != 0
36-
}
37-
38-
func (c *Config) fallbackIP4() bool {
39-
return strategy[c.DomainStrategy][2] == 4
40-
}
41-
42-
func (c *Config) fallbackIP6() bool {
43-
return strategy[c.DomainStrategy][2] == 6
44-
}

0 commit comments

Comments
 (0)