dns.go 3.7 KB

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