2022-11-03 18:39:37 +01:00
package dns
import (
"context"
"fmt"
"net"
"net/netip"
2023-06-22 14:59:21 +02:00
"os"
2023-02-13 15:25:11 +01:00
"strings"
2022-11-03 18:39:37 +01:00
"testing"
"time"
2023-02-13 15:25:11 +01:00
2023-06-22 14:59:21 +02:00
"github.com/golang/mock/gomock"
2023-07-14 21:56:22 +02:00
log "github.com/sirupsen/logrus"
2023-04-13 17:00:01 +02:00
2023-07-14 21:56:22 +02:00
"github.com/netbirdio/netbird/client/firewall/uspfilter"
2023-06-08 11:46:57 +02:00
"github.com/netbirdio/netbird/client/internal/stdnet"
2023-02-13 15:25:11 +01:00
nbdns "github.com/netbirdio/netbird/dns"
2023-07-14 21:56:22 +02:00
"github.com/netbirdio/netbird/formatter"
2023-02-13 15:25:11 +01:00
"github.com/netbirdio/netbird/iface"
2023-06-22 14:59:21 +02:00
pfmock "github.com/netbirdio/netbird/iface/mocks"
2022-11-03 18:39:37 +01:00
)
2023-07-14 21:56:22 +02:00
type mocWGIface struct {
filter iface . PacketFilter
}
func ( w * mocWGIface ) Name ( ) string {
panic ( "implement me" )
}
func ( w * mocWGIface ) Address ( ) iface . WGAddress {
ip , network , _ := net . ParseCIDR ( "100.66.100.0/24" )
return iface . WGAddress {
IP : ip ,
Network : network ,
}
}
func ( w * mocWGIface ) GetFilter ( ) iface . PacketFilter {
return w . filter
}
func ( w * mocWGIface ) GetDevice ( ) * iface . DeviceWrapper {
panic ( "implement me" )
}
func ( w * mocWGIface ) GetInterfaceGUIDString ( ) ( string , error ) {
panic ( "implement me" )
}
func ( w * mocWGIface ) IsUserspaceBind ( ) bool {
return false
}
func ( w * mocWGIface ) SetFilter ( filter iface . PacketFilter ) error {
w . filter = filter
return nil
}
2022-11-03 18:39:37 +01:00
var zoneRecords = [ ] nbdns . SimpleRecord {
{
Name : "peera.netbird.cloud" ,
Type : 1 ,
Class : nbdns . DefaultClass ,
TTL : 300 ,
RData : "1.2.3.4" ,
} ,
}
2023-07-14 21:56:22 +02:00
func init ( ) {
log . SetLevel ( log . TraceLevel )
formatter . SetTextFormatter ( log . StandardLogger ( ) )
}
2022-11-03 18:39:37 +01:00
func TestUpdateDNSServer ( t * testing . T ) {
nameServers := [ ] nbdns . NameServer {
{
IP : netip . MustParseAddr ( "8.8.8.8" ) ,
NSType : nbdns . UDPNameServerType ,
Port : 53 ,
} ,
{
IP : netip . MustParseAddr ( "8.8.4.4" ) ,
NSType : nbdns . UDPNameServerType ,
Port : 53 ,
} ,
}
2023-05-26 17:13:59 +02:00
dummyHandler := & localResolver { }
2022-11-03 18:39:37 +01:00
testCases := [ ] struct {
name string
2023-05-26 17:13:59 +02:00
initUpstreamMap registeredHandlerMap
2022-11-03 18:39:37 +01:00
initLocalMap registrationMap
initSerial uint64
inputSerial uint64
2022-11-07 15:38:21 +01:00
inputUpdate nbdns . Config
2022-11-03 18:39:37 +01:00
shouldFail bool
2023-05-26 17:13:59 +02:00
expectedUpstreamMap registeredHandlerMap
2022-11-03 18:39:37 +01:00
expectedLocalMap registrationMap
} {
{
2022-11-07 15:38:21 +01:00
name : "Initial Config Should Succeed" ,
2022-11-03 18:39:37 +01:00
initLocalMap : make ( registrationMap ) ,
2023-05-26 17:13:59 +02:00
initUpstreamMap : make ( registeredHandlerMap ) ,
2022-11-03 18:39:37 +01:00
initSerial : 0 ,
inputSerial : 1 ,
2022-11-07 15:38:21 +01:00
inputUpdate : nbdns . Config {
2022-11-03 18:39:37 +01:00
ServiceEnable : true ,
CustomZones : [ ] nbdns . CustomZone {
{
Domain : "netbird.cloud" ,
Records : zoneRecords ,
} ,
} ,
2022-11-07 15:38:21 +01:00
NameServerGroups : [ ] * nbdns . NameServerGroup {
2022-11-03 18:39:37 +01:00
{
Domains : [ ] string { "netbird.io" } ,
NameServers : nameServers ,
} ,
{
NameServers : nameServers ,
Primary : true ,
} ,
} ,
} ,
2023-05-26 17:13:59 +02:00
expectedUpstreamMap : registeredHandlerMap { "netbird.io" : dummyHandler , "netbird.cloud" : dummyHandler , nbdns . RootZone : dummyHandler } ,
2022-11-23 13:39:42 +01:00
expectedLocalMap : registrationMap { buildRecordKey ( zoneRecords [ 0 ] . Name , 1 , 1 ) : struct { } { } } ,
2022-11-03 18:39:37 +01:00
} ,
{
2022-11-07 15:38:21 +01:00
name : "New Config Should Succeed" ,
2022-11-03 18:39:37 +01:00
initLocalMap : registrationMap { "netbird.cloud" : struct { } { } } ,
2023-05-26 17:13:59 +02:00
initUpstreamMap : registeredHandlerMap { buildRecordKey ( zoneRecords [ 0 ] . Name , 1 , 1 ) : dummyHandler } ,
2022-11-03 18:39:37 +01:00
initSerial : 0 ,
inputSerial : 1 ,
2022-11-07 15:38:21 +01:00
inputUpdate : nbdns . Config {
2022-11-03 18:39:37 +01:00
ServiceEnable : true ,
CustomZones : [ ] nbdns . CustomZone {
{
Domain : "netbird.cloud" ,
Records : zoneRecords ,
} ,
} ,
2022-11-07 15:38:21 +01:00
NameServerGroups : [ ] * nbdns . NameServerGroup {
2022-11-03 18:39:37 +01:00
{
Domains : [ ] string { "netbird.io" } ,
NameServers : nameServers ,
} ,
} ,
} ,
2023-05-26 17:13:59 +02:00
expectedUpstreamMap : registeredHandlerMap { "netbird.io" : dummyHandler , "netbird.cloud" : dummyHandler } ,
2022-11-23 13:39:42 +01:00
expectedLocalMap : registrationMap { buildRecordKey ( zoneRecords [ 0 ] . Name , 1 , 1 ) : struct { } { } } ,
2022-11-03 18:39:37 +01:00
} ,
{
2022-11-07 15:38:21 +01:00
name : "Smaller Config Serial Should Be Skipped" ,
2022-11-03 18:39:37 +01:00
initLocalMap : make ( registrationMap ) ,
2023-05-26 17:13:59 +02:00
initUpstreamMap : make ( registeredHandlerMap ) ,
2022-11-03 18:39:37 +01:00
initSerial : 2 ,
inputSerial : 1 ,
shouldFail : true ,
} ,
{
name : "Empty NS Group Domain Or Not Primary Element Should Fail" ,
initLocalMap : make ( registrationMap ) ,
2023-05-26 17:13:59 +02:00
initUpstreamMap : make ( registeredHandlerMap ) ,
2022-11-03 18:39:37 +01:00
initSerial : 0 ,
inputSerial : 1 ,
2022-11-07 15:38:21 +01:00
inputUpdate : nbdns . Config {
2022-11-03 18:39:37 +01:00
ServiceEnable : true ,
CustomZones : [ ] nbdns . CustomZone {
{
Domain : "netbird.cloud" ,
Records : zoneRecords ,
} ,
} ,
2022-11-07 15:38:21 +01:00
NameServerGroups : [ ] * nbdns . NameServerGroup {
2022-11-03 18:39:37 +01:00
{
NameServers : nameServers ,
} ,
} ,
} ,
shouldFail : true ,
} ,
{
name : "Invalid NS Group Nameservers list Should Fail" ,
initLocalMap : make ( registrationMap ) ,
2023-05-26 17:13:59 +02:00
initUpstreamMap : make ( registeredHandlerMap ) ,
2022-11-03 18:39:37 +01:00
initSerial : 0 ,
inputSerial : 1 ,
2022-11-07 15:38:21 +01:00
inputUpdate : nbdns . Config {
2022-11-03 18:39:37 +01:00
ServiceEnable : true ,
CustomZones : [ ] nbdns . CustomZone {
{
Domain : "netbird.cloud" ,
Records : zoneRecords ,
} ,
} ,
2022-11-07 15:38:21 +01:00
NameServerGroups : [ ] * nbdns . NameServerGroup {
2022-11-03 18:39:37 +01:00
{
NameServers : nameServers ,
} ,
} ,
} ,
shouldFail : true ,
} ,
{
name : "Invalid Custom Zone Records list Should Fail" ,
initLocalMap : make ( registrationMap ) ,
2023-05-26 17:13:59 +02:00
initUpstreamMap : make ( registeredHandlerMap ) ,
2022-11-03 18:39:37 +01:00
initSerial : 0 ,
inputSerial : 1 ,
2022-11-07 15:38:21 +01:00
inputUpdate : nbdns . Config {
2022-11-03 18:39:37 +01:00
ServiceEnable : true ,
CustomZones : [ ] nbdns . CustomZone {
{
Domain : "netbird.cloud" ,
} ,
} ,
2022-11-07 15:38:21 +01:00
NameServerGroups : [ ] * nbdns . NameServerGroup {
2022-11-03 18:39:37 +01:00
{
NameServers : nameServers ,
Primary : true ,
} ,
} ,
} ,
shouldFail : true ,
} ,
{
2022-11-07 15:38:21 +01:00
name : "Empty Config Should Succeed and Clean Maps" ,
2022-11-03 18:39:37 +01:00
initLocalMap : registrationMap { "netbird.cloud" : struct { } { } } ,
2023-05-26 17:13:59 +02:00
initUpstreamMap : registeredHandlerMap { zoneRecords [ 0 ] . Name : dummyHandler } ,
2022-11-03 18:39:37 +01:00
initSerial : 0 ,
inputSerial : 1 ,
2022-11-07 15:38:21 +01:00
inputUpdate : nbdns . Config { ServiceEnable : true } ,
2023-05-26 17:13:59 +02:00
expectedUpstreamMap : make ( registeredHandlerMap ) ,
2022-11-03 18:39:37 +01:00
expectedLocalMap : make ( registrationMap ) ,
} ,
2022-12-13 12:26:48 +01:00
{
name : "Disabled Service Should clean map" ,
initLocalMap : registrationMap { "netbird.cloud" : struct { } { } } ,
2023-05-26 17:13:59 +02:00
initUpstreamMap : registeredHandlerMap { zoneRecords [ 0 ] . Name : dummyHandler } ,
2022-12-13 12:26:48 +01:00
initSerial : 0 ,
inputSerial : 1 ,
inputUpdate : nbdns . Config { ServiceEnable : false } ,
2023-05-26 17:13:59 +02:00
expectedUpstreamMap : make ( registeredHandlerMap ) ,
2022-12-13 12:26:48 +01:00
expectedLocalMap : make ( registrationMap ) ,
} ,
2022-11-03 18:39:37 +01:00
}
2022-12-13 12:26:48 +01:00
for n , testCase := range testCases {
2022-11-03 18:39:37 +01:00
t . Run ( testCase . name , func ( t * testing . T ) {
2023-04-13 17:00:01 +02:00
newNet , err := stdnet . NewNet ( nil )
if err != nil {
t . Fatal ( err )
}
2023-05-31 18:25:24 +02:00
wgIface , err := iface . NewWGIFace ( fmt . Sprintf ( "utun230%d" , n ) , fmt . Sprintf ( "100.66.100.%d/32" , n + 1 ) , iface . DefaultMTU , nil , newNet )
2022-12-13 12:26:48 +01:00
if err != nil {
t . Fatal ( err )
}
err = wgIface . Create ( )
if err != nil {
t . Fatal ( err )
}
defer func ( ) {
err = wgIface . Close ( )
if err != nil {
t . Log ( err )
}
} ( )
2023-07-14 21:56:22 +02:00
dnsServer , err := NewDefaultServer ( context . Background ( ) , wgIface , "" )
2022-12-13 12:26:48 +01:00
if err != nil {
t . Fatal ( err )
}
2023-06-15 12:25:18 +02:00
err = dnsServer . Initialize ( )
if err != nil {
t . Fatal ( err )
}
2022-12-13 12:26:48 +01:00
defer func ( ) {
err = dnsServer . hostManager . restoreHostDNS ( )
if err != nil {
t . Log ( err )
}
} ( )
2022-11-03 18:39:37 +01:00
dnsServer . dnsMuxMap = testCase . initUpstreamMap
dnsServer . localResolver . registeredMap = testCase . initLocalMap
dnsServer . updateSerial = testCase . initSerial
2022-12-13 12:26:48 +01:00
err = dnsServer . UpdateDNSServer ( testCase . inputSerial , testCase . inputUpdate )
2022-11-03 18:39:37 +01:00
if err != nil {
if testCase . shouldFail {
return
}
t . Fatalf ( "update dns server should not fail, got error: %v" , err )
}
if len ( dnsServer . dnsMuxMap ) != len ( testCase . expectedUpstreamMap ) {
t . Fatalf ( "update upstream failed, map size is different than expected, want %d, got %d" , len ( testCase . expectedUpstreamMap ) , len ( dnsServer . dnsMuxMap ) )
}
for key := range testCase . expectedUpstreamMap {
_ , found := dnsServer . dnsMuxMap [ key ]
if ! found {
t . Fatalf ( "update upstream failed, key %s was not found in the dnsMuxMap: %#v" , key , dnsServer . dnsMuxMap )
}
}
if len ( dnsServer . localResolver . registeredMap ) != len ( testCase . expectedLocalMap ) {
t . Fatalf ( "update local failed, registered map size is different than expected, want %d, got %d" , len ( testCase . expectedLocalMap ) , len ( dnsServer . localResolver . registeredMap ) )
}
for key := range testCase . expectedLocalMap {
_ , found := dnsServer . localResolver . registeredMap [ key ]
if ! found {
t . Fatalf ( "update local failed, key %s was not found in the localResolver.registeredMap: %#v" , key , dnsServer . localResolver . registeredMap )
}
}
} )
}
}
2023-06-22 14:59:21 +02:00
func TestDNSFakeResolverHandleUpdates ( t * testing . T ) {
ov := os . Getenv ( "NB_WG_KERNEL_DISABLED" )
defer os . Setenv ( "NB_WG_KERNEL_DISABLED" , ov )
2023-07-14 21:56:22 +02:00
_ = os . Setenv ( "NB_WG_KERNEL_DISABLED" , "true" )
2023-06-22 14:59:21 +02:00
newNet , err := stdnet . NewNet ( nil )
if err != nil {
t . Errorf ( "create stdnet: %v" , err )
return
}
wgIface , err := iface . NewWGIFace ( "utun2301" , "100.66.100.1/32" , iface . DefaultMTU , nil , newNet )
if err != nil {
t . Errorf ( "build interface wireguard: %v" , err )
return
}
err = wgIface . Create ( )
if err != nil {
t . Errorf ( "crate and init wireguard interface: %v" , err )
return
}
defer func ( ) {
if err = wgIface . Close ( ) ; err != nil {
t . Logf ( "close wireguard interface: %v" , err )
}
} ( )
ctrl := gomock . NewController ( t )
defer ctrl . Finish ( )
_ , ipNet , err := net . ParseCIDR ( "100.66.100.1/32" )
if err != nil {
t . Errorf ( "parse CIDR: %v" , err )
return
}
packetfilter := pfmock . NewMockPacketFilter ( ctrl )
packetfilter . EXPECT ( ) . DropOutgoing ( gomock . Any ( ) ) . AnyTimes ( )
2023-07-14 21:56:22 +02:00
packetfilter . EXPECT ( ) . AddUDPPacketHook ( gomock . Any ( ) , gomock . Any ( ) , gomock . Any ( ) , gomock . Any ( ) )
packetfilter . EXPECT ( ) . RemovePacketHook ( gomock . Any ( ) )
packetfilter . EXPECT ( ) . SetNetwork ( ipNet )
2023-06-22 14:59:21 +02:00
if err := wgIface . SetFilter ( packetfilter ) ; err != nil {
t . Errorf ( "set packet filter: %v" , err )
return
}
2023-07-14 21:56:22 +02:00
dnsServer , err := NewDefaultServer ( context . Background ( ) , wgIface , "" )
2023-06-22 14:59:21 +02:00
if err != nil {
t . Errorf ( "create DNS server: %v" , err )
return
}
err = dnsServer . Initialize ( )
if err != nil {
t . Errorf ( "run DNS server: %v" , err )
return
}
defer func ( ) {
if err = dnsServer . hostManager . restoreHostDNS ( ) ; err != nil {
t . Logf ( "restore DNS settings on the host: %v" , err )
return
}
} ( )
dnsServer . dnsMuxMap = registeredHandlerMap { zoneRecords [ 0 ] . Name : & localResolver { } }
dnsServer . localResolver . registeredMap = registrationMap { "netbird.cloud" : struct { } { } }
dnsServer . updateSerial = 0
nameServers := [ ] nbdns . NameServer {
{
IP : netip . MustParseAddr ( "8.8.8.8" ) ,
NSType : nbdns . UDPNameServerType ,
Port : 53 ,
} ,
{
IP : netip . MustParseAddr ( "8.8.4.4" ) ,
NSType : nbdns . UDPNameServerType ,
Port : 53 ,
} ,
}
update := nbdns . Config {
ServiceEnable : true ,
CustomZones : [ ] nbdns . CustomZone {
{
Domain : "netbird.cloud" ,
Records : zoneRecords ,
} ,
} ,
NameServerGroups : [ ] * nbdns . NameServerGroup {
{
Domains : [ ] string { "netbird.io" } ,
NameServers : nameServers ,
} ,
{
NameServers : nameServers ,
Primary : true ,
} ,
} ,
}
// Start the server with regular configuration
if err := dnsServer . UpdateDNSServer ( 1 , update ) ; err != nil {
t . Fatalf ( "update dns server should not fail, got error: %v" , err )
return
}
update2 := update
update2 . ServiceEnable = false
// Disable the server, stop the listener
if err := dnsServer . UpdateDNSServer ( 2 , update2 ) ; err != nil {
t . Fatalf ( "update dns server should not fail, got error: %v" , err )
return
}
update3 := update2
update3 . NameServerGroups = update3 . NameServerGroups [ : 1 ]
// But service still get updates and we checking that we handle
// internal state in the right way
if err := dnsServer . UpdateDNSServer ( 3 , update3 ) ; err != nil {
t . Fatalf ( "update dns server should not fail, got error: %v" , err )
return
}
}
2022-11-03 18:39:37 +01:00
func TestDNSServerStartStop ( t * testing . T ) {
2023-01-17 19:16:50 +01:00
testCases := [ ] struct {
name string
addrPort string
} {
{
name : "Should Pass With Port Discovery" ,
} ,
{
name : "Should Pass With Custom Port" ,
addrPort : "127.0.0.1:3535" ,
} ,
2022-11-03 18:39:37 +01:00
}
2023-01-17 19:16:50 +01:00
for _ , testCase := range testCases {
t . Run ( testCase . name , func ( t * testing . T ) {
2023-07-14 21:56:22 +02:00
dnsServer , err := NewDefaultServer ( context . Background ( ) , & mocWGIface { } , testCase . addrPort )
if err != nil {
t . Fatalf ( "%v" , err )
}
2023-01-17 19:16:50 +01:00
dnsServer . hostManager = newNoopHostMocker ( )
2023-07-14 21:56:22 +02:00
err = dnsServer . service . Listen ( )
if err != nil {
t . Fatalf ( "dns server is not running: %s" , err )
2022-11-03 18:39:37 +01:00
}
2023-07-14 21:56:22 +02:00
time . Sleep ( 100 * time . Millisecond )
2023-01-17 19:16:50 +01:00
defer dnsServer . Stop ( )
2023-07-14 21:56:22 +02:00
err = dnsServer . localResolver . registerRecord ( zoneRecords [ 0 ] )
2022-11-03 18:39:37 +01:00
if err != nil {
2023-01-17 19:16:50 +01:00
t . Error ( err )
2022-11-03 18:39:37 +01:00
}
2023-07-14 21:56:22 +02:00
dnsServer . service . RegisterMux ( "netbird.cloud" , dnsServer . localResolver )
2022-11-03 18:39:37 +01:00
2023-01-17 19:16:50 +01:00
resolver := & net . Resolver {
PreferGo : true ,
Dial : func ( ctx context . Context , network , address string ) ( net . Conn , error ) {
d := net . Dialer {
Timeout : time . Second * 5 ,
}
2023-07-14 21:56:22 +02:00
addr := fmt . Sprintf ( "%s:%d" , dnsServer . service . RuntimeIP ( ) , dnsServer . service . RuntimePort ( ) )
2023-01-17 19:16:50 +01:00
conn , err := d . DialContext ( ctx , network , addr )
if err != nil {
t . Log ( err )
// retry test before exit, for slower systems
return d . DialContext ( ctx , network , addr )
}
2022-11-03 18:39:37 +01:00
2023-01-17 19:16:50 +01:00
return conn , nil
} ,
}
2022-11-03 18:39:37 +01:00
2023-01-17 19:16:50 +01:00
ips , err := resolver . LookupHost ( context . Background ( ) , zoneRecords [ 0 ] . Name )
if err != nil {
t . Fatalf ( "failed to connect to the server, error: %v" , err )
}
2022-11-03 18:39:37 +01:00
2023-01-17 19:16:50 +01:00
if ips [ 0 ] != zoneRecords [ 0 ] . RData {
t . Fatalf ( "got a different IP from the server: want %s, got %s" , zoneRecords [ 0 ] . RData , ips [ 0 ] )
}
dnsServer . Stop ( )
ctx , cancel := context . WithTimeout ( context . TODO ( ) , time . Second * 1 )
defer cancel ( )
_ , err = resolver . LookupHost ( ctx , zoneRecords [ 0 ] . Name )
if err == nil {
t . Fatalf ( "we should encounter an error when querying a stopped server" )
}
} )
2022-11-03 18:39:37 +01:00
}
}
2022-11-23 13:39:42 +01:00
2023-02-13 15:25:11 +01:00
func TestDNSServerUpstreamDeactivateCallback ( t * testing . T ) {
hostManager := & mockHostConfigurator { }
server := DefaultServer {
2023-07-14 21:56:22 +02:00
service : newServiceViaMemory ( & mocWGIface { } ) ,
2023-02-13 15:25:11 +01:00
localResolver : & localResolver {
registeredMap : make ( registrationMap ) ,
} ,
hostManager : hostManager ,
currentConfig : hostDNSConfig {
domains : [ ] domainConfig {
{ false , "domain0" , false } ,
{ false , "domain1" , false } ,
{ false , "domain2" , false } ,
} ,
} ,
}
var domainsUpdate string
hostManager . applyDNSConfigFunc = func ( config hostDNSConfig ) error {
domains := [ ] string { }
for _ , item := range config . domains {
if item . disabled {
continue
}
domains = append ( domains , item . domain )
}
domainsUpdate = strings . Join ( domains , "," )
return nil
}
deactivate , reactivate := server . upstreamCallbacks ( & nbdns . NameServerGroup {
Domains : [ ] string { "domain1" } ,
NameServers : [ ] nbdns . NameServer {
{ IP : netip . MustParseAddr ( "8.8.0.0" ) , NSType : nbdns . UDPNameServerType , Port : 53 } ,
} ,
} , nil )
deactivate ( )
expected := "domain0,domain2"
domains := [ ] string { }
for _ , item := range server . currentConfig . domains {
if item . disabled {
continue
}
domains = append ( domains , item . domain )
}
got := strings . Join ( domains , "," )
if expected != got {
t . Errorf ( "expected domains list: %q, got %q" , expected , got )
}
reactivate ( )
expected = "domain0,domain1,domain2"
domains = [ ] string { }
for _ , item := range server . currentConfig . domains {
if item . disabled {
continue
}
domains = append ( domains , item . domain )
}
got = strings . Join ( domains , "," )
if expected != got {
t . Errorf ( "expected domains list: %q, got %q" , expected , domainsUpdate )
}
}
2023-07-14 21:56:22 +02:00
func TestDNSPermanent_updateHostDNS_emptyUpstream ( t * testing . T ) {
wgIFace , err := createWgInterfaceWithBind ( t )
if err != nil {
t . Fatal ( "failed to initialize wg interface" )
}
defer wgIFace . Close ( )
2023-01-17 19:16:50 +01:00
2023-07-14 21:56:22 +02:00
var dnsList [ ] string
dnsServer := NewDefaultServerPermanentUpstream ( context . Background ( ) , wgIFace , dnsList )
err = dnsServer . Initialize ( )
if err != nil {
t . Errorf ( "failed to initialize DNS server: %v" , err )
return
2022-11-23 13:39:42 +01:00
}
2023-07-14 21:56:22 +02:00
defer dnsServer . Stop ( )
2022-11-23 13:39:42 +01:00
2023-07-14 21:56:22 +02:00
dnsServer . OnUpdatedHostDNSServer ( [ ] string { "8.8.8.8" } )
resolver := newDnsResolver ( dnsServer . service . RuntimeIP ( ) , dnsServer . service . RuntimePort ( ) )
_ , err = resolver . LookupHost ( context . Background ( ) , "netbird.io" )
if err != nil {
t . Errorf ( "failed to resolve: %s" , err )
2022-11-23 13:39:42 +01:00
}
2023-07-14 21:56:22 +02:00
}
2022-11-23 13:39:42 +01:00
2023-07-14 21:56:22 +02:00
func TestDNSPermanent_updateUpstream ( t * testing . T ) {
wgIFace , err := createWgInterfaceWithBind ( t )
if err != nil {
t . Fatal ( "failed to initialize wg interface" )
}
defer wgIFace . Close ( )
2022-11-23 13:39:42 +01:00
2023-07-14 21:56:22 +02:00
dnsServer := NewDefaultServerPermanentUpstream ( context . Background ( ) , wgIFace , [ ] string { "8.8.8.8" } )
err = dnsServer . Initialize ( )
if err != nil {
t . Errorf ( "failed to initialize DNS server: %v" , err )
return
}
defer dnsServer . Stop ( )
// check initial state
resolver := newDnsResolver ( dnsServer . service . RuntimeIP ( ) , dnsServer . service . RuntimePort ( ) )
_ , err = resolver . LookupHost ( context . Background ( ) , "netbird.io" )
if err != nil {
t . Errorf ( "failed to resolve: %s" , err )
}
update := nbdns . Config {
ServiceEnable : true ,
CustomZones : [ ] nbdns . CustomZone {
{
Domain : "netbird.cloud" ,
Records : zoneRecords ,
} ,
2022-11-23 13:39:42 +01:00
} ,
2023-07-14 21:56:22 +02:00
NameServerGroups : [ ] * nbdns . NameServerGroup {
{
NameServers : [ ] nbdns . NameServer {
{
IP : netip . MustParseAddr ( "8.8.4.4" ) ,
NSType : nbdns . UDPNameServerType ,
Port : 53 ,
} ,
} ,
Enabled : true ,
Primary : true ,
} ,
} ,
}
err = dnsServer . UpdateDNSServer ( 1 , update )
if err != nil {
t . Errorf ( "failed to update dns server: %s" , err )
}
_ , err = resolver . LookupHost ( context . Background ( ) , "netbird.io" )
if err != nil {
t . Errorf ( "failed to resolve: %s" , err )
}
ips , err := resolver . LookupHost ( context . Background ( ) , zoneRecords [ 0 ] . Name )
if err != nil {
t . Fatalf ( "failed resolve zone record: %v" , err )
}
if ips [ 0 ] != zoneRecords [ 0 ] . RData {
t . Fatalf ( "invalid zone record: %v" , err )
}
update2 := nbdns . Config {
ServiceEnable : true ,
CustomZones : [ ] nbdns . CustomZone {
{
Domain : "netbird.cloud" ,
Records : zoneRecords ,
} ,
} ,
NameServerGroups : [ ] * nbdns . NameServerGroup { } ,
}
err = dnsServer . UpdateDNSServer ( 2 , update2 )
if err != nil {
t . Errorf ( "failed to update dns server: %s" , err )
}
_ , err = resolver . LookupHost ( context . Background ( ) , "netbird.io" )
if err != nil {
t . Errorf ( "failed to resolve: %s" , err )
}
ips , err = resolver . LookupHost ( context . Background ( ) , zoneRecords [ 0 ] . Name )
if err != nil {
t . Fatalf ( "failed resolve zone record: %v" , err )
}
if ips [ 0 ] != zoneRecords [ 0 ] . RData {
t . Fatalf ( "invalid zone record: %v" , err )
2022-11-23 13:39:42 +01:00
}
2023-06-12 14:43:55 +02:00
}
2023-07-14 21:56:22 +02:00
func TestDNSPermanent_matchOnly ( t * testing . T ) {
wgIFace , err := createWgInterfaceWithBind ( t )
if err != nil {
t . Fatal ( "failed to initialize wg interface" )
2023-06-12 14:43:55 +02:00
}
2023-07-14 21:56:22 +02:00
defer wgIFace . Close ( )
2023-06-12 14:43:55 +02:00
2023-07-14 21:56:22 +02:00
dnsServer := NewDefaultServerPermanentUpstream ( context . Background ( ) , wgIFace , [ ] string { "8.8.8.8" } )
err = dnsServer . Initialize ( )
if err != nil {
t . Errorf ( "failed to initialize DNS server: %v" , err )
return
}
defer dnsServer . Stop ( )
2023-06-12 14:43:55 +02:00
2023-07-14 21:56:22 +02:00
// check initial state
resolver := newDnsResolver ( dnsServer . service . RuntimeIP ( ) , dnsServer . service . RuntimePort ( ) )
_ , err = resolver . LookupHost ( context . Background ( ) , "netbird.io" )
if err != nil {
t . Errorf ( "failed to resolve: %s" , err )
}
update := nbdns . Config {
ServiceEnable : true ,
CustomZones : [ ] nbdns . CustomZone {
{
Domain : "netbird.cloud" ,
Records : zoneRecords ,
} ,
} ,
NameServerGroups : [ ] * nbdns . NameServerGroup {
{
NameServers : [ ] nbdns . NameServer {
{
IP : netip . MustParseAddr ( "8.8.4.4" ) ,
NSType : nbdns . UDPNameServerType ,
Port : 53 ,
} ,
} ,
Domains : [ ] string { "customdomain.com" } ,
Primary : false ,
} ,
} ,
}
err = dnsServer . UpdateDNSServer ( 1 , update )
if err != nil {
t . Errorf ( "failed to update dns server: %s" , err )
}
_ , err = resolver . LookupHost ( context . Background ( ) , "netbird.io" )
if err != nil {
t . Errorf ( "failed to resolve: %s" , err )
}
ips , err := resolver . LookupHost ( context . Background ( ) , zoneRecords [ 0 ] . Name )
if err != nil {
t . Fatalf ( "failed resolve zone record: %v" , err )
}
if ips [ 0 ] != zoneRecords [ 0 ] . RData {
t . Fatalf ( "invalid zone record: %v" , err )
}
_ , err = resolver . LookupHost ( context . Background ( ) , "customdomain.com" )
if err != nil {
t . Errorf ( "failed to resolve: %s" , err )
}
}
func createWgInterfaceWithBind ( t * testing . T ) ( * iface . WGIface , error ) {
ov := os . Getenv ( "NB_WG_KERNEL_DISABLED" )
defer os . Setenv ( "NB_WG_KERNEL_DISABLED" , ov )
_ = os . Setenv ( "NB_WG_KERNEL_DISABLED" , "true" )
newNet , err := stdnet . NewNet ( nil )
if err != nil {
t . Fatalf ( "create stdnet: %v" , err )
return nil , nil
}
wgIface , err := iface . NewWGIFace ( "utun2301" , "100.66.100.2/24" , iface . DefaultMTU , nil , newNet )
if err != nil {
t . Fatalf ( "build interface wireguard: %v" , err )
return nil , err
}
err = wgIface . Create ( )
if err != nil {
t . Fatalf ( "crate and init wireguard interface: %v" , err )
return nil , err
}
pf , err := uspfilter . Create ( wgIface )
if err != nil {
t . Fatalf ( "failed to create uspfilter: %v" , err )
return nil , err
}
err = wgIface . SetFilter ( pf )
if err != nil {
t . Fatalf ( "set packet filter: %v" , err )
return nil , err
}
return wgIface , nil
}
func newDnsResolver ( ip string , port int ) * net . Resolver {
return & net . Resolver {
PreferGo : true ,
Dial : func ( ctx context . Context , network , address string ) ( net . Conn , error ) {
d := net . Dialer {
Timeout : time . Second * 3 ,
}
addr := fmt . Sprintf ( "%s:%d" , ip , port )
return d . DialContext ( ctx , network , addr )
} ,
2023-06-12 14:43:55 +02:00
}
2022-11-23 13:39:42 +01:00
}