verify.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package verify
  2. import (
  3. "bufio"
  4. "fmt"
  5. "net"
  6. "os"
  7. "os/exec"
  8. "strings"
  9. "networktool/internal/model"
  10. )
  11. type Service struct{}
  12. func New() *Service { return &Service{} }
  13. func (s *Service) Verify(input model.InterfaceConfig, managementInterface string, maintenanceCIDR string) error {
  14. iface, err := net.InterfaceByName(input.Interface)
  15. if err != nil {
  16. return err
  17. }
  18. addrs, err := iface.Addrs()
  19. if err != nil {
  20. return err
  21. }
  22. matchedAddress := false
  23. for _, addr := range addrs {
  24. ipNet, ok := addr.(*net.IPNet)
  25. if !ok || ipNet.IP.To4() == nil {
  26. continue
  27. }
  28. prefix, _ := ipNet.Mask.Size()
  29. if ipNet.IP.String() == input.IP && prefix == input.Prefix {
  30. matchedAddress = true
  31. break
  32. }
  33. }
  34. if !matchedAddress {
  35. return fmt.Errorf("目标接口地址未按预期生效")
  36. }
  37. actualGateway := readGateway(input.Interface)
  38. if strings.TrimSpace(input.Gateway) != strings.TrimSpace(actualGateway) {
  39. return fmt.Errorf("目标接口网关未按预期生效")
  40. }
  41. actualDNS := readDNS()
  42. if !containsAll(actualDNS, input.DNS) {
  43. return fmt.Errorf("DNS 未按预期生效")
  44. }
  45. if managementInterface != "" && maintenanceCIDR != "" {
  46. ok, err := hasInterfaceCIDR(managementInterface, maintenanceCIDR)
  47. if err != nil {
  48. return err
  49. }
  50. if !ok {
  51. return fmt.Errorf("管理接口维护地址未按预期保留")
  52. }
  53. }
  54. return nil
  55. }
  56. func readGateway(interfaceName string) string {
  57. cmd := exec.Command("ip", "route", "show", "dev", interfaceName)
  58. output, err := cmd.Output()
  59. if err != nil {
  60. return ""
  61. }
  62. for _, line := range strings.Split(string(output), "\n") {
  63. line = strings.TrimSpace(line)
  64. if !strings.HasPrefix(line, "default via ") {
  65. continue
  66. }
  67. parts := strings.Fields(line)
  68. if len(parts) >= 3 {
  69. return parts[2]
  70. }
  71. }
  72. return ""
  73. }
  74. func readDNS() []string {
  75. file, err := os.Open("/etc/resolv.conf")
  76. if err != nil {
  77. return []string{}
  78. }
  79. defer file.Close()
  80. result := make([]string, 0, 2)
  81. scanner := bufio.NewScanner(file)
  82. for scanner.Scan() {
  83. line := strings.TrimSpace(scanner.Text())
  84. if !strings.HasPrefix(line, "nameserver ") {
  85. continue
  86. }
  87. parts := strings.Fields(line)
  88. if len(parts) >= 2 {
  89. result = append(result, parts[1])
  90. }
  91. }
  92. return result
  93. }
  94. func hasInterfaceCIDR(interfaceName string, expectedCIDR string) (bool, error) {
  95. iface, err := net.InterfaceByName(interfaceName)
  96. if err != nil {
  97. return false, err
  98. }
  99. addrs, err := iface.Addrs()
  100. if err != nil {
  101. return false, err
  102. }
  103. for _, addr := range addrs {
  104. if addr.String() == expectedCIDR {
  105. return true, nil
  106. }
  107. }
  108. return false, nil
  109. }
  110. func containsAll(actual []string, expected []string) bool {
  111. if len(expected) == 0 {
  112. return true
  113. }
  114. set := make(map[string]struct{}, len(actual))
  115. for _, item := range actual {
  116. set[strings.TrimSpace(item)] = struct{}{}
  117. }
  118. for _, item := range expected {
  119. if _, ok := set[strings.TrimSpace(item)]; !ok {
  120. return false
  121. }
  122. }
  123. return true
  124. }