all: ignoring local interfaces RFC1918 IP for private resolver

Otherwises, the discovery may make a looping with new PTR query flow.
This commit is contained in:
Cuong Manh Le
2023-12-05 01:29:31 +07:00
committed by Cuong Manh Le
parent 5897c174d3
commit c3ff8182af
3 changed files with 29 additions and 18 deletions

View File

@@ -114,7 +114,7 @@ func (p *prog) serveDNS(listenerNum string) error {
// addresses of the machine. So ctrld could receive queries from LAN clients.
if needRFC1918Listeners(listenerConfig) {
g.Go(func() error {
for _, addr := range rfc1918Addresses() {
for _, addr := range ctrld.Rfc1918Addresses() {
func() {
listenAddr := net.JoinHostPort(addr, strconv.Itoa(listenerConfig.Port))
s, errCh := runDNSServer(listenAddr, proto, handler)
@@ -737,21 +737,6 @@ func needRFC1918Listeners(lc *ctrld.ListenerConfig) bool {
return lc.IP == "127.0.0.1" && lc.Port == 53
}
func rfc1918Addresses() []string {
var res []string
interfaces.ForeachInterface(func(i interfaces.Interface, prefixes []netip.Prefix) {
addrs, _ := i.Addrs()
for _, addr := range addrs {
ipNet, ok := addr.(*net.IPNet)
if !ok || !ipNet.IP.IsPrivate() {
continue
}
res = append(res, ipNet.IP.String())
}
})
return res
}
// ipFromARPA parses a FQDN arpa domain and return the IP address if valid.
func ipFromARPA(arpa string) net.IP {
if arpa, ok := strings.CutSuffix(arpa, ".in-addr.arpa."); ok {

View File

@@ -438,7 +438,7 @@ func (p *prog) setDNS() {
nameservers := []string{ns}
if needRFC1918Listeners(lc) {
nameservers = append(nameservers, rfc1918Addresses()...)
nameservers = append(nameservers, ctrld.Rfc1918Addresses()...)
}
if err := setDNS(netIface, nameservers); err != nil {
logger.Error().Err(err).Msgf("could not set DNS for interface")

View File

@@ -5,10 +5,12 @@ import (
"errors"
"fmt"
"net"
"net/netip"
"sync"
"time"
"github.com/miekg/dns"
"tailscale.com/net/interfaces"
)
const (
@@ -245,12 +247,16 @@ func NewBootstrapResolver(servers ...string) Resolver {
}
// NewPrivateResolver returns an OS resolver, which includes only private DNS servers,
// excluding nameservers from /etc/resolv.conf file.
// excluding:
//
// - Nameservers from /etc/resolv.conf file.
// - Nameservers which is local RFC1918 addresses.
//
// This is useful for doing PTR lookup in LAN network.
func NewPrivateResolver() Resolver {
nss := nameservers()
resolveConfNss := nameserversFromResolvconf()
localRfc1918Addrs := Rfc1918Addresses()
n := 0
for _, ns := range nss {
host, _, _ := net.SplitHostPort(ns)
@@ -263,6 +269,10 @@ func NewPrivateResolver() Resolver {
if sliceContains(resolveConfNss, host) {
continue
}
// Ignoring local RFC 1918 addresses.
if sliceContains(localRfc1918Addrs, host) {
continue
}
ip := net.ParseIP(host)
if ip != nil && ip.IsPrivate() && !ip.IsLoopback() {
nss[n] = ns
@@ -285,6 +295,22 @@ func NewResolverWithNameserver(nameservers []string) Resolver {
return &osResolver{nameservers: nameservers}
}
// Rfc1918Addresses returns the list of local interfaces private IP addresses
func Rfc1918Addresses() []string {
var res []string
interfaces.ForeachInterface(func(i interfaces.Interface, prefixes []netip.Prefix) {
addrs, _ := i.Addrs()
for _, addr := range addrs {
ipNet, ok := addr.(*net.IPNet)
if !ok || !ipNet.IP.IsPrivate() {
continue
}
res = append(res, ipNet.IP.String())
}
})
return res
}
func newDialer(dnsAddress string) *net.Dialer {
return &net.Dialer{
Resolver: &net.Resolver{