diff --git a/component/control/tcp.go b/component/control/tcp.go index 7bc3772..5e63c02 100644 --- a/component/control/tcp.go +++ b/component/control/tcp.go @@ -49,14 +49,19 @@ func (c *ControlPlane) handleConn(lConn net.Conn) (err error) { outbound := c.outbounds[value.Outbound] // TODO: Set-up ip to domain mapping and show domain if possible. src := lConn.RemoteAddr().(*net.TCPAddr).AddrPort() - c.log.WithFields(logrus.Fields{ - "l4proto": "TCP", - "outbound": outbound.Name, - }).Infof("%v <-> %v", RefineSourceToShow(src, dst.Addr()), RefineAddrPortToShow(dst)) if value.Outbound < 0 || int(value.Outbound) >= len(c.outbounds) { return fmt.Errorf("outbound id from bpf is out of range: %v not in [0, %v]", value.Outbound, len(c.outbounds)-1) } - rConn, err := outbound.Dial("tcp", dst.String()) + dialer, err := outbound.Select() + if err != nil { + return fmt.Errorf("failed to select dialer from group %v: %w", outbound.Name, err) + } + c.log.WithFields(logrus.Fields{ + "l4proto": "TCP", + "outbound": outbound.Name, + "dialer": dialer.Name(), + }).Infof("%v <-> %v", RefineSourceToShow(src, dst.Addr()), RefineAddrPortToShow(dst)) + rConn, err := dialer.Dial("tcp", dst.String()) if err != nil { return fmt.Errorf("failed to dial %v: %w", dst, err) } diff --git a/component/control/udp.go b/component/control/udp.go index 4ad3ae2..ebdc4c6 100644 --- a/component/control/udp.go +++ b/component/control/udp.go @@ -11,6 +11,7 @@ import ( "github.com/mzz2017/softwind/pool" "github.com/sirupsen/logrus" "github.com/v2rayA/dae/common/consts" + "github.com/v2rayA/dae/component/outbound/dialer" "golang.org/x/net/dns/dnsmessage" "net" "net/netip" @@ -120,43 +121,59 @@ func (c *ControlPlane) handlePkt(data []byte, lConn *net.UDPConn, lAddrPort neti } if c.log.IsLevelEnabled(logrus.DebugLevel) && len(dnsMessage.Questions) > 0 { q := dnsMessage.Questions[0] - c.log.Debugf("UDP(DNS) %v <-[%v]-> Cache: %v %v", + c.log.Tracef("UDP(DNS) %v <-[%v]-> Cache: %v %v", RefineSourceToShow(lAddrPort, dest.Addr()), outbound.Name, q.Name, q.Type, ) } return nil } else { - c.log.Debugf("Modify dns target %v to upstream: %v", RefineAddrPortToShow(dest), c.dnsUpstream) + c.log.Tracef("Modify dns target %v to upstream: %v", RefineAddrPortToShow(dest), c.dnsUpstream) // Modify dns target to upstream. // NOTICE: Routing was calculated in advance by the eBPF program. dummyFrom = &addrHdr.Dest dest = c.dnsUpstream - - if c.log.IsLevelEnabled(logrus.DebugLevel) && len(dnsMessage.Questions) > 0 { - q := dnsMessage.Questions[0] - c.log.Debugf("UDP(DNS) %v <-[%v]-> %v: %v %v", - RefineSourceToShow(lAddrPort, addrHdr.Dest.Addr()), outbound.Name, RefineAddrPortToShow(dest), q.Name, q.Type, - ) - } } + } + + ue, err := DefaultUdpEndpointPool.GetOrCreate(lAddrPort, &UdpEndpointOptions{ + Handler: c.RelayToUDP(lConn, lAddrPort, isDns, dummyFrom), + NatTimeout: natTimeout, + DialerFunc: func() (*dialer.Dialer, error) { + newDialer, err := outbound.Select() + if err != nil { + return nil, fmt.Errorf("failed to select dialer from group %v: %w", outbound.Name, err) + } + return newDialer, nil + }, + Target: dest, + }) + if err != nil { + return fmt.Errorf("failed to GetOrCreate: %w", err) + } + // This is real dialer. + d := ue.Dialer + + if isDns && c.log.IsLevelEnabled(logrus.DebugLevel) && len(dnsMessage.Questions) > 0 { + q := dnsMessage.Questions[0] + c.log.WithFields(logrus.Fields{ + "l4proto": "UDP(DNS)", + "outbound": outbound.Name, + "dialer": d.Name(), + "qname": q.Name, + "qtype": q.Type, + }).Infof("%v <-> %v", + RefineSourceToShow(lAddrPort, dest.Addr()), RefineAddrPortToShow(dest), + ) } else { // TODO: Set-up ip to domain mapping and show domain if possible. c.log.WithFields(logrus.Fields{ "l4proto": "UDP", "outbound": outbound.Name, + "dialer": d.Name(), }).Infof("%v <-> %v", RefineSourceToShow(lAddrPort, dest.Addr()), RefineAddrPortToShow(dest), ) } - ue, err := DefaultUdpEndpointPool.GetOrCreate(lAddrPort, &UdpEndpointOptions{ - Handler: c.RelayToUDP(lConn, lAddrPort, isDns, dummyFrom), - NatTimeout: natTimeout, - Dialer: outbound, - Target: dest, - }) - if err != nil { - return fmt.Errorf("failed to GetOrCreate: %w", err) - } //log.Printf("WriteToUDPAddrPort->%v", dest) _, err = ue.WriteToUDPAddrPort(data, dest) if err != nil { diff --git a/component/control/udp_endpoint.go b/component/control/udp_endpoint.go index 347fb2e..693fc28 100644 --- a/component/control/udp_endpoint.go +++ b/component/control/udp_endpoint.go @@ -8,7 +8,7 @@ package control import ( "fmt" "github.com/mzz2017/softwind/pool" - "golang.org/x/net/proxy" + "github.com/v2rayA/dae/component/outbound/dialer" "net" "net/netip" "sync" @@ -24,6 +24,8 @@ type UdpEndpoint struct { deadlineTimer *time.Timer handler UdpHandler NatTimeout time.Duration + + Dialer *dialer.Dialer } func (ue *UdpEndpoint) start() { @@ -67,7 +69,7 @@ type UdpEndpointPool struct { type UdpEndpointOptions struct { Handler UdpHandler NatTimeout time.Duration - Dialer proxy.Dialer + DialerFunc func() (*dialer.Dialer, error) // Target is useful only if the underlay does not support Full-cone. Target netip.AddrPort } @@ -96,7 +98,12 @@ func (p *UdpEndpointPool) GetOrCreate(lAddr netip.AddrPort, createOption *UdpEnd return nil, fmt.Errorf("createOption.Handler cannot be nil") } - udpConn, err := createOption.Dialer.Dial("udp", createOption.Target.String()) + d, err := createOption.DialerFunc() + if err != nil { + return nil, err + } + + udpConn, err := d.Dial("udp", createOption.Target.String()) if err != nil { return nil, err } @@ -112,6 +119,7 @@ func (p *UdpEndpointPool) GetOrCreate(lAddr netip.AddrPort, createOption *UdpEnd }), handler: createOption.Handler, NatTimeout: createOption.NatTimeout, + Dialer: d, } p.pool[lAddr] = ue // Receive UDP messages. diff --git a/component/outbound/dialer/alive_dialer_set.go b/component/outbound/dialer/alive_dialer_set.go index 3099225..485c68f 100644 --- a/component/outbound/dialer/alive_dialer_set.go +++ b/component/outbound/dialer/alive_dialer_set.go @@ -164,7 +164,7 @@ func (a *AliveDialerSet) SetAlive(dialer *Dialer, alive bool) { a.log.WithFields(logrus.Fields{ "group": a.dialerGroupName, "dialer": a.minLatency.dialer.Name(), - }).Infof("Group re-selects dialer") + }).Infof("Group selects dialer") } } } diff --git a/component/outbound/dialer_group.go b/component/outbound/dialer_group.go index d7b6120..d67edcd 100644 --- a/component/outbound/dialer_group.go +++ b/component/outbound/dialer_group.go @@ -117,6 +117,5 @@ func (g *DialerGroup) Dial(network string, addr string) (c net.Conn, err error) if err != nil { return nil, err } - g.log.Tracef("Group [%v] dial using <%v>", g.Name, d.Name()) return d.Dial(network, addr) }