diff --git a/Common/ParseIP.go b/Common/ParseIP.go index 316b319..8d2c4df 100644 --- a/Common/ParseIP.go +++ b/Common/ParseIP.go @@ -13,62 +13,79 @@ import ( "strings" ) -var ParseIPErr = errors.New(" host parsing error\n" + - "format: \n" + - "192.168.1.1\n" + - "192.168.1.1/8\n" + - "192.168.1.1/16\n" + - "192.168.1.1/24\n" + - "192.168.1.1,192.168.1.2\n" + - "192.168.1.1-192.168.255.255\n" + - "192.168.1.1-255") +var ParseIPErr = errors.New("主机解析错误\n" + + "支持的格式: \n" + + "192.168.1.1 (单个IP)\n" + + "192.168.1.1/8 (8位子网)\n" + + "192.168.1.1/16 (16位子网)\n" + + "192.168.1.1/24 (24位子网)\n" + + "192.168.1.1,192.168.1.2 (IP列表)\n" + + "192.168.1.1-192.168.255.255 (IP范围)\n" + + "192.168.1.1-255 (最后一位简写范围)") +// ParseIP 解析IP地址配置,支持从主机字符串和文件读取 func ParseIP(host string, filename string, nohosts ...string) (hosts []string, err error) { + // 处理主机和端口组合的情况 (192.168.0.0/16:80) if filename == "" && strings.Contains(host, ":") { - //192.168.0.0/16:80 hostport := strings.Split(host, ":") if len(hostport) == 2 { host = hostport[0] hosts = ParseIPs(host) Ports = hostport[1] + fmt.Printf("[*] 已解析主机端口组合,端口设置为: %s\n", Ports) } } else { + // 解析主机地址 hosts = ParseIPs(host) + + // 从文件加载额外主机 if filename != "" { - var filehost []string - filehost, _ = Readipfile(filename) - hosts = append(hosts, filehost...) - } - } - - if len(nohosts) > 0 { - nohost := nohosts[0] - if nohost != "" { - nohosts := ParseIPs(nohost) - if len(nohosts) > 0 { - temp := map[string]struct{}{} - for _, host := range hosts { - temp[host] = struct{}{} - } - - for _, host := range nohosts { - delete(temp, host) - } - - var newDatas []string - for host := range temp { - newDatas = append(newDatas, host) - } - hosts = newDatas - sort.Strings(hosts) + fileHosts, err := Readipfile(filename) + if err != nil { + fmt.Printf("[!] 读取主机文件失败: %v\n", err) + } else { + hosts = append(hosts, fileHosts...) + fmt.Printf("[*] 已从文件加载额外主机: %d 个\n", len(fileHosts)) } } } - hosts = RemoveDuplicate(hosts) - if len(hosts) == 0 && len(HostPort) == 0 && host != "" && filename != "" { - err = ParseIPErr + + // 处理排除主机 + if len(nohosts) > 0 && nohosts[0] != "" { + excludeHosts := ParseIPs(nohosts[0]) + if len(excludeHosts) > 0 { + // 使用map存储有效主机 + temp := make(map[string]struct{}) + for _, host := range hosts { + temp[host] = struct{}{} + } + + // 删除需要排除的主机 + for _, host := range excludeHosts { + delete(temp, host) + } + + // 重建主机列表 + var newHosts []string + for host := range temp { + newHosts = append(newHosts, host) + } + hosts = newHosts + sort.Strings(hosts) + fmt.Printf("[*] 已排除指定主机: %d 个\n", len(excludeHosts)) + } } - return + + // 去重处理 + hosts = RemoveDuplicate(hosts) + fmt.Printf("[*] 最终有效主机数量: %d\n", len(hosts)) + + // 检查解析结果 + if len(hosts) == 0 && len(HostPort) == 0 && (host != "" || filename != "") { + return nil, ParseIPErr + } + + return hosts, nil } func ParseIPs(ip string) (hosts []string) { @@ -85,190 +102,279 @@ func ParseIPs(ip string) (hosts []string) { return hosts } +// parseIP 解析不同格式的IP地址,返回解析后的IP列表 func parseIP(ip string) []string { reg := regexp.MustCompile(`[a-zA-Z]+`) + switch { + // 处理常用内网IP段简写 case ip == "192": return parseIP("192.168.0.0/8") case ip == "172": return parseIP("172.16.0.0/12") case ip == "10": return parseIP("10.0.0.0/8") - // 扫描/8时,只扫网关和随机IP,避免扫描过多IP + + // 处理/8网段 - 仅扫描网关和随机IP以避免过多扫描 case strings.HasSuffix(ip, "/8"): return parseIP8(ip) - //解析 /24 /16 /8 /xxx 等 + + // 处理CIDR格式 (/24 /16 /8等) case strings.Contains(ip, "/"): return parseIP2(ip) - //可能是域名,用lookup获取ip + + // 处理域名 - 保留域名格式 case reg.MatchString(ip): - // _, err := net.LookupHost(ip) - // if err != nil { - // return nil - // } return []string{ip} - //192.168.1.1-192.168.1.100 + + // 处理IP范围格式 (192.168.1.1-192.168.1.100) case strings.Contains(ip, "-"): return parseIP1(ip) - //处理单个ip + + // 处理单个IP地址 default: testIP := net.ParseIP(ip) if testIP == nil { + fmt.Printf("[!] 无效的IP地址格式: %s\n", ip) return nil } return []string{ip} } } -// 把 192.168.x.x/xx 转换成 192.168.x.x-192.168.x.x -func parseIP2(host string) (hosts []string) { +// parseIP2 解析CIDR格式的IP地址段 +func parseIP2(host string) []string { + // 解析CIDR _, ipNet, err := net.ParseCIDR(host) if err != nil { - return + fmt.Printf("[!] CIDR格式解析失败: %s, %v\n", host, err) + return nil } - hosts = parseIP1(IPRange(ipNet)) - return + + // 转换为IP范围并解析 + ipRange := IPRange(ipNet) + hosts := parseIP1(ipRange) + + fmt.Printf("[*] 已解析CIDR %s -> IP范围 %s\n", host, ipRange) + return hosts } -// 解析ip段: -// -// 192.168.111.1-255 -// 192.168.111.1-192.168.112.255 +// parseIP1 解析IP范围格式的地址 func parseIP1(ip string) []string { - IPRange := strings.Split(ip, "-") - testIP := net.ParseIP(IPRange[0]) - var AllIP []string - if len(IPRange[1]) < 4 { - Range, err := strconv.Atoi(IPRange[1]) - if testIP == nil || Range > 255 || err != nil { + ipRange := strings.Split(ip, "-") + testIP := net.ParseIP(ipRange[0]) + var allIP []string + + // 处理简写格式 (192.168.111.1-255) + if len(ipRange[1]) < 4 { + endNum, err := strconv.Atoi(ipRange[1]) + if testIP == nil || endNum > 255 || err != nil { + fmt.Printf("[!] IP范围格式错误: %s\n", ip) return nil } - SplitIP := strings.Split(IPRange[0], ".") - ip1, err1 := strconv.Atoi(SplitIP[3]) - ip2, err2 := strconv.Atoi(IPRange[1]) - PrefixIP := strings.Join(SplitIP[0:3], ".") - if ip1 > ip2 || err1 != nil || err2 != nil { + + // 解析IP段 + splitIP := strings.Split(ipRange[0], ".") + startNum, err1 := strconv.Atoi(splitIP[3]) + endNum, err2 := strconv.Atoi(ipRange[1]) + prefixIP := strings.Join(splitIP[0:3], ".") + + if startNum > endNum || err1 != nil || err2 != nil { + fmt.Printf("[!] IP范围无效: %d-%d\n", startNum, endNum) return nil } - for i := ip1; i <= ip2; i++ { - AllIP = append(AllIP, PrefixIP+"."+strconv.Itoa(i)) + + // 生成IP列表 + for i := startNum; i <= endNum; i++ { + allIP = append(allIP, prefixIP+"."+strconv.Itoa(i)) } + + fmt.Printf("[*] 已生成IP范围: %s.%d - %s.%d\n", prefixIP, startNum, prefixIP, endNum) } else { - SplitIP1 := strings.Split(IPRange[0], ".") - SplitIP2 := strings.Split(IPRange[1], ".") - if len(SplitIP1) != 4 || len(SplitIP2) != 4 { + // 处理完整IP范围格式 (192.168.111.1-192.168.112.255) + splitIP1 := strings.Split(ipRange[0], ".") + splitIP2 := strings.Split(ipRange[1], ".") + + if len(splitIP1) != 4 || len(splitIP2) != 4 { + fmt.Printf("[!] IP格式错误: %s\n", ip) return nil } + + // 解析起始和结束IP start, end := [4]int{}, [4]int{} for i := 0; i < 4; i++ { - ip1, err1 := strconv.Atoi(SplitIP1[i]) - ip2, err2 := strconv.Atoi(SplitIP2[i]) + ip1, err1 := strconv.Atoi(splitIP1[i]) + ip2, err2 := strconv.Atoi(splitIP2[i]) if ip1 > ip2 || err1 != nil || err2 != nil { + fmt.Printf("[!] IP范围无效: %s-%s\n", ipRange[0], ipRange[1]) return nil } start[i], end[i] = ip1, ip2 } + + // 将IP转换为数值并生成范围内的所有IP startNum := start[0]<<24 | start[1]<<16 | start[2]<<8 | start[3] endNum := end[0]<<24 | end[1]<<16 | end[2]<<8 | end[3] + for num := startNum; num <= endNum; num++ { - ip := strconv.Itoa((num>>24)&0xff) + "." + strconv.Itoa((num>>16)&0xff) + "." + strconv.Itoa((num>>8)&0xff) + "." + strconv.Itoa((num)&0xff) - AllIP = append(AllIP, ip) + ip := strconv.Itoa((num>>24)&0xff) + "." + + strconv.Itoa((num>>16)&0xff) + "." + + strconv.Itoa((num>>8)&0xff) + "." + + strconv.Itoa((num)&0xff) + allIP = append(allIP, ip) } + + fmt.Printf("[*] 已生成IP范围: %s - %s\n", ipRange[0], ipRange[1]) } - return AllIP + + return allIP } -// 获取起始IP、结束IP +// IPRange 计算CIDR的起始IP和结束IP func IPRange(c *net.IPNet) string { + // 获取起始IP start := c.IP.String() + + // 获取子网掩码 mask := c.Mask + + // 计算广播地址(结束IP) bcst := make(net.IP, len(c.IP)) copy(bcst, c.IP) + + // 通过位运算计算最大IP地址 for i := 0; i < len(mask); i++ { ipIdx := len(bcst) - i - 1 bcst[ipIdx] = c.IP[ipIdx] | ^mask[len(mask)-i-1] } end := bcst.String() - return fmt.Sprintf("%s-%s", start, end) //返回用-表示的ip段,192.168.1.0-192.168.255.255 + + // 返回"起始IP-结束IP"格式的字符串 + result := fmt.Sprintf("%s-%s", start, end) + fmt.Printf("[*] CIDR范围: %s\n", result) + + return result } -// 按行读ip +// Readipfile 从文件中按行读取IP地址 func Readipfile(filename string) ([]string, error) { + // 打开文件 file, err := os.Open(filename) if err != nil { - fmt.Printf("Open %s error, %v", filename, err) - os.Exit(0) + fmt.Printf("[!] 打开文件失败 %s: %v\n", filename, err) + return nil, err } defer file.Close() + var content []string scanner := bufio.NewScanner(file) scanner.Split(bufio.ScanLines) + + // 逐行处理IP for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) - if line != "" { - text := strings.Split(line, ":") - if len(text) == 2 { - port := strings.Split(text[1], " ")[0] - num, err := strconv.Atoi(port) - if err != nil || (num < 1 || num > 65535) { - continue - } - hosts := ParseIPs(text[0]) - for _, host := range hosts { - HostPort = append(HostPort, fmt.Sprintf("%s:%s", host, port)) - } - } else { - host := ParseIPs(line) - content = append(content, host...) + if line == "" { + continue + } + + // 解析IP:端口格式 + text := strings.Split(line, ":") + if len(text) == 2 { + port := strings.Split(text[1], " ")[0] + num, err := strconv.Atoi(port) + if err != nil || num < 1 || num > 65535 { + fmt.Printf("[!] 忽略无效端口: %s\n", line) + continue } + + // 解析带端口的IP地址 + hosts := ParseIPs(text[0]) + for _, host := range hosts { + HostPort = append(HostPort, fmt.Sprintf("%s:%s", host, port)) + } + fmt.Printf("[*] 已解析IP端口组合: %s\n", line) + } else { + // 解析纯IP地址 + hosts := ParseIPs(line) + content = append(content, hosts...) + fmt.Printf("[*] 已解析IP地址: %s\n", line) } } + + // 检查扫描过程中是否有错误 + if err := scanner.Err(); err != nil { + fmt.Printf("[!] 读取文件时出错: %v\n", err) + return content, err + } + + fmt.Printf("[*] 从文件加载完成,共解析 %d 个IP地址\n", len(content)) return content, nil } -// 去重 +// RemoveDuplicate 对字符串切片进行去重 func RemoveDuplicate(old []string) []string { - result := []string{} - temp := map[string]struct{}{} + // 使用map存储不重复的元素 + temp := make(map[string]struct{}) + var result []string + + // 遍历并去重 for _, item := range old { - if _, ok := temp[item]; !ok { + if _, exists := temp[item]; !exists { temp[item] = struct{}{} result = append(result, item) } } + return result } +// parseIP8 解析/8网段的IP地址 func parseIP8(ip string) []string { + // 去除CIDR后缀获取基础IP realIP := ip[:len(ip)-2] testIP := net.ParseIP(realIP) if testIP == nil { + fmt.Printf("[!] 无效的IP地址格式: %s\n", realIP) return nil } - IPrange := strings.Split(ip, ".")[0] - var AllIP []string + // 获取/8网段的第一段 + ipRange := strings.Split(ip, ".")[0] + var allIP []string + + fmt.Printf("[*] 开始解析 %s.0.0.0/8 网段\n", ipRange) + + // 遍历所有可能的第二、三段 for a := 0; a <= 255; a++ { for b := 0; b <= 255; b++ { - AllIP = append(AllIP, fmt.Sprintf("%s.%d.%d.%d", IPrange, a, b, 1)) - AllIP = append(AllIP, fmt.Sprintf("%s.%d.%d.%d", IPrange, a, b, 2)) - AllIP = append(AllIP, fmt.Sprintf("%s.%d.%d.%d", IPrange, a, b, 4)) - AllIP = append(AllIP, fmt.Sprintf("%s.%d.%d.%d", IPrange, a, b, 5)) - AllIP = append(AllIP, fmt.Sprintf("%s.%d.%d.%d", IPrange, a, b, RandInt(6, 55))) - AllIP = append(AllIP, fmt.Sprintf("%s.%d.%d.%d", IPrange, a, b, RandInt(56, 100))) - AllIP = append(AllIP, fmt.Sprintf("%s.%d.%d.%d", IPrange, a, b, RandInt(101, 150))) - AllIP = append(AllIP, fmt.Sprintf("%s.%d.%d.%d", IPrange, a, b, RandInt(151, 200))) - AllIP = append(AllIP, fmt.Sprintf("%s.%d.%d.%d", IPrange, a, b, RandInt(201, 253))) - AllIP = append(AllIP, fmt.Sprintf("%s.%d.%d.%d", IPrange, a, b, 254)) + // 添加常用网关IP + allIP = append(allIP, fmt.Sprintf("%s.%d.%d.1", ipRange, a, b)) // 默认网关 + allIP = append(allIP, fmt.Sprintf("%s.%d.%d.2", ipRange, a, b)) // 备用网关 + allIP = append(allIP, fmt.Sprintf("%s.%d.%d.4", ipRange, a, b)) // 常用服务器 + allIP = append(allIP, fmt.Sprintf("%s.%d.%d.5", ipRange, a, b)) // 常用服务器 + + // 随机采样不同范围的IP + allIP = append(allIP, fmt.Sprintf("%s.%d.%d.%d", ipRange, a, b, RandInt(6, 55))) // 低段随机 + allIP = append(allIP, fmt.Sprintf("%s.%d.%d.%d", ipRange, a, b, RandInt(56, 100))) // 中低段随机 + allIP = append(allIP, fmt.Sprintf("%s.%d.%d.%d", ipRange, a, b, RandInt(101, 150))) // 中段随机 + allIP = append(allIP, fmt.Sprintf("%s.%d.%d.%d", ipRange, a, b, RandInt(151, 200))) // 中高段随机 + allIP = append(allIP, fmt.Sprintf("%s.%d.%d.%d", ipRange, a, b, RandInt(201, 253))) // 高段随机 + allIP = append(allIP, fmt.Sprintf("%s.%d.%d.254", ipRange, a, b)) // 广播地址前 } } - return AllIP + + fmt.Printf("[*] 已生成 %d 个采样IP地址\n", len(allIP)) + return allIP } +// RandInt 生成指定范围内的随机整数 func RandInt(min, max int) int { + // 参数验证 if min >= max || min == 0 || max == 0 { return max } + + // 生成随机数 return rand.Intn(max-min) + min }