mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-11-27 01:13:01 +00:00
Add DestIpAddress() in Dialer interface
Android client prepares an IP before proxy connection is established. It is useful when connecting to wireguard (or quic) outbound with domain address. E.g. engage.cloudflareclient.com:2408
This commit is contained in:
parent
5a5e615b46
commit
d60281d0a5
@ -229,6 +229,10 @@ func (h *Handler) Address() net.Address {
|
|||||||
return h.senderSettings.Via.AsAddress()
|
return h.senderSettings.Via.AsAddress()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handler) DestIpAddress() net.IP {
|
||||||
|
return internet.DestIpAddress()
|
||||||
|
}
|
||||||
|
|
||||||
// Dial implements internet.Dialer.
|
// Dial implements internet.Dialer.
|
||||||
func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connection, error) {
|
func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connection, error) {
|
||||||
if h.senderSettings != nil {
|
if h.senderSettings != nil {
|
||||||
|
@ -22,7 +22,9 @@ package wireguard
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
@ -49,7 +51,6 @@ type Handler struct {
|
|||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
dns dns.Client
|
dns dns.Client
|
||||||
// cached configuration
|
// cached configuration
|
||||||
ipc string
|
|
||||||
endpoints []netip.Addr
|
endpoints []netip.Addr
|
||||||
hasIPv4, hasIPv6 bool
|
hasIPv4, hasIPv6 bool
|
||||||
wgLock sync.Mutex
|
wgLock sync.Mutex
|
||||||
@ -69,7 +70,6 @@ func New(ctx context.Context, conf *DeviceConfig) (*Handler, error) {
|
|||||||
conf: conf,
|
conf: conf,
|
||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
dns: d,
|
dns: d,
|
||||||
ipc: createIPCRequest(conf),
|
|
||||||
endpoints: endpoints,
|
endpoints: endpoints,
|
||||||
hasIPv4: hasIPv4,
|
hasIPv4: hasIPv4,
|
||||||
hasIPv6: hasIPv6,
|
hasIPv6: hasIPv6,
|
||||||
@ -247,9 +247,76 @@ func (h *Handler) makeVirtualTun(bind *netBindClient) (Tunnel, error) {
|
|||||||
bind.dnsOption.IPv4Enable = h.hasIPv4
|
bind.dnsOption.IPv4Enable = h.hasIPv4
|
||||||
bind.dnsOption.IPv6Enable = h.hasIPv6
|
bind.dnsOption.IPv6Enable = h.hasIPv6
|
||||||
|
|
||||||
if err = t.BuildDevice(h.ipc, bind); err != nil {
|
if err = t.BuildDevice(h.createIPCRequest(bind, h.conf), bind); err != nil {
|
||||||
_ = t.Close()
|
_ = t.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// serialize the config into an IPC request
|
||||||
|
func (h *Handler) createIPCRequest(bind *netBindClient, conf *DeviceConfig) string {
|
||||||
|
var request strings.Builder
|
||||||
|
|
||||||
|
request.WriteString(fmt.Sprintf("private_key=%s\n", conf.SecretKey))
|
||||||
|
|
||||||
|
if !conf.IsClient {
|
||||||
|
// placeholder, we'll handle actual port listening on Xray
|
||||||
|
request.WriteString("listen_port=1337\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, peer := range conf.Peers {
|
||||||
|
if peer.PublicKey != "" {
|
||||||
|
request.WriteString(fmt.Sprintf("public_key=%s\n", peer.PublicKey))
|
||||||
|
}
|
||||||
|
|
||||||
|
if peer.PreSharedKey != "" {
|
||||||
|
request.WriteString(fmt.Sprintf("preshared_key=%s\n", peer.PreSharedKey))
|
||||||
|
}
|
||||||
|
|
||||||
|
split := strings.Split(peer.Endpoint, ":")
|
||||||
|
addr := net.ParseAddress(split[0])
|
||||||
|
if addr.Family().IsDomain() {
|
||||||
|
dialerIp := bind.dialer.DestIpAddress()
|
||||||
|
if dialerIp != nil {
|
||||||
|
addr = net.ParseAddress(dialerIp.String())
|
||||||
|
newError("createIPCRequest use dialer dest ip: ", addr).WriteToLog()
|
||||||
|
} else {
|
||||||
|
ips, err := h.dns.LookupIP(addr.Domain(), dns.IPOption{
|
||||||
|
IPv4Enable: h.hasIPv4 && h.conf.preferIP4(),
|
||||||
|
IPv6Enable: h.hasIPv6 && h.conf.preferIP6(),
|
||||||
|
})
|
||||||
|
{ // Resolve fallback
|
||||||
|
if (len(ips) == 0 || err != nil) && h.conf.hasFallback() {
|
||||||
|
ips, err = h.dns.LookupIP(addr.Domain(), dns.IPOption{
|
||||||
|
IPv4Enable: h.hasIPv4 && h.conf.fallbackIP4(),
|
||||||
|
IPv6Enable: h.hasIPv6 && h.conf.fallbackIP6(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
newError("createIPCRequest failed to lookup DNS").Base(err).WriteToLog()
|
||||||
|
} else if len(ips) == 0 {
|
||||||
|
newError("createIPCRequest empty lookup DNS").WriteToLog()
|
||||||
|
} else {
|
||||||
|
addr = net.IPAddress(ips[dice.Roll(len(ips))])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if peer.Endpoint != "" {
|
||||||
|
request.WriteString(fmt.Sprintf("endpoint=%s:%s\n", addr, split[1]))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ip := range peer.AllowedIps {
|
||||||
|
request.WriteString(fmt.Sprintf("allowed_ip=%s\n", ip))
|
||||||
|
}
|
||||||
|
|
||||||
|
if peer.KeepAlive != 0 {
|
||||||
|
request.WriteString(fmt.Sprintf("persistent_keepalive_interval=%d\n", peer.KeepAlive))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return request.String()[:request.Len()]
|
||||||
|
}
|
||||||
|
@ -22,6 +22,9 @@ type Dialer interface {
|
|||||||
|
|
||||||
// Address returns the address used by this Dialer. Maybe nil if not known.
|
// Address returns the address used by this Dialer. Maybe nil if not known.
|
||||||
Address() net.Address
|
Address() net.Address
|
||||||
|
|
||||||
|
// DestIpAddress returns the ip of proxy server. It is useful in case of Android client, which prepare an IP before proxy connection is established
|
||||||
|
DestIpAddress() net.IP
|
||||||
}
|
}
|
||||||
|
|
||||||
// dialFunc is an interface to dial network connection to a specific destination.
|
// dialFunc is an interface to dial network connection to a specific destination.
|
||||||
@ -68,6 +71,11 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *MemoryStrea
|
|||||||
return nil, newError("unknown network ", dest.Network)
|
return nil, newError("unknown network ", dest.Network)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DestIpAddress returns the ip of proxy server. It is useful in case of Android client, which prepare an IP before proxy connection is established
|
||||||
|
func DestIpAddress() net.IP {
|
||||||
|
return effectiveSystemDialer.DestIpAddress()
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
dnsClient dns.Client
|
dnsClient dns.Client
|
||||||
obm outbound.Manager
|
obm outbound.Manager
|
||||||
|
@ -16,6 +16,7 @@ var effectiveSystemDialer SystemDialer = &DefaultSystemDialer{}
|
|||||||
|
|
||||||
type SystemDialer interface {
|
type SystemDialer interface {
|
||||||
Dial(ctx context.Context, source net.Address, destination net.Destination, sockopt *SocketConfig) (net.Conn, error)
|
Dial(ctx context.Context, source net.Address, destination net.Destination, sockopt *SocketConfig) (net.Conn, error)
|
||||||
|
DestIpAddress() net.IP
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefaultSystemDialer struct {
|
type DefaultSystemDialer struct {
|
||||||
@ -108,6 +109,10 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne
|
|||||||
return dialer.DialContext(ctx, dest.Network.SystemString(), dest.NetAddr())
|
return dialer.DialContext(ctx, dest.Network.SystemString(), dest.NetAddr())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *DefaultSystemDialer) DestIpAddress() net.IP {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type PacketConnWrapper struct {
|
type PacketConnWrapper struct {
|
||||||
Conn net.PacketConn
|
Conn net.PacketConn
|
||||||
Dest net.Addr
|
Dest net.Addr
|
||||||
@ -172,6 +177,10 @@ func (v *SimpleSystemDialer) Dial(ctx context.Context, src net.Address, dest net
|
|||||||
return v.adapter.Dial(dest.Network.SystemString(), dest.NetAddr())
|
return v.adapter.Dial(dest.Network.SystemString(), dest.NetAddr())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *SimpleSystemDialer) DestIpAddress() net.IP {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// UseAlternativeSystemDialer replaces the current system dialer with a given one.
|
// UseAlternativeSystemDialer replaces the current system dialer with a given one.
|
||||||
// Caller must ensure there is no race condition.
|
// Caller must ensure there is no race condition.
|
||||||
//
|
//
|
||||||
|
Loading…
Reference in New Issue
Block a user