mirror of
https://github.com/netbirdio/netbird.git
synced 2026-05-01 06:36:39 +00:00
Add IPv6 reverse DNS and host configurator support
This commit is contained in:
@@ -12,52 +12,83 @@ import (
|
|||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createPTRRecord(aRecord nbdns.SimpleRecord, prefix netip.Prefix) (nbdns.SimpleRecord, bool) {
|
func createPTRRecord(record nbdns.SimpleRecord, prefix netip.Prefix) (nbdns.SimpleRecord, bool) {
|
||||||
ip, err := netip.ParseAddr(aRecord.RData)
|
ip, err := netip.ParseAddr(record.RData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("failed to parse IP address %s: %v", aRecord.RData, err)
|
log.Warnf("failed to parse IP address %s: %v", record.RData, err)
|
||||||
return nbdns.SimpleRecord{}, false
|
return nbdns.SimpleRecord{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ip = ip.Unmap()
|
||||||
if !prefix.Contains(ip) {
|
if !prefix.Contains(ip) {
|
||||||
return nbdns.SimpleRecord{}, false
|
return nbdns.SimpleRecord{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
ipOctets := strings.Split(ip.String(), ".")
|
var rdnsName string
|
||||||
slices.Reverse(ipOctets)
|
if ip.Is4() {
|
||||||
rdnsName := dns.Fqdn(strings.Join(ipOctets, ".") + ".in-addr.arpa")
|
octets := strings.Split(ip.String(), ".")
|
||||||
|
slices.Reverse(octets)
|
||||||
|
rdnsName = dns.Fqdn(strings.Join(octets, ".") + ".in-addr.arpa")
|
||||||
|
} else {
|
||||||
|
// Expand to full 32 nibbles in reverse order (LSB first) per RFC 3596.
|
||||||
|
raw := ip.As16()
|
||||||
|
nibbles := make([]string, 32)
|
||||||
|
for i := 0; i < 16; i++ {
|
||||||
|
nibbles[31-i*2] = fmt.Sprintf("%x", raw[i]>>4)
|
||||||
|
nibbles[31-i*2-1] = fmt.Sprintf("%x", raw[i]&0x0f)
|
||||||
|
}
|
||||||
|
rdnsName = dns.Fqdn(strings.Join(nibbles, ".") + ".ip6.arpa")
|
||||||
|
}
|
||||||
|
|
||||||
return nbdns.SimpleRecord{
|
return nbdns.SimpleRecord{
|
||||||
Name: rdnsName,
|
Name: rdnsName,
|
||||||
Type: int(dns.TypePTR),
|
Type: int(dns.TypePTR),
|
||||||
Class: aRecord.Class,
|
Class: record.Class,
|
||||||
TTL: aRecord.TTL,
|
TTL: record.TTL,
|
||||||
RData: dns.Fqdn(aRecord.Name),
|
RData: dns.Fqdn(record.Name),
|
||||||
}, true
|
}, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateReverseZoneName creates the reverse DNS zone name for a given network
|
// generateReverseZoneName creates the reverse DNS zone name for a given network.
|
||||||
|
// For IPv4 it produces an in-addr.arpa name, for IPv6 an ip6.arpa name.
|
||||||
func generateReverseZoneName(network netip.Prefix) (string, error) {
|
func generateReverseZoneName(network netip.Prefix) (string, error) {
|
||||||
networkIP := network.Masked().Addr()
|
networkIP := network.Masked().Addr().Unmap()
|
||||||
|
bits := network.Bits()
|
||||||
|
|
||||||
if !networkIP.Is4() {
|
if networkIP.Is4() {
|
||||||
return "", fmt.Errorf("reverse DNS is only supported for IPv4 networks, got: %s", networkIP)
|
// Round up to nearest byte.
|
||||||
|
octetsToUse := (bits + 7) / 8
|
||||||
|
|
||||||
|
octets := strings.Split(networkIP.String(), ".")
|
||||||
|
if octetsToUse > len(octets) {
|
||||||
|
return "", fmt.Errorf("invalid network mask size for reverse DNS: %d", bits)
|
||||||
|
}
|
||||||
|
|
||||||
|
reverseOctets := make([]string, octetsToUse)
|
||||||
|
for i := 0; i < octetsToUse; i++ {
|
||||||
|
reverseOctets[octetsToUse-1-i] = octets[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
return dns.Fqdn(strings.Join(reverseOctets, ".") + ".in-addr.arpa"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// round up to nearest byte
|
// IPv6: round up to nearest nibble (4-bit boundary).
|
||||||
octetsToUse := (network.Bits() + 7) / 8
|
nibblesToUse := (bits + 3) / 4
|
||||||
|
|
||||||
octets := strings.Split(networkIP.String(), ".")
|
raw := networkIP.As16()
|
||||||
if octetsToUse > len(octets) {
|
allNibbles := make([]string, 32)
|
||||||
return "", fmt.Errorf("invalid network mask size for reverse DNS: %d", network.Bits())
|
for i := 0; i < 16; i++ {
|
||||||
|
allNibbles[i*2] = fmt.Sprintf("%x", raw[i]>>4)
|
||||||
|
allNibbles[i*2+1] = fmt.Sprintf("%x", raw[i]&0x0f)
|
||||||
}
|
}
|
||||||
|
|
||||||
reverseOctets := make([]string, octetsToUse)
|
// Take the first nibblesToUse nibbles (network portion), reverse them.
|
||||||
for i := 0; i < octetsToUse; i++ {
|
used := make([]string, nibblesToUse)
|
||||||
reverseOctets[octetsToUse-1-i] = octets[i]
|
for i := 0; i < nibblesToUse; i++ {
|
||||||
|
used[nibblesToUse-1-i] = allNibbles[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
return dns.Fqdn(strings.Join(reverseOctets, ".") + ".in-addr.arpa"), nil
|
return dns.Fqdn(strings.Join(used, ".") + ".ip6.arpa"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// zoneExists checks if a zone with the given name already exists in the configuration
|
// zoneExists checks if a zone with the given name already exists in the configuration
|
||||||
@@ -71,7 +102,7 @@ func zoneExists(config *nbdns.Config, zoneName string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// collectPTRRecords gathers all PTR records for the given network from A records
|
// collectPTRRecords gathers all PTR records for the given network from A and AAAA records.
|
||||||
func collectPTRRecords(config *nbdns.Config, prefix netip.Prefix) []nbdns.SimpleRecord {
|
func collectPTRRecords(config *nbdns.Config, prefix netip.Prefix) []nbdns.SimpleRecord {
|
||||||
var records []nbdns.SimpleRecord
|
var records []nbdns.SimpleRecord
|
||||||
|
|
||||||
@@ -80,7 +111,7 @@ func collectPTRRecords(config *nbdns.Config, prefix netip.Prefix) []nbdns.Simple
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, record := range zone.Records {
|
for _, record := range zone.Records {
|
||||||
if record.Type != int(dns.TypeA) {
|
if record.Type != int(dns.TypeA) && record.Type != int(dns.TypeAAAA) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -298,6 +298,7 @@ func (s *systemConfigurator) getSystemDNSSettings() (SystemDNSSettings, error) {
|
|||||||
if ip, err := netip.ParseAddr(address); err == nil && !ip.IsUnspecified() {
|
if ip, err := netip.ParseAddr(address); err == nil && !ip.IsUnspecified() {
|
||||||
ip = ip.Unmap()
|
ip = ip.Unmap()
|
||||||
serverAddresses = append(serverAddresses, ip)
|
serverAddresses = append(serverAddresses, ip)
|
||||||
|
// Prefer the first IPv4 server as ServerIP since our DNS listener is IPv4.
|
||||||
if !dnsSettings.ServerIP.IsValid() && ip.Is4() {
|
if !dnsSettings.ServerIP.IsValid() && ip.Is4() {
|
||||||
dnsSettings.ServerIP = ip
|
dnsSettings.ServerIP = ip
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,8 +110,15 @@ func (n *networkManagerDbusConfigurator) applyDNSConfig(config HostDNSConfig, st
|
|||||||
|
|
||||||
connSettings.cleanDeprecatedSettings()
|
connSettings.cleanDeprecatedSettings()
|
||||||
|
|
||||||
convDNSIP := binary.LittleEndian.Uint32(config.ServerIP.AsSlice())
|
ipKey := networkManagerDbusIPv4Key
|
||||||
connSettings[networkManagerDbusIPv4Key][networkManagerDbusDNSKey] = dbus.MakeVariant([]uint32{convDNSIP})
|
if config.ServerIP.Is6() {
|
||||||
|
ipKey = networkManagerDbusIPv6Key
|
||||||
|
raw := config.ServerIP.As16()
|
||||||
|
connSettings[ipKey][networkManagerDbusDNSKey] = dbus.MakeVariant([][]byte{raw[:]})
|
||||||
|
} else {
|
||||||
|
convDNSIP := binary.LittleEndian.Uint32(config.ServerIP.AsSlice())
|
||||||
|
connSettings[ipKey][networkManagerDbusDNSKey] = dbus.MakeVariant([]uint32{convDNSIP})
|
||||||
|
}
|
||||||
var (
|
var (
|
||||||
searchDomains []string
|
searchDomains []string
|
||||||
matchDomains []string
|
matchDomains []string
|
||||||
@@ -146,8 +153,8 @@ func (n *networkManagerDbusConfigurator) applyDNSConfig(config HostDNSConfig, st
|
|||||||
n.routingAll = false
|
n.routingAll = false
|
||||||
}
|
}
|
||||||
|
|
||||||
connSettings[networkManagerDbusIPv4Key][networkManagerDbusDNSPriorityKey] = dbus.MakeVariant(priority)
|
connSettings[ipKey][networkManagerDbusDNSPriorityKey] = dbus.MakeVariant(priority)
|
||||||
connSettings[networkManagerDbusIPv4Key][networkManagerDbusDNSSearchKey] = dbus.MakeVariant(newDomainList)
|
connSettings[ipKey][networkManagerDbusDNSSearchKey] = dbus.MakeVariant(newDomainList)
|
||||||
|
|
||||||
state := &ShutdownState{
|
state := &ShutdownState{
|
||||||
ManagerType: networkManager,
|
ManagerType: networkManager,
|
||||||
|
|||||||
@@ -90,8 +90,12 @@ func (s *systemdDbusConfigurator) supportCustomPort() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *systemdDbusConfigurator) applyDNSConfig(config HostDNSConfig, stateManager *statemanager.Manager) error {
|
func (s *systemdDbusConfigurator) applyDNSConfig(config HostDNSConfig, stateManager *statemanager.Manager) error {
|
||||||
|
family := int32(unix.AF_INET)
|
||||||
|
if config.ServerIP.Is6() {
|
||||||
|
family = unix.AF_INET6
|
||||||
|
}
|
||||||
defaultLinkInput := systemdDbusDNSInput{
|
defaultLinkInput := systemdDbusDNSInput{
|
||||||
Family: unix.AF_INET,
|
Family: family,
|
||||||
Address: config.ServerIP.AsSlice(),
|
Address: config.ServerIP.AsSlice(),
|
||||||
}
|
}
|
||||||
if err := s.callLinkMethod(systemdDbusSetDNSMethodSuffix, []systemdDbusDNSInput{defaultLinkInput}); err != nil {
|
if err := s.callLinkMethod(systemdDbusSetDNSMethodSuffix, []systemdDbusDNSInput{defaultLinkInput}); err != nil {
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ type upstreamResolverIOS struct {
|
|||||||
*upstreamResolverBase
|
*upstreamResolverBase
|
||||||
lIP netip.Addr
|
lIP netip.Addr
|
||||||
lNet netip.Prefix
|
lNet netip.Prefix
|
||||||
|
lIPv6 netip.Addr
|
||||||
|
lNetV6 netip.Prefix
|
||||||
interfaceName string
|
interfaceName string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,6 +39,8 @@ func newUpstreamResolver(
|
|||||||
upstreamResolverBase: upstreamResolverBase,
|
upstreamResolverBase: upstreamResolverBase,
|
||||||
lIP: wgIface.Address().IP,
|
lIP: wgIface.Address().IP,
|
||||||
lNet: wgIface.Address().Network,
|
lNet: wgIface.Address().Network,
|
||||||
|
lIPv6: wgIface.Address().IPv6,
|
||||||
|
lNetV6: wgIface.Address().IPv6Net,
|
||||||
interfaceName: wgIface.Name(),
|
interfaceName: wgIface.Name(),
|
||||||
}
|
}
|
||||||
ios.upstreamClient = ios
|
ios.upstreamClient = ios
|
||||||
@@ -65,11 +69,27 @@ func (u *upstreamResolverIOS) exchange(ctx context.Context, upstream string, r *
|
|||||||
} else {
|
} else {
|
||||||
upstreamIP = upstreamIP.Unmap()
|
upstreamIP = upstreamIP.Unmap()
|
||||||
}
|
}
|
||||||
if u.lNet.Contains(upstreamIP) || upstreamIP.IsPrivate() {
|
// TODO: IsPrivate is a rough heuristic. It misses public IPs routed through
|
||||||
log.Debugf("using private client to query upstream: %s", upstream)
|
// the tunnel (e.g. 9.9.9.9 via network route) and incorrectly matches local
|
||||||
client, err = GetClientPrivate(u.lIP, u.interfaceName, timeout)
|
// LAN private IPs. Replace with a check against the active route table or
|
||||||
if err != nil {
|
// the set of routed prefixes from the network map.
|
||||||
return nil, 0, fmt.Errorf("error while creating private client: %s", err)
|
needsPrivate := u.lNet.Contains(upstreamIP) || upstreamIP.IsPrivate() ||
|
||||||
|
(u.lNetV6.IsValid() && u.lNetV6.Contains(upstreamIP))
|
||||||
|
if needsPrivate {
|
||||||
|
var bindIP netip.Addr
|
||||||
|
switch {
|
||||||
|
case upstreamIP.Is6() && u.lIPv6.IsValid():
|
||||||
|
bindIP = u.lIPv6
|
||||||
|
case upstreamIP.Is4() && u.lIP.IsValid():
|
||||||
|
bindIP = u.lIP
|
||||||
|
}
|
||||||
|
|
||||||
|
if bindIP.IsValid() {
|
||||||
|
log.Debugf("using private client to query upstream: %s", upstream)
|
||||||
|
client, err = GetClientPrivate(bindIP, u.interfaceName, timeout)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, fmt.Errorf("create private client: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,16 +106,18 @@ func GetClientPrivate(ip netip.Addr, interfaceName string, dialTimeout time.Dura
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proto, opt := unix.IPPROTO_IP, unix.IP_BOUND_IF
|
||||||
|
if ip.Is6() {
|
||||||
|
proto, opt = unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF
|
||||||
|
}
|
||||||
|
|
||||||
dialer := &net.Dialer{
|
dialer := &net.Dialer{
|
||||||
LocalAddr: &net.UDPAddr{
|
LocalAddr: net.UDPAddrFromAddrPort(netip.AddrPortFrom(ip, 0)),
|
||||||
IP: ip.AsSlice(),
|
|
||||||
Port: 0, // Let the OS pick a free port
|
|
||||||
},
|
|
||||||
Timeout: dialTimeout,
|
Timeout: dialTimeout,
|
||||||
Control: func(network, address string, c syscall.RawConn) error {
|
Control: func(network, address string, c syscall.RawConn) error {
|
||||||
var operr error
|
var operr error
|
||||||
fn := func(s uintptr) {
|
fn := func(s uintptr) {
|
||||||
operr = unix.SetsockoptInt(int(s), unix.IPPROTO_IP, unix.IP_BOUND_IF, index)
|
operr = unix.SetsockoptInt(int(s), proto, opt, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.Control(fn); err != nil {
|
if err := c.Control(fn); err != nil {
|
||||||
|
|||||||
138
client/internal/dns_test.go
Normal file
138
client/internal/dns_test.go
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/netip"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCreatePTRRecord_IPv4(t *testing.T) {
|
||||||
|
record := nbdns.SimpleRecord{
|
||||||
|
Name: "peer1.netbird.cloud.",
|
||||||
|
Type: int(dns.TypeA),
|
||||||
|
Class: nbdns.DefaultClass,
|
||||||
|
TTL: 300,
|
||||||
|
RData: "100.64.0.5",
|
||||||
|
}
|
||||||
|
prefix := netip.MustParsePrefix("100.64.0.0/16")
|
||||||
|
|
||||||
|
ptr, ok := createPTRRecord(record, prefix)
|
||||||
|
require.True(t, ok)
|
||||||
|
assert.Equal(t, "5.0.64.100.in-addr.arpa.", ptr.Name)
|
||||||
|
assert.Equal(t, int(dns.TypePTR), ptr.Type)
|
||||||
|
assert.Equal(t, "peer1.netbird.cloud.", ptr.RData)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreatePTRRecord_IPv6(t *testing.T) {
|
||||||
|
record := nbdns.SimpleRecord{
|
||||||
|
Name: "peer1.netbird.cloud.",
|
||||||
|
Type: int(dns.TypeAAAA),
|
||||||
|
Class: nbdns.DefaultClass,
|
||||||
|
TTL: 300,
|
||||||
|
RData: "fd00:1234:5678::1",
|
||||||
|
}
|
||||||
|
prefix := netip.MustParsePrefix("fd00:1234:5678::/48")
|
||||||
|
|
||||||
|
ptr, ok := createPTRRecord(record, prefix)
|
||||||
|
require.True(t, ok)
|
||||||
|
assert.Equal(t, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.7.6.5.4.3.2.1.0.0.d.f.ip6.arpa.", ptr.Name)
|
||||||
|
assert.Equal(t, int(dns.TypePTR), ptr.Type)
|
||||||
|
assert.Equal(t, "peer1.netbird.cloud.", ptr.RData)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreatePTRRecord_OutOfRange(t *testing.T) {
|
||||||
|
record := nbdns.SimpleRecord{
|
||||||
|
Name: "peer1.netbird.cloud.",
|
||||||
|
Type: int(dns.TypeA),
|
||||||
|
RData: "10.0.0.1",
|
||||||
|
}
|
||||||
|
prefix := netip.MustParsePrefix("100.64.0.0/16")
|
||||||
|
|
||||||
|
_, ok := createPTRRecord(record, prefix)
|
||||||
|
assert.False(t, ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenerateReverseZoneName_IPv4(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
prefix string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"100.64.0.0/16", "64.100.in-addr.arpa."},
|
||||||
|
{"10.0.0.0/8", "10.in-addr.arpa."},
|
||||||
|
{"192.168.1.0/24", "1.168.192.in-addr.arpa."},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.prefix, func(t *testing.T) {
|
||||||
|
zone, err := generateReverseZoneName(netip.MustParsePrefix(tt.prefix))
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.expected, zone)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenerateReverseZoneName_IPv6(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
prefix string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"fd00:1234:5678::/48", "8.7.6.5.4.3.2.1.0.0.d.f.ip6.arpa."},
|
||||||
|
{"fd00::/16", "0.0.d.f.ip6.arpa."},
|
||||||
|
{"fd12:3456:789a:bcde::/64", "e.d.c.b.a.9.8.7.6.5.4.3.2.1.d.f.ip6.arpa."},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.prefix, func(t *testing.T) {
|
||||||
|
zone, err := generateReverseZoneName(netip.MustParsePrefix(tt.prefix))
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.expected, zone)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCollectPTRRecords_BothFamilies(t *testing.T) {
|
||||||
|
config := &nbdns.Config{
|
||||||
|
CustomZones: []nbdns.CustomZone{
|
||||||
|
{
|
||||||
|
Domain: "netbird.cloud.",
|
||||||
|
Records: []nbdns.SimpleRecord{
|
||||||
|
{Name: "peer1.netbird.cloud.", Type: int(dns.TypeA), RData: "100.64.0.1"},
|
||||||
|
{Name: "peer1.netbird.cloud.", Type: int(dns.TypeAAAA), RData: "fd00::1"},
|
||||||
|
{Name: "peer2.netbird.cloud.", Type: int(dns.TypeA), RData: "100.64.0.2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
v4Records := collectPTRRecords(config, netip.MustParsePrefix("100.64.0.0/16"))
|
||||||
|
assert.Len(t, v4Records, 2, "should collect 2 A record PTRs for the v4 prefix")
|
||||||
|
|
||||||
|
v6Records := collectPTRRecords(config, netip.MustParsePrefix("fd00::/64"))
|
||||||
|
assert.Len(t, v6Records, 1, "should collect 1 AAAA record PTR for the v6 prefix")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddReverseZone_IPv6(t *testing.T) {
|
||||||
|
config := &nbdns.Config{
|
||||||
|
CustomZones: []nbdns.CustomZone{
|
||||||
|
{
|
||||||
|
Domain: "netbird.cloud.",
|
||||||
|
Records: []nbdns.SimpleRecord{
|
||||||
|
{Name: "peer1.netbird.cloud.", Type: int(dns.TypeAAAA), RData: "fd00:1234:5678::1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
addReverseZone(config, netip.MustParsePrefix("fd00:1234:5678::/48"))
|
||||||
|
|
||||||
|
require.Len(t, config.CustomZones, 2)
|
||||||
|
reverseZone := config.CustomZones[1]
|
||||||
|
assert.Equal(t, "8.7.6.5.4.3.2.1.0.0.d.f.ip6.arpa.", reverseZone.Domain)
|
||||||
|
assert.Len(t, reverseZone.Records, 1)
|
||||||
|
assert.Equal(t, int(dns.TypePTR), reverseZone.Records[0].Type)
|
||||||
|
}
|
||||||
@@ -28,11 +28,10 @@ import (
|
|||||||
"github.com/netbirdio/netbird/client/firewall"
|
"github.com/netbirdio/netbird/client/firewall"
|
||||||
firewallManager "github.com/netbirdio/netbird/client/firewall/manager"
|
firewallManager "github.com/netbirdio/netbird/client/firewall/manager"
|
||||||
"github.com/netbirdio/netbird/client/iface"
|
"github.com/netbirdio/netbird/client/iface"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
|
||||||
"github.com/netbirdio/netbird/shared/netiputil"
|
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
nbnetstack "github.com/netbirdio/netbird/client/iface/netstack"
|
nbnetstack "github.com/netbirdio/netbird/client/iface/netstack"
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
"github.com/netbirdio/netbird/client/internal/acl"
|
"github.com/netbirdio/netbird/client/internal/acl"
|
||||||
"github.com/netbirdio/netbird/client/internal/debug"
|
"github.com/netbirdio/netbird/client/internal/debug"
|
||||||
"github.com/netbirdio/netbird/client/internal/dns"
|
"github.com/netbirdio/netbird/client/internal/dns"
|
||||||
@@ -63,6 +62,7 @@ import (
|
|||||||
mgm "github.com/netbirdio/netbird/shared/management/client"
|
mgm "github.com/netbirdio/netbird/shared/management/client"
|
||||||
"github.com/netbirdio/netbird/shared/management/domain"
|
"github.com/netbirdio/netbird/shared/management/domain"
|
||||||
mgmProto "github.com/netbirdio/netbird/shared/management/proto"
|
mgmProto "github.com/netbirdio/netbird/shared/management/proto"
|
||||||
|
"github.com/netbirdio/netbird/shared/netiputil"
|
||||||
auth "github.com/netbirdio/netbird/shared/relay/auth/hmac"
|
auth "github.com/netbirdio/netbird/shared/relay/auth/hmac"
|
||||||
relayClient "github.com/netbirdio/netbird/shared/relay/client"
|
relayClient "github.com/netbirdio/netbird/shared/relay/client"
|
||||||
signal "github.com/netbirdio/netbird/shared/signal/client"
|
signal "github.com/netbirdio/netbird/shared/signal/client"
|
||||||
@@ -1252,7 +1252,7 @@ func (e *Engine) updateNetworkMap(networkMap *mgmProto.NetworkMap) error {
|
|||||||
protoDNSConfig = &mgmProto.DNSConfig{}
|
protoDNSConfig = &mgmProto.DNSConfig{}
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsConfig := toDNSConfig(protoDNSConfig, e.wgInterface.Address().Network)
|
dnsConfig := toDNSConfig(protoDNSConfig, e.wgInterface.Address())
|
||||||
|
|
||||||
if err := e.dnsServer.UpdateDNSServer(serial, dnsConfig); err != nil {
|
if err := e.dnsServer.UpdateDNSServer(serial, dnsConfig); err != nil {
|
||||||
log.Errorf("failed to update dns server, err: %v", err)
|
log.Errorf("failed to update dns server, err: %v", err)
|
||||||
@@ -1407,7 +1407,9 @@ func toRouteDomains(myPubKey string, routes []*route.Route) []*dnsfwd.ForwarderE
|
|||||||
return entries
|
return entries
|
||||||
}
|
}
|
||||||
|
|
||||||
func toDNSConfig(protoDNSConfig *mgmProto.DNSConfig, network netip.Prefix) nbdns.Config {
|
func toDNSConfig(protoDNSConfig *mgmProto.DNSConfig, addr wgaddr.Address) nbdns.Config {
|
||||||
|
network := addr.Network
|
||||||
|
networkV6 := addr.IPv6Net
|
||||||
//nolint
|
//nolint
|
||||||
forwarderPort := uint16(protoDNSConfig.GetForwarderPort())
|
forwarderPort := uint16(protoDNSConfig.GetForwarderPort())
|
||||||
if forwarderPort == 0 {
|
if forwarderPort == 0 {
|
||||||
@@ -1464,6 +1466,9 @@ func toDNSConfig(protoDNSConfig *mgmProto.DNSConfig, network netip.Prefix) nbdns
|
|||||||
|
|
||||||
if len(dnsUpdate.CustomZones) > 0 {
|
if len(dnsUpdate.CustomZones) > 0 {
|
||||||
addReverseZone(&dnsUpdate, network)
|
addReverseZone(&dnsUpdate, network)
|
||||||
|
if networkV6.IsValid() {
|
||||||
|
addReverseZone(&dnsUpdate, networkV6)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dnsUpdate
|
return dnsUpdate
|
||||||
@@ -1789,7 +1794,7 @@ func (e *Engine) readInitialSettings() ([]*route.Route, *nbdns.Config, bool, err
|
|||||||
return nil, nil, false, err
|
return nil, nil, false, err
|
||||||
}
|
}
|
||||||
routes := toRoutes(netMap.GetRoutes())
|
routes := toRoutes(netMap.GetRoutes())
|
||||||
dnsCfg := toDNSConfig(netMap.GetDNSConfig(), e.wgInterface.Address().Network)
|
dnsCfg := toDNSConfig(netMap.GetDNSConfig(), e.wgInterface.Address())
|
||||||
dnsFeatureFlag := toDNSFeatureFlag(netMap)
|
dnsFeatureFlag := toDNSFeatureFlag(netMap)
|
||||||
return routes, &dnsCfg, dnsFeatureFlag, nil
|
return routes, &dnsCfg, dnsFeatureFlag, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user