实现Ping和TCP端口扫描功能
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
package scan
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
reIPv4 = regexp.MustCompile(`^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$`)
|
||||
reIPv4Range = regexp.MustCompile(`^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)-((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$`)
|
||||
reCIDR = regexp.MustCompile(`^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)/(0?[0-9]|1[0-9]|2[0-9]|3[0-2])$`)
|
||||
reIPv6 = regexp.MustCompile(`^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$`)
|
||||
reDomain = regexp.MustCompile(`^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\.)+[a-zA-Z]{2,}$`)
|
||||
rePort = regexp.MustCompile(`^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$`)
|
||||
)
|
||||
|
||||
func ParseIPs(text string) ([]string, error) {
|
||||
var ips []string
|
||||
sc := bufio.NewScanner(strings.NewReader(text))
|
||||
for sc.Scan() {
|
||||
line := strings.TrimSpace(sc.Text())
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
switch {
|
||||
case reIPv4.MatchString(line):
|
||||
ips = append(ips, line)
|
||||
case reIPv4Range.MatchString(line):
|
||||
parts := strings.SplitN(line, "-", 2)
|
||||
a, err := netip.ParseAddr(parts[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("无效IP段: %s", line)
|
||||
}
|
||||
b, err := netip.ParseAddr(parts[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("无效IP段: %s", line)
|
||||
}
|
||||
ai := a.As4()
|
||||
bi := b.As4()
|
||||
aInt := uint32(ai[0])<<24 | uint32(ai[1])<<16 | uint32(ai[2])<<8 | uint32(ai[3])
|
||||
bInt := uint32(bi[0])<<24 | uint32(bi[1])<<16 | uint32(bi[2])<<8 | uint32(bi[3])
|
||||
if aInt > bInt {
|
||||
aInt, bInt = bInt, aInt
|
||||
}
|
||||
for i := aInt; i <= bInt; i++ {
|
||||
ip := netip.AddrFrom4([4]byte{byte(i >> 24), byte(i >> 16), byte(i >> 8), byte(i)})
|
||||
ips = append(ips, ip.String())
|
||||
}
|
||||
case reCIDR.MatchString(line):
|
||||
baseIP, ipNet, err := net.ParseCIDR(line)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("无效CIDR: %s", line)
|
||||
}
|
||||
if baseIP.To4() == nil {
|
||||
return nil, fmt.Errorf("仅支持IPv4 CIDR: %s", line)
|
||||
}
|
||||
ips = append(ips, cidrIPs(ipNet)...)
|
||||
case reIPv6.MatchString(line):
|
||||
ips = append(ips, line)
|
||||
case reDomain.MatchString(line):
|
||||
ips = append(ips, line)
|
||||
default:
|
||||
return nil, fmt.Errorf("无法识别的目标: %s", line)
|
||||
}
|
||||
}
|
||||
return ips, sc.Err()
|
||||
}
|
||||
|
||||
func cidrIPs(ipNet *net.IPNet) []string {
|
||||
var ips []string
|
||||
for ip := ipNet.IP.Mask(ipNet.Mask); ipNet.Contains(ip); inc(ip) {
|
||||
ips = append(ips, ip.String())
|
||||
}
|
||||
if len(ips) > 0 {
|
||||
ips = ips[1:]
|
||||
}
|
||||
if len(ips) > 0 {
|
||||
ips = ips[:len(ips)-1]
|
||||
}
|
||||
return ips
|
||||
}
|
||||
|
||||
func inc(ip net.IP) {
|
||||
for j := len(ip) - 1; j >= 0; j-- {
|
||||
ip[j]++
|
||||
if ip[j] > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ParsePorts(text string) ([]int, error) {
|
||||
var ports []int
|
||||
sc := bufio.NewScanner(strings.NewReader(text))
|
||||
for sc.Scan() {
|
||||
line := strings.TrimSpace(sc.Text())
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
for _, seg := range strings.Split(line, ";") {
|
||||
seg = strings.TrimSpace(seg)
|
||||
if seg == "" {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(seg, "-") {
|
||||
parts := strings.SplitN(seg, "-", 2)
|
||||
a, err1 := strconv.Atoi(strings.TrimSpace(parts[0]))
|
||||
b, err2 := strconv.Atoi(strings.TrimSpace(parts[1]))
|
||||
if err1 != nil || err2 != nil || a < 0 || a > 65535 || b < 0 || b > 65535 {
|
||||
return nil, fmt.Errorf("无效端口范围: %s", seg)
|
||||
}
|
||||
if a > b {
|
||||
a, b = b, a
|
||||
}
|
||||
for p := a; p <= b; p++ {
|
||||
ports = append(ports, p)
|
||||
}
|
||||
} else {
|
||||
if !rePort.MatchString(seg) {
|
||||
return nil, fmt.Errorf("无效端口: %s", seg)
|
||||
}
|
||||
p, _ := strconv.Atoi(seg)
|
||||
ports = append(ports, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ports, sc.Err()
|
||||
}
|
||||
Reference in New Issue
Block a user