netmaker/netclient/local/dns.go

150 lines
3.8 KiB
Go
Raw Normal View History

2021-06-03 12:55:39 +08:00
package local
import (
"fmt"
"net"
2021-06-03 12:55:39 +08:00
"os"
"strings"
"time"
2021-08-03 06:06:26 +08:00
2021-06-03 12:55:39 +08:00
//"github.com/davecgh/go-spew/spew"
2021-08-03 06:06:26 +08:00
"log"
"os/exec"
2021-08-31 03:58:23 +08:00
"github.com/gravitl/netmaker/logger"
2022-02-08 00:30:15 +08:00
"github.com/gravitl/netmaker/models"
2021-09-20 02:03:47 +08:00
"github.com/gravitl/netmaker/netclient/ncutils"
2021-06-03 12:55:39 +08:00
)
const DNS_UNREACHABLE_ERROR = "nameserver unreachable"
2022-02-08 00:30:15 +08:00
// SetDNSWithRetry - Attempt setting dns, if it fails return true (to reset dns)
func SetDNSWithRetry(node models.Node, address string) bool {
2022-02-06 03:26:19 +08:00
var reachable bool
2022-02-08 03:09:48 +08:00
if !hasPrereqs() {
return true
}
2022-02-06 03:26:19 +08:00
for counter := 0; !reachable && counter < 5; counter++ {
reachable = IsDNSReachable(address)
time.Sleep(time.Second << 1)
}
if !reachable {
logger.Log(0, "not setting dns (server unreachable), will try again later: "+address)
2022-02-08 00:30:15 +08:00
return true
} else if err := UpdateDNS(node.Interface, node.Network, address); err != nil {
logger.Log(0, "error applying dns"+err.Error())
2022-02-08 00:30:15 +08:00
} else if IsDNSWorking(node.Network, address) {
return true
2022-02-06 03:26:19 +08:00
}
resetDNS()
2022-02-08 00:30:15 +08:00
return false
2022-02-06 03:26:19 +08:00
}
func resetDNS() {
ncutils.RunCmd("systemctl restart systemd-resolved", true)
}
2021-10-09 03:07:12 +08:00
// SetDNS - sets the DNS of a local machine
2021-06-03 12:55:39 +08:00
func SetDNS(nameserver string) error {
2022-01-07 04:05:38 +08:00
bytes, err := os.ReadFile("/etc/resolv.conf")
2021-08-03 06:06:26 +08:00
if err != nil {
return err
}
resolvstring := string(bytes)
// //check whether s contains substring text
hasdns := strings.Contains(resolvstring, nameserver)
if hasdns {
return nil
}
resolv, err := os.OpenFile("/etc/resolv.conf", os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer resolv.Close()
_, err = resolv.WriteString("nameserver " + nameserver + "\n")
2021-06-03 12:55:39 +08:00
2021-08-03 06:06:26 +08:00
return err
2021-06-03 12:55:39 +08:00
}
2022-02-08 03:09:48 +08:00
func hasPrereqs() bool {
if !ncutils.IsLinux() {
return false
}
_, err := exec.LookPath("resolvectl")
return err == nil
}
2021-10-09 03:07:12 +08:00
// UpdateDNS - updates local DNS of client
2021-06-03 12:55:39 +08:00
func UpdateDNS(ifacename string, network string, nameserver string) error {
2022-02-08 00:30:15 +08:00
if !ncutils.IsLinux() {
return nil
}
if ifacename == "" {
return fmt.Errorf("cannot set dns: interface name is blank")
}
if network == "" {
return fmt.Errorf("cannot set dns: network name is blank")
}
if nameserver == "" {
return fmt.Errorf("cannot set dns: nameserver is blank")
}
if !IsDNSReachable(nameserver) {
return fmt.Errorf(DNS_UNREACHABLE_ERROR + " : " + nameserver + ":53")
}
2021-08-03 06:06:26 +08:00
_, err := exec.LookPath("resolvectl")
if err != nil {
log.Println(err)
log.Println("WARNING: resolvectl not present. Unable to set dns. Install resolvectl or run manually.")
} else {
2021-09-20 02:03:47 +08:00
_, err = ncutils.RunCmd("resolvectl domain "+ifacename+" ~"+network, true)
2021-08-03 06:06:26 +08:00
if err != nil {
log.Println("WARNING: Error encountered setting domain on dns. Aborted setting dns.")
} else {
2021-09-20 02:03:47 +08:00
_, err = ncutils.RunCmd("resolvectl default-route "+ifacename+" false", true)
2021-08-03 06:06:26 +08:00
if err != nil {
log.Println("WARNING: Error encountered setting default-route on dns. Aborted setting dns.")
} else {
2021-09-20 02:03:47 +08:00
_, err = ncutils.RunCmd("resolvectl dns "+ifacename+" "+nameserver, true)
2021-08-03 06:06:26 +08:00
if err != nil {
log.Println("WARNING: Error encountered running resolvectl dns " + ifacename + " " + nameserver)
}
}
}
}
return err
2021-06-03 12:55:39 +08:00
}
2022-02-07 02:28:05 +08:00
// IsDNSReachable - checks if nameserver is reachable
func IsDNSReachable(nameserver string) bool {
port := "53"
protocols := [2]string{"tcp", "udp"}
for _, proto := range protocols {
timeout := time.Second
conn, err := net.DialTimeout(proto, net.JoinHostPort(nameserver, port), timeout)
if err != nil {
return false
}
if conn != nil {
defer conn.Close()
} else {
return false
}
}
return true
}
2022-02-07 02:27:24 +08:00
2022-02-07 02:28:05 +08:00
// IsDNSWorking - checks if record is returned by correct nameserver
2022-02-07 02:27:24 +08:00
func IsDNSWorking(network string, nameserver string) bool {
var isworking bool
2022-02-08 00:30:15 +08:00
servers, err := net.LookupNS("netmaker" + "." + network)
2022-02-07 02:27:24 +08:00
if err != nil {
return isworking
}
for _, ns := range servers {
if strings.Contains(ns.Host, nameserver) {
isworking = true
}
}
return isworking
}