golang 根据网段拆分成ip多线程判断主机是否存活并进行端口探测做好异常判断
以下是一个示例代码,演示了如何使用Go语言根据给定的网段拆分出IP地址,并使用多线程判断主机是否存活并进行端口探测。代码中还包含了异常判断。
package main
import (
"fmt"
"net"
"strconv"
"sync"
"time"
)
const (
startPort = 1
endPort = 65535
timeout = 1 * time.Second
)
func main() {
ipRange := "192.168.0.1/24" // 你的网段
ips := getIPsFromRange(ipRange)
fmt.Printf("拆分的IP地址:%v\n", ips)
var wg sync.WaitGroup
for _, ip := range ips {
wg.Add(1)
go func(ip string) {
defer wg.Done()
isAlive := checkHostAlive(ip)
if isAlive {
fmt.Printf("主机 %s 存活\n", ip)
scanPorts(ip)
} else {
fmt.Printf("主机 %s 不可达\n", ip)
}
}(ip)
}
wg.Wait()
fmt.Println("完成")
}
// 从网段中获取所有的IP地址
func getIPsFromRange(ipRange string) []string {
ip, subnet, _ := net.ParseCIDR(ipRange)
var ips []string
for ip := ip.Mask(subnet.Mask); subnet.Contains(ip); inc(ip) {
ips = append(ips, ip.String())
}
return ips
}
// IP地址自增
func inc(ip net.IP) {
for j := len(ip) - 1; j >= 0; j-- {
ip[j]++
if ip[j] > 0 {
break
}
}
}
// 检查主机是否存活
func checkHostAlive(ip string) bool {
conn, err := net.DialTimeout("ip4:icmp", ip, timeout)
if err != nil {
return false
}
conn.Close()
return true
}
// 端口探测
func scanPorts(ip string) {
for port := startPort; port <= endPort; port++ {
target := ip + ":" + strconv.Itoa(port)
conn, err := net.DialTimeout("tcp", target, timeout)
if err == nil {
fmt.Printf("主机 %s 的端口 %d 是开放的\n", ip, port)
conn.Close()
}
}
}
在上面的示例代码中,首先定义了一个常量startPort和endPort,分别表示要扫描的端口范围。timeout常量表示连接超时时间。
getIPsFromRange函数根据给定的网段拆分出所有的IP地址,并返回一个字符串数组。
checkHostAlive函数用于检查主机是否存活。它使用net.DialTimeout函数尝试建立与主机的ICMP连接,如果连接成功,则表示主机存活。
scanPorts函数用于进行端口探测。它使用net.DialTimeout函数尝试建立与目标主机指定端口的TCP连接,如果连接成功,则表示该端口开放。
在main函数中,先调用getIPsFromRange函数获取所有的IP地址,然后使用一个sync.WaitGroup来等待所有的协程完成。
对于每个IP地址,启动一个协程来检查主机存活并进行端口探测。如果主机存活,则输出相应的信息并调用scanPorts函数进行端口探测;否则,输出主机不可达的信息。
最后,调用Wait方法等待所有的协程完成,并输出"完成"的信息。
注意,上述代码中的端口探测使用的是阻塞的方式,可以根据实际需求进行改进,使用非阻塞方式或并发方式进行端口探测。同时,对于大规模的扫描任务,可能需要考虑使用更高效的方式来提高性能
原文地址: http://www.cveoy.top/t/topic/hZGY 著作权归作者所有。请勿转载和采集!