Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion app/proxyman/inbound/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,18 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
outbounds[0].Target = originalDest
}
ctx = session.ContextWithOutbounds(ctx, outbounds)
local := net.DestinationFromAddr(w.hub.Addr())
if local.Address == net.AnyIP || local.Address == net.AnyIPv6 {
if source.Address.Family().IsIPv4() {
local.Address = net.AnyIP
} else if source.Address.Family().IsIPv6() {
local.Address = net.AnyIPv6
}
}

ctx = session.ContextWithInbound(ctx, &session.Inbound{
Source: source,
Local: net.DestinationFromAddr(w.hub.Addr()), // Due to some limitations, in UDP connections, localIP is always equal to listen interface IP
Local: local, // Due to some limitations, in UDP connections, localIP is always equal to listen interface IP
Gateway: net.UDPDestination(w.address, w.port),
Tag: w.tag,
})
Expand Down
82 changes: 43 additions & 39 deletions app/proxyman/outbound/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import (
"context"
"crypto/rand"
goerrors "errors"
"github.com/xtls/xray-core/common/dice"
"io"
"math/big"
gonet "net"
"os"

"github.com/xtls/xray-core/common/dice"

"github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
Expand Down Expand Up @@ -180,7 +181,11 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
ob := outbounds[len(outbounds)-1]
content := session.ContentFromContext(ctx)
if h.senderSettings != nil && h.senderSettings.TargetStrategy.HasStrategy() && ob.Target.Address.Family().IsDomain() && (content == nil || !content.SkipDNSResolve) {
ips, err := internet.LookupForIP(ob.Target.Address.Domain(), h.senderSettings.TargetStrategy, nil)
strategy := h.senderSettings.TargetStrategy
if ob.Target.Network == net.Network_UDP && ob.OriginalTarget.Address != nil {
strategy = strategy.GetDynamicStrategy(ob.OriginalTarget.Address.Family())
}
ips, err := internet.LookupForIP(ob.Target.Address.Domain(), strategy, nil)
if err != nil {
errors.LogInfoInner(ctx, err, "failed to resolve ip for target ", ob.Target.Address.Domain())
if h.senderSettings.TargetStrategy.ForceIP() {
Expand Down Expand Up @@ -251,14 +256,6 @@ out:
common.Interrupt(link.Reader)
}

// Address implements internet.Dialer.
func (h *Handler) Address() net.Address {
if h.senderSettings == nil || h.senderSettings.Via == nil {
return nil
}
return h.senderSettings.Via.AsAddress()
}

func (h *Handler) DestIpAddress() net.IP {
return internet.DestIpAddress()
}
Expand Down Expand Up @@ -293,41 +290,16 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
return h.getStatCouterConnection(conn), nil
}

errors.LogWarning(ctx, "failed to get outbound handler with tag: ", tag)
errors.LogError(ctx, "failed to get outbound handler with tag: ", tag)
return nil, errors.New("failed to get outbound handler with tag: " + tag)
}

if h.senderSettings.Via != nil {

outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1]
var domain string
addr := h.senderSettings.Via.AsAddress()
domain = h.senderSettings.Via.GetDomain()
switch {
case h.senderSettings.ViaCidr != "":
ob.Gateway = ParseRandomIP(addr, h.senderSettings.ViaCidr)

case domain == "origin":
if inbound := session.InboundFromContext(ctx); inbound != nil {
if inbound.Local.IsValid() && inbound.Local.Address.Family().IsIP() {
ob.Gateway = inbound.Local.Address
errors.LogDebug(ctx, "use inbound local ip as sendthrough: ", inbound.Local.Address.String())
}
}
case domain == "srcip":
if inbound := session.InboundFromContext(ctx); inbound != nil {
if inbound.Source.IsValid() && inbound.Source.Address.Family().IsIP() {
ob.Gateway = inbound.Source.Address
errors.LogDebug(ctx, "use inbound source ip as sendthrough: ", inbound.Source.Address.String())
}
}
//case addr.Family().IsDomain():
default:
ob.Gateway = addr

}

h.SetOutboundGateway(ctx, ob)
}

}

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

func (h *Handler) SetOutboundGateway(ctx context.Context, ob *session.Outbound) {
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) {
var domain string
addr := h.senderSettings.Via.AsAddress()
domain = h.senderSettings.Via.GetDomain()
switch {
case h.senderSettings.ViaCidr != "":
ob.Gateway = ParseRandomIP(addr, h.senderSettings.ViaCidr)

case domain == "origin":
if inbound := session.InboundFromContext(ctx); inbound != nil {
if inbound.Local.IsValid() && inbound.Local.Address.Family().IsIP() {
ob.Gateway = inbound.Local.Address
errors.LogDebug(ctx, "use inbound local ip as sendthrough: ", inbound.Local.Address.String())
}
}
case domain == "srcip":
if inbound := session.InboundFromContext(ctx); inbound != nil {
if inbound.Source.IsValid() && inbound.Source.Address.Family().IsIP() {
ob.Gateway = inbound.Source.Address
errors.LogDebug(ctx, "use inbound source ip as sendthrough: ", inbound.Source.Address.String())
}
}
//case addr.Family().IsDomain():
default:
ob.Gateway = addr

}

}
}

func (h *Handler) getStatCouterConnection(conn stat.Connection) stat.Connection {
if h.uplinkCounter != nil || h.downlinkCounter != nil {
return &stat.CounterConnection{
Expand Down
23 changes: 12 additions & 11 deletions infra/conf/freedom.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/proxy/freedom"
"google.golang.org/protobuf/proto"
"github.com/xtls/xray-core/transport/internet"
)

type FreedomConfig struct {
Expand Down Expand Up @@ -47,27 +48,27 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
}
switch strings.ToLower(targetStrategy) {
case "asis", "":
config.DomainStrategy = freedom.Config_AS_IS
config.DomainStrategy = internet.DomainStrategy_AS_IS
case "useip":
config.DomainStrategy = freedom.Config_USE_IP
config.DomainStrategy = internet.DomainStrategy_USE_IP
case "useipv4":
config.DomainStrategy = freedom.Config_USE_IP4
config.DomainStrategy = internet.DomainStrategy_USE_IP4
case "useipv6":
config.DomainStrategy = freedom.Config_USE_IP6
config.DomainStrategy = internet.DomainStrategy_USE_IP6
case "useipv4v6":
config.DomainStrategy = freedom.Config_USE_IP46
config.DomainStrategy = internet.DomainStrategy_USE_IP46
case "useipv6v4":
config.DomainStrategy = freedom.Config_USE_IP64
config.DomainStrategy = internet.DomainStrategy_USE_IP64
case "forceip":
config.DomainStrategy = freedom.Config_FORCE_IP
config.DomainStrategy = internet.DomainStrategy_FORCE_IP
case "forceipv4":
config.DomainStrategy = freedom.Config_FORCE_IP4
config.DomainStrategy = internet.DomainStrategy_FORCE_IP4
case "forceipv6":
config.DomainStrategy = freedom.Config_FORCE_IP6
config.DomainStrategy = internet.DomainStrategy_FORCE_IP6
case "forceipv4v6":
config.DomainStrategy = freedom.Config_FORCE_IP46
config.DomainStrategy = internet.DomainStrategy_FORCE_IP46
case "forceipv6v4":
config.DomainStrategy = freedom.Config_FORCE_IP64
config.DomainStrategy = internet.DomainStrategy_FORCE_IP64
default:
return nil, errors.New("unsupported domain strategy: ", targetStrategy)
}
Expand Down
3 changes: 2 additions & 1 deletion infra/conf/freedom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/xtls/xray-core/common/protocol"
. "github.com/xtls/xray-core/infra/conf"
"github.com/xtls/xray-core/proxy/freedom"
"github.com/xtls/xray-core/transport/internet"
)

func TestFreedomConfig(t *testing.T) {
Expand All @@ -23,7 +24,7 @@ func TestFreedomConfig(t *testing.T) {
}`,
Parser: loadJSON(creator),
Output: &freedom.Config{
DomainStrategy: freedom.Config_AS_IS,
DomainStrategy: internet.DomainStrategy_AS_IS,
DestinationOverride: &freedom.DestinationOverride{
Server: &protocol.ServerEndpoint{
Address: &net.IPOrDomain{
Expand Down
43 changes: 0 additions & 43 deletions proxy/freedom/config.go
Original file line number Diff line number Diff line change
@@ -1,44 +1 @@
package freedom

var strategy = [][]byte{
// name strategy, prefer, fallback
{0, 0, 0}, // AsIs none, /, /
{1, 0, 0}, // UseIP use, both, none
{1, 4, 0}, // UseIPv4 use, 4, none
{1, 6, 0}, // UseIPv6 use, 6, none
{1, 4, 6}, // UseIPv4v6 use, 4, 6
{1, 6, 4}, // UseIPv6v4 use, 6, 4
{2, 0, 0}, // ForceIP force, both, none
{2, 4, 0}, // ForceIPv4 force, 4, none
{2, 6, 0}, // ForceIPv6 force, 6, none
{2, 4, 6}, // ForceIPv4v6 force, 4, 6
{2, 6, 4}, // ForceIPv6v4 force, 6, 4
}

func (c *Config) hasStrategy() bool {
return strategy[c.DomainStrategy][0] != 0
}

func (c *Config) forceIP() bool {
return strategy[c.DomainStrategy][0] == 2
}

func (c *Config) preferIP4() bool {
return strategy[c.DomainStrategy][1] == 4 || strategy[c.DomainStrategy][1] == 0
}

func (c *Config) preferIP6() bool {
return strategy[c.DomainStrategy][1] == 6 || strategy[c.DomainStrategy][1] == 0
}

func (c *Config) hasFallback() bool {
return strategy[c.DomainStrategy][2] != 0
}

func (c *Config) fallbackIP4() bool {
return strategy[c.DomainStrategy][2] == 4
}

func (c *Config) fallbackIP6() bool {
return strategy[c.DomainStrategy][2] == 6
}
Loading
Loading