mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-09-23 01:27:04 +00:00
WireGuard outbound: Remove remoteDNS' "local" mode and domainStrategy (#6771)
https://github.com/XTLS/Xray-core/issues/6567#issuecomment-5660953757 https://github.com/XTLS/Xray-core/pull/6771#issuecomment-5751826982 https://github.com/XTLS/Xray-core/pull/6771#issuecomment-5751831637
This commit is contained in:
+7
-23
@@ -59,14 +59,13 @@ func (c *WireGuardPeerConfig) Build() (*wireguard.PeerConfig, error) {
|
|||||||
type WireGuardConfig struct {
|
type WireGuardConfig struct {
|
||||||
IsClient bool `json:""`
|
IsClient bool `json:""`
|
||||||
|
|
||||||
NoKernelTun bool `json:"noKernelTun"`
|
NoKernelTun bool `json:"noKernelTun"`
|
||||||
SecretKey string `json:"secretKey"`
|
SecretKey string `json:"secretKey"`
|
||||||
Address []string `json:"address"`
|
Address []string `json:"address"`
|
||||||
Peers []*WireGuardPeerConfig `json:"peers"`
|
Peers []*WireGuardPeerConfig `json:"peers"`
|
||||||
MTU int32 `json:"mtu"`
|
MTU int32 `json:"mtu"`
|
||||||
Reserved []byte `json:"reserved"`
|
Reserved []byte `json:"reserved"`
|
||||||
DomainStrategy string `json:"domainStrategy"`
|
DNS []string `json:"remoteDNS"`
|
||||||
DNS []string `json:"remoteDNS"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *WireGuardConfig) Build() (proto.Message, error) {
|
func (c *WireGuardConfig) Build() (proto.Message, error) {
|
||||||
@@ -125,21 +124,6 @@ func (c *WireGuardConfig) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
config.Reserved = c.Reserved
|
config.Reserved = c.Reserved
|
||||||
|
|
||||||
switch strings.ToLower(c.DomainStrategy) {
|
|
||||||
case "forceip", "":
|
|
||||||
config.DomainStrategy = wireguard.DeviceConfig_FORCE_IP
|
|
||||||
case "forceipv4":
|
|
||||||
config.DomainStrategy = wireguard.DeviceConfig_FORCE_IP4
|
|
||||||
case "forceipv6":
|
|
||||||
config.DomainStrategy = wireguard.DeviceConfig_FORCE_IP6
|
|
||||||
case "forceipv4v6":
|
|
||||||
config.DomainStrategy = wireguard.DeviceConfig_FORCE_IP46
|
|
||||||
case "forceipv6v4":
|
|
||||||
config.DomainStrategy = wireguard.DeviceConfig_FORCE_IP64
|
|
||||||
default:
|
|
||||||
return nil, errors.New("unsupported domain strategy: ", c.DomainStrategy)
|
|
||||||
}
|
|
||||||
|
|
||||||
config.IsClient = c.IsClient
|
config.IsClient = c.IsClient
|
||||||
config.NoKernelTun = c.NoKernelTun
|
config.NoKernelTun = c.NoKernelTun
|
||||||
config.DNS = c.DNS
|
config.DNS = c.DNS
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ func (t *Handler) Start() error {
|
|||||||
iface := updater.Get()
|
iface := updater.Get()
|
||||||
if iface == nil {
|
if iface == nil {
|
||||||
errors.LogInfo(context.Background(), "[tun] falied to set interface > iface == nil")
|
errors.LogInfo(context.Background(), "[tun] falied to set interface > iface == nil")
|
||||||
return nil
|
return errors.New("iface not found")
|
||||||
}
|
}
|
||||||
return c.Control(func(fd uintptr) {
|
return c.Control(func(fd uintptr) {
|
||||||
addrPort, _ := netip.ParseAddrPort(address)
|
addrPort, _ := netip.ParseAddrPort(address)
|
||||||
|
|||||||
+93
-119
@@ -3,7 +3,6 @@ package wireguard
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
gonet "net"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -32,11 +31,6 @@ import (
|
|||||||
"golang.zx2c4.com/wireguard/device"
|
"golang.zx2c4.com/wireguard/device"
|
||||||
)
|
)
|
||||||
|
|
||||||
type entry struct {
|
|
||||||
got []net.IP
|
|
||||||
time time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
conf *DeviceConfig
|
conf *DeviceConfig
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
@@ -50,11 +44,6 @@ type Handler struct {
|
|||||||
tnet *Net
|
tnet *Net
|
||||||
dev *device.Device
|
dev *device.Device
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
|
||||||
// TODO: cache cleanup loop
|
|
||||||
local bool
|
|
||||||
cache map[string]entry
|
|
||||||
cacheMu sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(ctx context.Context, conf *DeviceConfig) (*Handler, error) {
|
func NewClient(ctx context.Context, conf *DeviceConfig) (*Handler, error) {
|
||||||
@@ -110,15 +99,10 @@ func NewClient(ctx context.Context, conf *DeviceConfig) (*Handler, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
local := false
|
|
||||||
dns := conf.DNS
|
dns := conf.DNS
|
||||||
if len(dns) == 0 {
|
if len(dns) == 0 {
|
||||||
dns = []string{"1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001"}
|
dns = []string{"1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001"}
|
||||||
}
|
}
|
||||||
if len(dns) == 1 && dns[0] == "local" {
|
|
||||||
local = true
|
|
||||||
dns = nil
|
|
||||||
}
|
|
||||||
dnses := make([]netip.Addr, 0, len(dns))
|
dnses := make([]netip.Addr, 0, len(dns))
|
||||||
for _, dns := range dns {
|
for _, dns := range dns {
|
||||||
dnses = append(dnses, netip.MustParseAddr(dns))
|
dnses = append(dnses, netip.MustParseAddr(dns))
|
||||||
@@ -152,9 +136,6 @@ func NewClient(ctx context.Context, conf *DeviceConfig) (*Handler, error) {
|
|||||||
|
|
||||||
tun: tun,
|
tun: tun,
|
||||||
tnet: tnet,
|
tnet: tnet,
|
||||||
|
|
||||||
local: local,
|
|
||||||
cache: make(map[string]entry),
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,22 +154,6 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var addr netip.Addr
|
|
||||||
if ob.Target.Address.Family().IsDomain() {
|
|
||||||
ip, err := h.resolveRemote(ob.Target.Address.String())
|
|
||||||
if err != nil {
|
|
||||||
return errors.New("failed to resolve domain").Base(err)
|
|
||||||
}
|
|
||||||
addr, _ = netip.AddrFromSlice(ip)
|
|
||||||
} else {
|
|
||||||
addr, _ = netip.AddrFromSlice(ob.Target.Address.IP())
|
|
||||||
}
|
|
||||||
|
|
||||||
addrPort := netip.AddrPortFrom(addr, ob.Target.Port.Value())
|
|
||||||
if !addrPort.IsValid() {
|
|
||||||
return errors.New("invalid target ", ob.Target)
|
|
||||||
}
|
|
||||||
|
|
||||||
var newCtx context.Context
|
var newCtx context.Context
|
||||||
var newCancel context.CancelFunc
|
var newCancel context.CancelFunc
|
||||||
if session.TimeoutOnlyFromContext(ctx) {
|
if session.TimeoutOnlyFromContext(ctx) {
|
||||||
@@ -217,10 +182,10 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
var err error
|
var err error
|
||||||
if sessionPolicy.Timeouts.Handshake != 0 {
|
if sessionPolicy.Timeouts.Handshake != 0 {
|
||||||
timeoutCtx, timeoutCancel := context.WithTimeout(ctx, sessionPolicy.Timeouts.Handshake)
|
timeoutCtx, timeoutCancel := context.WithTimeout(ctx, sessionPolicy.Timeouts.Handshake)
|
||||||
conn, err = h.tnet.DialContextTCPAddrPort(timeoutCtx, addrPort)
|
conn, err = h.tnet.DialContext(timeoutCtx, "tcp", ob.Target.NetAddr())
|
||||||
timeoutCancel()
|
timeoutCancel()
|
||||||
} else {
|
} else {
|
||||||
conn, err = h.tnet.DialContextTCPAddrPort(ctx, addrPort)
|
conn, err = h.tnet.Dial("tcp", ob.Target.NetAddr())
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to create TCP connection").Base(err)
|
return errors.New("failed to create TCP connection").Base(err)
|
||||||
@@ -229,15 +194,14 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
reader = buf.NewReader(conn)
|
reader = buf.NewReader(conn)
|
||||||
writer = buf.NewWriter(conn)
|
writer = buf.NewWriter(conn)
|
||||||
case net.Network_UDP:
|
case net.Network_UDP:
|
||||||
conn, err := h.tnet.DialUDPAddrPort(netip.AddrPort{}, addrPort)
|
conn, err := h.tnet.Dial("udp", ob.Target.NetAddr())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to create UDP connection").Base(err)
|
return errors.New("failed to create UDP connection").Base(err)
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
c := &udpConnClient{
|
c := &udpConnClient{
|
||||||
PacketConn: conn.(*internet.PacketConnWrapper).PacketConn,
|
PacketConn: conn.(*internet.PacketConnWrapper).PacketConn,
|
||||||
resolveFunc: h.resolveRemote,
|
dest: conn.RemoteAddr().(*net.UDPAddr),
|
||||||
dest: gonet.UDPAddrFromAddrPort(addrPort),
|
|
||||||
}
|
}
|
||||||
reader = c
|
reader = c
|
||||||
writer = c
|
writer = c
|
||||||
@@ -372,87 +336,48 @@ func (h *Handler) init(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) resolveLocal(host string) (net.IP, error) {
|
func (h *Handler) resolveLocal(host string) (net.IP, error) {
|
||||||
return h.resolveDomain(host, h.conf.DomainStrategy, func(host string) ([]net.IP, uint32, error) {
|
ips, _, err := h.dns.LookupIP(host, dns.IPOption{IPv4Enable: true, IPv6Enable: true})
|
||||||
return h.dns.LookupIP(host, dns.IPOption{IPv4Enable: true, IPv6Enable: true})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handler) resolveRemote(host string) (net.IP, error) {
|
|
||||||
return h.resolveDomain(host, h.conf.DomainStrategy, func(host string) ([]net.IP, uint32, error) {
|
|
||||||
if h.local {
|
|
||||||
return h.dns.LookupIP(host, dns.IPOption{IPv4Enable: true, IPv6Enable: true})
|
|
||||||
}
|
|
||||||
return h.tnet.LookupHost(host)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handler) resolveDomain(host string, strategy DeviceConfig_DomainStrategy, lookupIP func(host string) ([]net.IP, uint32, error)) (net.IP, error) {
|
|
||||||
if ip := net.ParseIP(host); ip != nil {
|
|
||||||
return ip, nil
|
|
||||||
}
|
|
||||||
h.cacheMu.Lock()
|
|
||||||
if entry, ok := h.cache[host]; ok {
|
|
||||||
if time.Now().Before(entry.time) {
|
|
||||||
h.cacheMu.Unlock()
|
|
||||||
return entry.got[dice.Roll(len(entry.got))], nil
|
|
||||||
}
|
|
||||||
delete(h.cache, host)
|
|
||||||
}
|
|
||||||
h.cacheMu.Unlock()
|
|
||||||
ips, ttl, err := lookupIP(host)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(ips) == 0 {
|
got := ips
|
||||||
return nil, dns.ErrEmptyResponse
|
if h.streamSettings.SocketSettings != nil {
|
||||||
}
|
var got4, got6 []net.IP
|
||||||
var got4, got6 []net.IP
|
for _, ip := range ips {
|
||||||
for _, ip := range ips {
|
if ip.To4() != nil {
|
||||||
if ip.To4() != nil {
|
got4 = append(got4, ip)
|
||||||
got4 = append(got4, ip)
|
} else {
|
||||||
} else {
|
got6 = append(got6, ip)
|
||||||
got6 = append(got6, ip)
|
}
|
||||||
}
|
}
|
||||||
}
|
switch h.streamSettings.SocketSettings.DomainStrategy {
|
||||||
var got []net.IP
|
case internet.DomainStrategy_AS_IS, internet.DomainStrategy_USE_IP, internet.DomainStrategy_FORCE_IP:
|
||||||
switch strategy {
|
got = ips
|
||||||
case DeviceConfig_FORCE_IP:
|
case internet.DomainStrategy_USE_IP4, internet.DomainStrategy_FORCE_IP4:
|
||||||
got = ips
|
|
||||||
return ips[dice.Roll(len(ips))], nil
|
|
||||||
case DeviceConfig_FORCE_IP4:
|
|
||||||
got = got4
|
|
||||||
case DeviceConfig_FORCE_IP6:
|
|
||||||
got = got6
|
|
||||||
case DeviceConfig_FORCE_IP46:
|
|
||||||
got = got4
|
|
||||||
if len(got) == 0 {
|
|
||||||
got = got6
|
|
||||||
}
|
|
||||||
case DeviceConfig_FORCE_IP64:
|
|
||||||
got = got6
|
|
||||||
if len(got) == 0 {
|
|
||||||
got = got4
|
got = got4
|
||||||
|
case internet.DomainStrategy_USE_IP6, internet.DomainStrategy_FORCE_IP6:
|
||||||
|
got = got6
|
||||||
|
case internet.DomainStrategy_USE_IP46, internet.DomainStrategy_FORCE_IP46:
|
||||||
|
got = got4
|
||||||
|
if len(got) == 0 {
|
||||||
|
got = got6
|
||||||
|
}
|
||||||
|
case internet.DomainStrategy_USE_IP64, internet.DomainStrategy_FORCE_IP64:
|
||||||
|
got = got6
|
||||||
|
if len(got) == 0 {
|
||||||
|
got = got4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(got) == 0 {
|
||||||
|
return nil, dns.ErrEmptyResponse
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
panic(strategy)
|
|
||||||
}
|
}
|
||||||
if len(got) == 0 {
|
|
||||||
return nil, dns.ErrEmptyResponse
|
|
||||||
}
|
|
||||||
entry := entry{
|
|
||||||
got: got,
|
|
||||||
time: time.Now().Add(time.Duration(ttl) * time.Second),
|
|
||||||
}
|
|
||||||
h.cacheMu.Lock()
|
|
||||||
h.cache[host] = entry
|
|
||||||
h.cacheMu.Unlock()
|
|
||||||
return got[dice.Roll(len(got))], nil
|
return got[dice.Roll(len(got))], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type udpConnClient struct {
|
type udpConnClient struct {
|
||||||
net.PacketConn
|
net.PacketConn
|
||||||
resolveFunc func(host string) (net.IP, error)
|
dest *net.UDPAddr
|
||||||
dest *net.UDPAddr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpConnClient) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
func (c *udpConnClient) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||||
@@ -479,15 +404,8 @@ func (c *udpConnClient) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|||||||
dst := c.dest
|
dst := c.dest
|
||||||
if b.UDP != nil {
|
if b.UDP != nil {
|
||||||
if b.UDP.Address.Family().IsDomain() {
|
if b.UDP.Address.Family().IsDomain() {
|
||||||
ip, err := c.resolveFunc(b.UDP.Address.String())
|
if b.UDP.Port != net.Port(dst.Port) {
|
||||||
if err != nil {
|
dst = &net.UDPAddr{IP: dst.IP, Port: int(b.UDP.Port)}
|
||||||
errors.LogErrorInner(context.Background(), err, "drop packet to ", b.UDP, " with size ", len(b.Bytes()))
|
|
||||||
b.Release()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dst = &net.UDPAddr{
|
|
||||||
IP: ip,
|
|
||||||
Port: int(b.UDP.Port),
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dst = b.UDP.RawNetAddr().(*net.UDPAddr)
|
dst = b.UDP.RawNetAddr().(*net.UDPAddr)
|
||||||
@@ -524,3 +442,59 @@ func (c *PacketCounterConnection) WriteTo(p []byte, addr net.Addr) (n int, err e
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type entry struct {
|
||||||
|
saddr []string
|
||||||
|
deadline time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type cache struct {
|
||||||
|
running bool
|
||||||
|
m map[string]entry
|
||||||
|
mu sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cache) run() {
|
||||||
|
if c.running {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.running = true
|
||||||
|
c.m = make(map[string]entry)
|
||||||
|
go c.gc()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cache) gc() {
|
||||||
|
ticker := time.NewTicker(time.Minute)
|
||||||
|
for {
|
||||||
|
now := <-ticker.C
|
||||||
|
c.mu.Lock()
|
||||||
|
for key, entry := range c.m {
|
||||||
|
if now.After(entry.deadline) {
|
||||||
|
delete(c.m, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.mu.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cache) LookupHost(host string) []string {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
c.run()
|
||||||
|
if entry, ok := c.m[host]; ok {
|
||||||
|
if time.Now().Before(entry.deadline) {
|
||||||
|
return entry.saddr
|
||||||
|
}
|
||||||
|
delete(c.m, host)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cache) Cache(host string, saddr []string, ttl uint32) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
c.m[host] = entry{
|
||||||
|
saddr: saddr,
|
||||||
|
deadline: time.Now().Add(time.Second * time.Duration(ttl)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+26
-102
@@ -22,61 +22,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeviceConfig_DomainStrategy int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
DeviceConfig_FORCE_IP DeviceConfig_DomainStrategy = 0
|
|
||||||
DeviceConfig_FORCE_IP4 DeviceConfig_DomainStrategy = 1
|
|
||||||
DeviceConfig_FORCE_IP6 DeviceConfig_DomainStrategy = 2
|
|
||||||
DeviceConfig_FORCE_IP46 DeviceConfig_DomainStrategy = 3
|
|
||||||
DeviceConfig_FORCE_IP64 DeviceConfig_DomainStrategy = 4
|
|
||||||
)
|
|
||||||
|
|
||||||
// Enum value maps for DeviceConfig_DomainStrategy.
|
|
||||||
var (
|
|
||||||
DeviceConfig_DomainStrategy_name = map[int32]string{
|
|
||||||
0: "FORCE_IP",
|
|
||||||
1: "FORCE_IP4",
|
|
||||||
2: "FORCE_IP6",
|
|
||||||
3: "FORCE_IP46",
|
|
||||||
4: "FORCE_IP64",
|
|
||||||
}
|
|
||||||
DeviceConfig_DomainStrategy_value = map[string]int32{
|
|
||||||
"FORCE_IP": 0,
|
|
||||||
"FORCE_IP4": 1,
|
|
||||||
"FORCE_IP6": 2,
|
|
||||||
"FORCE_IP46": 3,
|
|
||||||
"FORCE_IP64": 4,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (x DeviceConfig_DomainStrategy) Enum() *DeviceConfig_DomainStrategy {
|
|
||||||
p := new(DeviceConfig_DomainStrategy)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x DeviceConfig_DomainStrategy) String() string {
|
|
||||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (DeviceConfig_DomainStrategy) Descriptor() protoreflect.EnumDescriptor {
|
|
||||||
return file_proxy_wireguard_config_proto_enumTypes[0].Descriptor()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (DeviceConfig_DomainStrategy) Type() protoreflect.EnumType {
|
|
||||||
return &file_proxy_wireguard_config_proto_enumTypes[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x DeviceConfig_DomainStrategy) Number() protoreflect.EnumNumber {
|
|
||||||
return protoreflect.EnumNumber(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use DeviceConfig_DomainStrategy.Descriptor instead.
|
|
||||||
func (DeviceConfig_DomainStrategy) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return file_proxy_wireguard_config_proto_rawDescGZIP(), []int{1, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
type PeerConfig struct {
|
type PeerConfig struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
PublicKey string `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
|
PublicKey string `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
|
||||||
@@ -154,19 +99,18 @@ func (x *PeerConfig) GetAllowedIps() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DeviceConfig struct {
|
type DeviceConfig struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
SecretKey string `protobuf:"bytes,1,opt,name=secret_key,json=secretKey,proto3" json:"secret_key,omitempty"`
|
SecretKey string `protobuf:"bytes,1,opt,name=secret_key,json=secretKey,proto3" json:"secret_key,omitempty"`
|
||||||
Endpoint []string `protobuf:"bytes,2,rep,name=endpoint,proto3" json:"endpoint,omitempty"`
|
Endpoint []string `protobuf:"bytes,2,rep,name=endpoint,proto3" json:"endpoint,omitempty"`
|
||||||
Peers []*PeerConfig `protobuf:"bytes,3,rep,name=peers,proto3" json:"peers,omitempty"`
|
Peers []*PeerConfig `protobuf:"bytes,3,rep,name=peers,proto3" json:"peers,omitempty"`
|
||||||
Users []*protocol.User `protobuf:"bytes,5,rep,name=users,proto3" json:"users,omitempty"`
|
Users []*protocol.User `protobuf:"bytes,5,rep,name=users,proto3" json:"users,omitempty"`
|
||||||
Mtu int32 `protobuf:"varint,4,opt,name=mtu,proto3" json:"mtu,omitempty"`
|
Mtu int32 `protobuf:"varint,4,opt,name=mtu,proto3" json:"mtu,omitempty"`
|
||||||
Reserved []byte `protobuf:"bytes,6,opt,name=reserved,proto3" json:"reserved,omitempty"`
|
Reserved []byte `protobuf:"bytes,6,opt,name=reserved,proto3" json:"reserved,omitempty"`
|
||||||
DomainStrategy DeviceConfig_DomainStrategy `protobuf:"varint,7,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.proxy.wireguard.DeviceConfig_DomainStrategy" json:"domain_strategy,omitempty"`
|
IsClient bool `protobuf:"varint,8,opt,name=is_client,json=isClient,proto3" json:"is_client,omitempty"`
|
||||||
IsClient bool `protobuf:"varint,8,opt,name=is_client,json=isClient,proto3" json:"is_client,omitempty"`
|
NoKernelTun bool `protobuf:"varint,9,opt,name=no_kernel_tun,json=noKernelTun,proto3" json:"no_kernel_tun,omitempty"`
|
||||||
NoKernelTun bool `protobuf:"varint,9,opt,name=no_kernel_tun,json=noKernelTun,proto3" json:"no_kernel_tun,omitempty"`
|
DNS []string `protobuf:"bytes,10,rep,name=DNS,proto3" json:"DNS,omitempty"`
|
||||||
DNS []string `protobuf:"bytes,10,rep,name=DNS,proto3" json:"DNS,omitempty"`
|
unknownFields protoimpl.UnknownFields
|
||||||
unknownFields protoimpl.UnknownFields
|
sizeCache protoimpl.SizeCache
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *DeviceConfig) Reset() {
|
func (x *DeviceConfig) Reset() {
|
||||||
@@ -241,13 +185,6 @@ func (x *DeviceConfig) GetReserved() []byte {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *DeviceConfig) GetDomainStrategy() DeviceConfig_DomainStrategy {
|
|
||||||
if x != nil {
|
|
||||||
return x.DomainStrategy
|
|
||||||
}
|
|
||||||
return DeviceConfig_FORCE_IP
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *DeviceConfig) GetIsClient() bool {
|
func (x *DeviceConfig) GetIsClient() bool {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.IsClient
|
return x.IsClient
|
||||||
@@ -283,7 +220,7 @@ const file_proxy_wireguard_config_proto_rawDesc = "" +
|
|||||||
"\n" +
|
"\n" +
|
||||||
"keep_alive\x18\x04 \x01(\tR\tkeepAlive\x12\x1f\n" +
|
"keep_alive\x18\x04 \x01(\tR\tkeepAlive\x12\x1f\n" +
|
||||||
"\vallowed_ips\x18\x05 \x03(\tR\n" +
|
"\vallowed_ips\x18\x05 \x03(\tR\n" +
|
||||||
"allowedIps\"\xee\x03\n" +
|
"allowedIps\"\xb4\x02\n" +
|
||||||
"\fDeviceConfig\x12\x1d\n" +
|
"\fDeviceConfig\x12\x1d\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"secret_key\x18\x01 \x01(\tR\tsecretKey\x12\x1a\n" +
|
"secret_key\x18\x01 \x01(\tR\tsecretKey\x12\x1a\n" +
|
||||||
@@ -291,20 +228,11 @@ const file_proxy_wireguard_config_proto_rawDesc = "" +
|
|||||||
"\x05peers\x18\x03 \x03(\v2 .xray.proxy.wireguard.PeerConfigR\x05peers\x120\n" +
|
"\x05peers\x18\x03 \x03(\v2 .xray.proxy.wireguard.PeerConfigR\x05peers\x120\n" +
|
||||||
"\x05users\x18\x05 \x03(\v2\x1a.xray.common.protocol.UserR\x05users\x12\x10\n" +
|
"\x05users\x18\x05 \x03(\v2\x1a.xray.common.protocol.UserR\x05users\x12\x10\n" +
|
||||||
"\x03mtu\x18\x04 \x01(\x05R\x03mtu\x12\x1a\n" +
|
"\x03mtu\x18\x04 \x01(\x05R\x03mtu\x12\x1a\n" +
|
||||||
"\breserved\x18\x06 \x01(\fR\breserved\x12Z\n" +
|
"\breserved\x18\x06 \x01(\fR\breserved\x12\x1b\n" +
|
||||||
"\x0fdomain_strategy\x18\a \x01(\x0e21.xray.proxy.wireguard.DeviceConfig.DomainStrategyR\x0edomainStrategy\x12\x1b\n" +
|
|
||||||
"\tis_client\x18\b \x01(\bR\bisClient\x12\"\n" +
|
"\tis_client\x18\b \x01(\bR\bisClient\x12\"\n" +
|
||||||
"\rno_kernel_tun\x18\t \x01(\bR\vnoKernelTun\x12\x10\n" +
|
"\rno_kernel_tun\x18\t \x01(\bR\vnoKernelTun\x12\x10\n" +
|
||||||
"\x03DNS\x18\n" +
|
"\x03DNS\x18\n" +
|
||||||
" \x03(\tR\x03DNS\"\\\n" +
|
" \x03(\tR\x03DNSB^\n" +
|
||||||
"\x0eDomainStrategy\x12\f\n" +
|
|
||||||
"\bFORCE_IP\x10\x00\x12\r\n" +
|
|
||||||
"\tFORCE_IP4\x10\x01\x12\r\n" +
|
|
||||||
"\tFORCE_IP6\x10\x02\x12\x0e\n" +
|
|
||||||
"\n" +
|
|
||||||
"FORCE_IP46\x10\x03\x12\x0e\n" +
|
|
||||||
"\n" +
|
|
||||||
"FORCE_IP64\x10\x04B^\n" +
|
|
||||||
"\x18com.xray.proxy.wireguardP\x01Z)github.com/xtls/xray-core/proxy/wireguard\xaa\x02\x14Xray.Proxy.WireGuardb\x06proto3"
|
"\x18com.xray.proxy.wireguardP\x01Z)github.com/xtls/xray-core/proxy/wireguard\xaa\x02\x14Xray.Proxy.WireGuardb\x06proto3"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -319,23 +247,20 @@ func file_proxy_wireguard_config_proto_rawDescGZIP() []byte {
|
|||||||
return file_proxy_wireguard_config_proto_rawDescData
|
return file_proxy_wireguard_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_proxy_wireguard_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
|
||||||
var file_proxy_wireguard_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
var file_proxy_wireguard_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||||
var file_proxy_wireguard_config_proto_goTypes = []any{
|
var file_proxy_wireguard_config_proto_goTypes = []any{
|
||||||
(DeviceConfig_DomainStrategy)(0), // 0: xray.proxy.wireguard.DeviceConfig.DomainStrategy
|
(*PeerConfig)(nil), // 0: xray.proxy.wireguard.PeerConfig
|
||||||
(*PeerConfig)(nil), // 1: xray.proxy.wireguard.PeerConfig
|
(*DeviceConfig)(nil), // 1: xray.proxy.wireguard.DeviceConfig
|
||||||
(*DeviceConfig)(nil), // 2: xray.proxy.wireguard.DeviceConfig
|
(*protocol.User)(nil), // 2: xray.common.protocol.User
|
||||||
(*protocol.User)(nil), // 3: xray.common.protocol.User
|
|
||||||
}
|
}
|
||||||
var file_proxy_wireguard_config_proto_depIdxs = []int32{
|
var file_proxy_wireguard_config_proto_depIdxs = []int32{
|
||||||
1, // 0: xray.proxy.wireguard.DeviceConfig.peers:type_name -> xray.proxy.wireguard.PeerConfig
|
0, // 0: xray.proxy.wireguard.DeviceConfig.peers:type_name -> xray.proxy.wireguard.PeerConfig
|
||||||
3, // 1: xray.proxy.wireguard.DeviceConfig.users:type_name -> xray.common.protocol.User
|
2, // 1: xray.proxy.wireguard.DeviceConfig.users:type_name -> xray.common.protocol.User
|
||||||
0, // 2: xray.proxy.wireguard.DeviceConfig.domain_strategy:type_name -> xray.proxy.wireguard.DeviceConfig.DomainStrategy
|
2, // [2:2] is the sub-list for method output_type
|
||||||
3, // [3:3] is the sub-list for method output_type
|
2, // [2:2] is the sub-list for method input_type
|
||||||
3, // [3:3] is the sub-list for method input_type
|
2, // [2:2] is the sub-list for extension type_name
|
||||||
3, // [3:3] is the sub-list for extension type_name
|
2, // [2:2] is the sub-list for extension extendee
|
||||||
3, // [3:3] is the sub-list for extension extendee
|
0, // [0:2] is the sub-list for field type_name
|
||||||
0, // [0:3] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_proxy_wireguard_config_proto_init() }
|
func init() { file_proxy_wireguard_config_proto_init() }
|
||||||
@@ -348,14 +273,13 @@ func file_proxy_wireguard_config_proto_init() {
|
|||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proxy_wireguard_config_proto_rawDesc), len(file_proxy_wireguard_config_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proxy_wireguard_config_proto_rawDesc), len(file_proxy_wireguard_config_proto_rawDesc)),
|
||||||
NumEnums: 1,
|
NumEnums: 0,
|
||||||
NumMessages: 2,
|
NumMessages: 2,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
GoTypes: file_proxy_wireguard_config_proto_goTypes,
|
GoTypes: file_proxy_wireguard_config_proto_goTypes,
|
||||||
DependencyIndexes: file_proxy_wireguard_config_proto_depIdxs,
|
DependencyIndexes: file_proxy_wireguard_config_proto_depIdxs,
|
||||||
EnumInfos: file_proxy_wireguard_config_proto_enumTypes,
|
|
||||||
MessageInfos: file_proxy_wireguard_config_proto_msgTypes,
|
MessageInfos: file_proxy_wireguard_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_proxy_wireguard_config_proto = out.File
|
File_proxy_wireguard_config_proto = out.File
|
||||||
|
|||||||
@@ -17,13 +17,6 @@ message PeerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message DeviceConfig {
|
message DeviceConfig {
|
||||||
enum DomainStrategy {
|
|
||||||
FORCE_IP = 0;
|
|
||||||
FORCE_IP4 = 1;
|
|
||||||
FORCE_IP6 = 2;
|
|
||||||
FORCE_IP46 = 3;
|
|
||||||
FORCE_IP64 = 4;
|
|
||||||
}
|
|
||||||
string secret_key = 1;
|
string secret_key = 1;
|
||||||
repeated string endpoint = 2;
|
repeated string endpoint = 2;
|
||||||
repeated PeerConfig peers = 3;
|
repeated PeerConfig peers = 3;
|
||||||
@@ -31,7 +24,6 @@ message DeviceConfig {
|
|||||||
int32 mtu = 4;
|
int32 mtu = 4;
|
||||||
|
|
||||||
bytes reserved = 6;
|
bytes reserved = 6;
|
||||||
DomainStrategy domain_strategy = 7;
|
|
||||||
bool is_client = 8;
|
bool is_client = 8;
|
||||||
bool no_kernel_tun = 9;
|
bool no_kernel_tun = 9;
|
||||||
repeated string DNS = 10;
|
repeated string DNS = 10;
|
||||||
|
|||||||
+144
-9
@@ -15,6 +15,8 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
@@ -219,6 +221,7 @@ type Net struct {
|
|||||||
DialUDPAddrPort func(laddr, raddr netip.AddrPort) (net.Conn, error)
|
DialUDPAddrPort func(laddr, raddr netip.AddrPort) (net.Conn, error)
|
||||||
dnsServers []netip.Addr
|
dnsServers []netip.Addr
|
||||||
hasV4, hasV6 bool
|
hasV4, hasV6 bool
|
||||||
|
cache cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertToFullAddr(endpoint netip.AddrPort) (tcpip.FullAddress, tcpip.NetworkProtocolNumber) {
|
func convertToFullAddr(endpoint netip.AddrPort) (tcpip.FullAddress, tcpip.NetworkProtocolNumber) {
|
||||||
@@ -246,9 +249,12 @@ var (
|
|||||||
errServerTemporarilyMisbehaving = errors.New("server misbehaving")
|
errServerTemporarilyMisbehaving = errors.New("server misbehaving")
|
||||||
errCanceled = errors.New("operation was canceled")
|
errCanceled = errors.New("operation was canceled")
|
||||||
errTimeout = errors.New("i/o timeout")
|
errTimeout = errors.New("i/o timeout")
|
||||||
|
errNumericPort = errors.New("port must be numeric")
|
||||||
|
errNoSuitableAddress = errors.New("no suitable address found")
|
||||||
|
errMissingAddress = errors.New("missing address")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (net *Net) LookupHost(host string) (addrs []net.IP, ttl uint32, err error) {
|
func (net *Net) LookupHost(host string) (addrs []string, err error) {
|
||||||
return net.LookupContextHost(context.Background(), host)
|
return net.LookupContextHost(context.Background(), host)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -567,9 +573,12 @@ func (tnet *Net) tryOneName(ctx context.Context, name string, qtype dnsmessage.T
|
|||||||
return dnsmessage.Parser{}, "", lastErr
|
return dnsmessage.Parser{}, "", lastErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tnet *Net) LookupContextHost(ctx context.Context, host string) ([]net.IP, uint32, error) {
|
func (tnet *Net) LookupContextHost(ctx context.Context, host string) ([]string, error) {
|
||||||
|
if saddr := tnet.cache.LookupHost(host); saddr != nil {
|
||||||
|
return saddr, nil
|
||||||
|
}
|
||||||
if host == "" || (!tnet.hasV6 && !tnet.hasV4) {
|
if host == "" || (!tnet.hasV6 && !tnet.hasV4) {
|
||||||
return nil, 0, &net.DNSError{Err: errNoSuchHost.Error(), Name: host, IsNotFound: true}
|
return nil, &net.DNSError{Err: errNoSuchHost.Error(), Name: host, IsNotFound: true}
|
||||||
}
|
}
|
||||||
zlen := len(host)
|
zlen := len(host)
|
||||||
if strings.IndexByte(host, ':') != -1 {
|
if strings.IndexByte(host, ':') != -1 {
|
||||||
@@ -578,11 +587,11 @@ func (tnet *Net) LookupContextHost(ctx context.Context, host string) ([]net.IP,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ip, err := netip.ParseAddr(host[:zlen]); err == nil {
|
if ip, err := netip.ParseAddr(host[:zlen]); err == nil {
|
||||||
return []net.IP{ip.AsSlice()}, 0, nil
|
return []string{ip.String()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isDomainName(host) {
|
if !isDomainName(host) {
|
||||||
return nil, 0, &net.DNSError{Err: errNoSuchHost.Error(), Name: host, IsNotFound: true}
|
return nil, &net.DNSError{Err: errNoSuchHost.Error(), Name: host, IsNotFound: true}
|
||||||
}
|
}
|
||||||
type result struct {
|
type result struct {
|
||||||
p dnsmessage.Parser
|
p dnsmessage.Parser
|
||||||
@@ -683,11 +692,137 @@ func (tnet *Net) LookupContextHost(ctx context.Context, host string) ([]net.IP,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(addrs) == 0 && lastErr != nil {
|
if len(addrs) == 0 && lastErr != nil {
|
||||||
return nil, 0, lastErr
|
return nil, lastErr
|
||||||
}
|
}
|
||||||
ips := make([]net.IP, 0, len(addrs))
|
saddrs := make([]string, 0, len(addrs))
|
||||||
for _, ip := range addrs {
|
for _, ip := range addrs {
|
||||||
ips = append(ips, ip.AsSlice())
|
saddrs = append(saddrs, ip.String())
|
||||||
}
|
}
|
||||||
return ips, ttl, nil
|
tnet.cache.Cache(host, saddrs, ttl)
|
||||||
|
return saddrs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func partialDeadline(now, deadline time.Time, addrsRemaining int) (time.Time, error) {
|
||||||
|
if deadline.IsZero() {
|
||||||
|
return deadline, nil
|
||||||
|
}
|
||||||
|
timeRemaining := deadline.Sub(now)
|
||||||
|
if timeRemaining <= 0 {
|
||||||
|
return time.Time{}, errTimeout
|
||||||
|
}
|
||||||
|
timeout := timeRemaining / time.Duration(addrsRemaining)
|
||||||
|
const saneMinimum = 2 * time.Second
|
||||||
|
if timeout < saneMinimum {
|
||||||
|
if timeRemaining < saneMinimum {
|
||||||
|
timeout = timeRemaining
|
||||||
|
} else {
|
||||||
|
timeout = saneMinimum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return now.Add(timeout), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var protoSplitter = regexp.MustCompile(`^(tcp|udp|ping)(4|6)?$`)
|
||||||
|
|
||||||
|
func (tnet *Net) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
|
if ctx == nil {
|
||||||
|
panic("nil context")
|
||||||
|
}
|
||||||
|
var acceptV4, acceptV6 bool
|
||||||
|
matches := protoSplitter.FindStringSubmatch(network)
|
||||||
|
if matches == nil {
|
||||||
|
return nil, &net.OpError{Op: "dial", Err: net.UnknownNetworkError(network)}
|
||||||
|
} else if len(matches[2]) == 0 {
|
||||||
|
acceptV4 = true
|
||||||
|
acceptV6 = true
|
||||||
|
} else {
|
||||||
|
acceptV4 = matches[2][0] == '4'
|
||||||
|
acceptV6 = !acceptV4
|
||||||
|
}
|
||||||
|
var host string
|
||||||
|
var port int
|
||||||
|
if matches[1] == "ping" {
|
||||||
|
host = address
|
||||||
|
} else {
|
||||||
|
var sport string
|
||||||
|
var err error
|
||||||
|
host, sport, err = net.SplitHostPort(address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, &net.OpError{Op: "dial", Err: err}
|
||||||
|
}
|
||||||
|
port, err = strconv.Atoi(sport)
|
||||||
|
if err != nil || port < 0 || port > 65535 {
|
||||||
|
return nil, &net.OpError{Op: "dial", Err: errNumericPort}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allAddr, err := tnet.LookupContextHost(ctx, host)
|
||||||
|
if err != nil {
|
||||||
|
return nil, &net.OpError{Op: "dial", Err: err}
|
||||||
|
}
|
||||||
|
var addrs []netip.AddrPort
|
||||||
|
for _, addr := range allAddr {
|
||||||
|
ip, err := netip.ParseAddr(addr)
|
||||||
|
if err == nil && ((ip.Is4() && acceptV4) || (ip.Is6() && acceptV6)) {
|
||||||
|
addrs = append(addrs, netip.AddrPortFrom(ip, uint16(port)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(addrs) == 0 && len(allAddr) != 0 {
|
||||||
|
return nil, &net.OpError{Op: "dial", Err: errNoSuitableAddress}
|
||||||
|
}
|
||||||
|
|
||||||
|
var firstErr error
|
||||||
|
for i, addr := range addrs {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
err := ctx.Err()
|
||||||
|
if err == context.Canceled {
|
||||||
|
err = errCanceled
|
||||||
|
} else if err == context.DeadlineExceeded {
|
||||||
|
err = errTimeout
|
||||||
|
}
|
||||||
|
return nil, &net.OpError{Op: "dial", Err: err}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
dialCtx := ctx
|
||||||
|
if deadline, hasDeadline := ctx.Deadline(); hasDeadline {
|
||||||
|
partialDeadline, err := partialDeadline(time.Now(), deadline, len(addrs)-i)
|
||||||
|
if err != nil {
|
||||||
|
if firstErr == nil {
|
||||||
|
firstErr = &net.OpError{Op: "dial", Err: err}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if partialDeadline.Before(deadline) {
|
||||||
|
var cancel context.CancelFunc
|
||||||
|
dialCtx, cancel = context.WithDeadline(ctx, partialDeadline)
|
||||||
|
defer cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var c net.Conn
|
||||||
|
switch matches[1] {
|
||||||
|
case "tcp":
|
||||||
|
c, err = tnet.DialContextTCPAddrPort(dialCtx, addr)
|
||||||
|
case "udp":
|
||||||
|
c, err = tnet.DialUDPAddrPort(netip.AddrPort{}, addr)
|
||||||
|
case "ping":
|
||||||
|
err = errors.New("not support")
|
||||||
|
// c, err = tnet.DialPingAddr(netip.Addr{}, addr.Addr())
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
if firstErr == nil {
|
||||||
|
firstErr = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if firstErr == nil {
|
||||||
|
firstErr = &net.OpError{Op: "dial", Err: errMissingAddress}
|
||||||
|
}
|
||||||
|
return nil, firstErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tnet *Net) Dial(network, address string) (net.Conn, error) {
|
||||||
|
return tnet.DialContext(context.Background(), network, address)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user