scanner.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package scanner
  2. import (
  3. "fmt"
  4. "net"
  5. "sync"
  6. "time"
  7. sshclient "network-topology-discovery/internal/ssh"
  8. )
  9. // Scanner 网络扫描器
  10. type Scanner struct {
  11. concurrency int
  12. timeout time.Duration
  13. }
  14. // NewScanner 创建扫描器
  15. func NewScanner(concurrency int, timeout time.Duration) *Scanner {
  16. if concurrency <= 0 {
  17. concurrency = 10
  18. }
  19. if timeout == 0 {
  20. timeout = 2 * time.Second
  21. }
  22. return &Scanner{
  23. concurrency: concurrency,
  24. timeout: timeout,
  25. }
  26. }
  27. // ScanRange 扫描IP范围
  28. func (s *Scanner) ScanRange(cidr string) ([]string, error) {
  29. _, ipNet, err := net.ParseCIDR(cidr)
  30. if err != nil {
  31. return nil, fmt.Errorf("invalid CIDR: %w", err)
  32. }
  33. var ips []string
  34. for ip := ipNet.IP.Mask(ipNet.Mask); ipNet.Contains(ip); incIP(ip) {
  35. ips = append(ips, ip.String())
  36. }
  37. return ips, nil
  38. }
  39. // CheckHosts 检查主机是否存活
  40. func (s *Scanner) CheckHosts(ips []string) []string {
  41. var aliveHosts []string
  42. var mu sync.Mutex
  43. var wg sync.WaitGroup
  44. semaphore := make(chan struct{}, s.concurrency)
  45. for _, ip := range ips {
  46. wg.Add(1)
  47. semaphore <- struct{}{}
  48. go func(ip string) {
  49. defer wg.Done()
  50. defer func() { <-semaphore }()
  51. if sshclient.Ping(ip, s.timeout) {
  52. mu.Lock()
  53. aliveHosts = append(aliveHosts, ip)
  54. mu.Unlock()
  55. }
  56. }(ip)
  57. }
  58. wg.Wait()
  59. return aliveHosts
  60. }
  61. // CheckSSHHosts 检查哪些主机开启了SSH
  62. func (s *Scanner) CheckSSHHosts(ips []string, port int) []string {
  63. var sshHosts []string
  64. var mu sync.Mutex
  65. var wg sync.WaitGroup
  66. semaphore := make(chan struct{}, s.concurrency)
  67. for _, ip := range ips {
  68. wg.Add(1)
  69. semaphore <- struct{}{}
  70. go func(ip string) {
  71. defer wg.Done()
  72. defer func() { <-semaphore }()
  73. if sshclient.CheckSSH(ip, port, s.timeout) {
  74. mu.Lock()
  75. sshHosts = append(sshHosts, ip)
  76. mu.Unlock()
  77. }
  78. }(ip)
  79. }
  80. wg.Wait()
  81. return sshHosts
  82. }
  83. // ScanAndDiscover 扫描并发现设备
  84. func (s *Scanner) ScanAndDiscover(cidr string, sshPort int) ([]string, error) {
  85. // 解析IP范围
  86. ips, err := s.ScanRange(cidr)
  87. if err != nil {
  88. return nil, err
  89. }
  90. // 检查存活主机
  91. aliveHosts := s.CheckHosts(ips)
  92. // 检查SSH
  93. sshHosts := s.CheckSSHHosts(aliveHosts, sshPort)
  94. return sshHosts, nil
  95. }
  96. // incIP IP地址递增
  97. func incIP(ip net.IP) {
  98. for j := len(ip) - 1; j >= 0; j-- {
  99. ip[j]++
  100. if ip[j] > 0 {
  101. break
  102. }
  103. }
  104. }