mirror of
https://github.com/folbricht/routedns.git
synced 2025-12-19 00:20:31 -06:00
112 lines
2.3 KiB
Go
112 lines
2.3 KiB
Go
package rdns
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
func NewNetDialer(r Resolver) *net.Dialer {
|
|
return &net.Dialer{
|
|
Resolver: NewNetResolver(r),
|
|
}
|
|
}
|
|
|
|
// NewNetResolver returns a new.Resolver that is backed by a RouteDNS resolver
|
|
// instead of the system's.
|
|
func NewNetResolver(r Resolver) *net.Resolver {
|
|
return &net.Resolver{
|
|
PreferGo: true,
|
|
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
|
return newConn(r, network, address), nil
|
|
},
|
|
}
|
|
}
|
|
|
|
// var _ net.PacketConn = &packetConn{}
|
|
var _ net.Conn = &packetConn{}
|
|
|
|
// packetConn implements net.PacketConn and is used in the Dial() func in a
|
|
// net.Resolver to redirect lookups through one of RouteDNS' resolvers instead
|
|
// of the system ones.
|
|
type packetConn struct {
|
|
network string
|
|
address string
|
|
r Resolver
|
|
ch chan *dns.Msg
|
|
}
|
|
|
|
func newConn(r Resolver, network, address string) *packetConn {
|
|
return &packetConn{
|
|
network: network,
|
|
address: address,
|
|
r: r,
|
|
ch: make(chan *dns.Msg, 1),
|
|
}
|
|
}
|
|
|
|
func (c *packetConn) Read(p []byte) (n int, err error) {
|
|
a := <-c.ch
|
|
b, err := a.Pack()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
if len(p) < len(b) {
|
|
return 0, errors.New("read buffer too small")
|
|
}
|
|
copy(p, b)
|
|
return len(b), nil
|
|
}
|
|
|
|
// These functions need to exist to implement net.PacketConn as the net.Resolver
|
|
// then uses Read/Write in UDP mode. They're not called but need to be present.
|
|
func (c *packetConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
|
return 0, nil, nil
|
|
}
|
|
|
|
func (c *packetConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|
return len(p), nil
|
|
}
|
|
|
|
func (c *packetConn) Write(p []byte) (n int, err error) {
|
|
// Decode the query
|
|
q := new(dns.Msg)
|
|
if err := q.Unpack(p); err != nil {
|
|
return len(p), err
|
|
}
|
|
|
|
a, err := c.r.Resolve(q, ClientInfo{SourceIP: net.IP{127, 0, 0, 1}})
|
|
if err != nil {
|
|
return len(p), err
|
|
}
|
|
c.ch <- a
|
|
return len(p), nil
|
|
}
|
|
|
|
func (c *packetConn) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func (c *packetConn) LocalAddr() net.Addr {
|
|
return nil
|
|
}
|
|
|
|
func (c *packetConn) RemoteAddr() net.Addr {
|
|
return nil
|
|
}
|
|
|
|
func (c *packetConn) SetDeadline(t time.Time) error {
|
|
return nil
|
|
}
|
|
|
|
func (c *packetConn) SetReadDeadline(t time.Time) error {
|
|
return nil
|
|
}
|
|
|
|
func (c *packetConn) SetWriteDeadline(t time.Time) error {
|
|
return nil
|
|
}
|