dns.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. package local
  2. import (
  3. "fmt"
  4. "net"
  5. "os"
  6. "strings"
  7. "time"
  8. //"github.com/davecgh/go-spew/spew"
  9. "log"
  10. "os/exec"
  11. "github.com/gravitl/netmaker/logger"
  12. "github.com/gravitl/netmaker/models"
  13. "github.com/gravitl/netmaker/netclient/ncutils"
  14. )
  15. const DNS_UNREACHABLE_ERROR = "nameserver unreachable"
  16. // SetDNSWithRetry - Attempt setting dns, if it fails return true (to reset dns)
  17. func SetDNSWithRetry(node models.Node, address string) bool {
  18. var reachable bool
  19. if !hasPrereqs() {
  20. return true
  21. }
  22. for counter := 0; !reachable && counter < 5; counter++ {
  23. reachable = IsDNSReachable(address)
  24. time.Sleep(time.Second << 1)
  25. }
  26. if !reachable {
  27. logger.Log(0, "not setting dns (server unreachable), will try again later: "+address)
  28. return true
  29. } else if err := UpdateDNS(node.Interface, node.Network, address); err != nil {
  30. logger.Log(0, "error applying dns"+err.Error())
  31. } else if IsDNSWorking(node.Network, address) {
  32. return true
  33. }
  34. resetDNS()
  35. return false
  36. }
  37. func resetDNS() {
  38. ncutils.RunCmd("systemctl restart systemd-resolved", true)
  39. }
  40. // SetDNS - sets the DNS of a local machine
  41. func SetDNS(nameserver string) error {
  42. bytes, err := os.ReadFile("/etc/resolv.conf")
  43. if err != nil {
  44. return err
  45. }
  46. resolvstring := string(bytes)
  47. // //check whether s contains substring text
  48. hasdns := strings.Contains(resolvstring, nameserver)
  49. if hasdns {
  50. return nil
  51. }
  52. resolv, err := os.OpenFile("/etc/resolv.conf", os.O_APPEND|os.O_WRONLY, 0644)
  53. if err != nil {
  54. return err
  55. }
  56. defer resolv.Close()
  57. _, err = resolv.WriteString("nameserver " + nameserver + "\n")
  58. return err
  59. }
  60. func hasPrereqs() bool {
  61. if !ncutils.IsLinux() {
  62. return false
  63. }
  64. _, err := exec.LookPath("resolvectl")
  65. return err == nil
  66. }
  67. // UpdateDNS - updates local DNS of client
  68. func UpdateDNS(ifacename string, network string, nameserver string) error {
  69. if !ncutils.IsLinux() {
  70. return nil
  71. }
  72. if ifacename == "" {
  73. return fmt.Errorf("cannot set dns: interface name is blank")
  74. }
  75. if network == "" {
  76. return fmt.Errorf("cannot set dns: network name is blank")
  77. }
  78. if nameserver == "" {
  79. return fmt.Errorf("cannot set dns: nameserver is blank")
  80. }
  81. if !IsDNSReachable(nameserver) {
  82. return fmt.Errorf(DNS_UNREACHABLE_ERROR + " : " + nameserver + ":53")
  83. }
  84. _, err := exec.LookPath("resolvectl")
  85. if err != nil {
  86. log.Println(err)
  87. log.Println("WARNING: resolvectl not present. Unable to set dns. Install resolvectl or run manually.")
  88. } else {
  89. _, err = ncutils.RunCmd("resolvectl domain "+ifacename+" ~"+network, true)
  90. if err != nil {
  91. log.Println("WARNING: Error encountered setting domain on dns. Aborted setting dns.")
  92. } else {
  93. _, err = ncutils.RunCmd("resolvectl default-route "+ifacename+" false", true)
  94. if err != nil {
  95. log.Println("WARNING: Error encountered setting default-route on dns. Aborted setting dns.")
  96. } else {
  97. _, err = ncutils.RunCmd("resolvectl dns "+ifacename+" "+nameserver, true)
  98. if err != nil {
  99. log.Println("WARNING: Error encountered running resolvectl dns " + ifacename + " " + nameserver)
  100. }
  101. }
  102. }
  103. }
  104. return err
  105. }
  106. // IsDNSReachable - checks if nameserver is reachable
  107. func IsDNSReachable(nameserver string) bool {
  108. port := "53"
  109. protocols := [2]string{"tcp", "udp"}
  110. for _, proto := range protocols {
  111. timeout := time.Second
  112. conn, err := net.DialTimeout(proto, net.JoinHostPort(nameserver, port), timeout)
  113. if err != nil {
  114. return false
  115. }
  116. if conn != nil {
  117. defer conn.Close()
  118. } else {
  119. return false
  120. }
  121. }
  122. return true
  123. }
  124. // IsDNSWorking - checks if record is returned by correct nameserver
  125. func IsDNSWorking(network string, nameserver string) bool {
  126. var isworking bool
  127. servers, err := net.LookupNS("netmaker" + "." + network)
  128. if err != nil {
  129. return isworking
  130. }
  131. for _, ns := range servers {
  132. if strings.Contains(ns.Host, nameserver) {
  133. isworking = true
  134. }
  135. }
  136. return isworking
  137. }