Fix: resolver dial context udp

This commit is contained in:
yaling888
2021-11-11 00:53:42 +08:00
parent 038cc1f6b5
commit d0c23998d2
5 changed files with 79 additions and 10 deletions

View File

@ -49,14 +49,14 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error)
}
var conn net.Conn
if c.proxyAdapter != "" && network == "tcp" {
conn, err = dialContextWithProxyAdapter(ctx, c.proxyAdapter, ip, c.port)
} else {
if c.proxyAdapter == "" {
options := []dialer.Option{}
if c.iface != "" {
options = append(options, dialer.WithInterface(c.iface))
}
conn, err = dialer.DialContext(ctx, network, net.JoinHostPort(c.host, c.port), options...)
conn, err = dialer.DialContext(ctx, network, net.JoinHostPort(ip.String(), c.port), options...)
} else {
conn, err = dialContextWithProxyAdapter(ctx, c.proxyAdapter, network, ip, c.port)
}
if err != nil {

View File

@ -100,7 +100,7 @@ func newDoHClient(url string, r *Resolver, proxyAdapter string) *dohClient {
if proxyAdapter == "" {
return dialer.DialContext(ctx, "tcp", net.JoinHostPort(ip.String(), port))
} else {
return dialContextWithProxyAdapter(ctx, proxyAdapter, ip, port)
return dialContextWithProxyAdapter(ctx, proxyAdapter, "tcp", ip, port)
}
},
},

View File

@ -379,6 +379,7 @@ func NewMainResolver(old *Resolver) *Resolver {
main: old.main,
lruCache: old.lruCache,
hosts: old.hosts,
policy: old.policy,
}
return r
}

View File

@ -110,25 +110,62 @@ func msgToIP(msg *D.Msg) []net.IP {
return ips
}
func dialContextWithProxyAdapter(ctx context.Context, adapterName string, dstIP net.IP, port string) (net.Conn, error) {
type wrapPacketConn struct {
net.PacketConn
rAddr net.Addr
}
func (wpc *wrapPacketConn) Read(b []byte) (n int, err error) {
n, _, err = wpc.PacketConn.ReadFrom(b)
return n, err
}
func (wpc *wrapPacketConn) Write(b []byte) (n int, err error) {
return wpc.PacketConn.WriteTo(b, wpc.rAddr)
}
func (wpc *wrapPacketConn) RemoteAddr() net.Addr {
return wpc.rAddr
}
func dialContextWithProxyAdapter(ctx context.Context, adapterName string, network string, dstIP net.IP, port string) (net.Conn, error) {
adapter, ok := tunnel.Proxies()[adapterName]
if !ok {
return nil, fmt.Errorf("proxy dapter [%s] not found", adapterName)
return nil, fmt.Errorf("proxy adapter [%s] not found", adapterName)
}
networkType := C.TCP
if network == "udp" {
if !adapter.SupportUDP() {
return nil, fmt.Errorf("proxy adapter [%s] UDP is not supported", adapterName)
}
networkType = C.UDP
}
addrType := C.AtypIPv4
if dstIP.To4() == nil {
addrType = C.AtypIPv6
}
metadata := &C.Metadata{
NetWork: C.TCP,
NetWork: networkType,
AddrType: addrType,
Host: "",
DstIP: dstIP,
DstPort: port,
}
if networkType == C.UDP {
packetConn, err := adapter.ListenPacketContext(ctx, metadata)
if err != nil {
return nil, err
}
return &wrapPacketConn{
PacketConn: packetConn,
rAddr: metadata.UDPAddr(),
}, nil
}
return adapter.DialContext(ctx, metadata)
}