dns.go 3.6 KB

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