Files
CloudflareSpeedTest/task/ip.go

183 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package task
import (
"bufio"
"log"
"math/rand"
"net"
"os"
"strconv"
"strings"
"time"
)
const defaultInputFile = "ip.txt"
var (
// TestAll test all ip
TestAll = false
// IPFile is the filename of IP Rangs
IPFile = defaultInputFile
IPText string
)
func InitRandSeed() {
rand.Seed(time.Now().UnixNano())
}
func isIPv4(ip string) bool {
return strings.Contains(ip, ".")
}
func randIPEndWith(num byte) byte {
if num == 0 { // 对于 /32 这种单独的 IP
return byte(0)
}
return byte(rand.Intn(int(num)))
}
type IPRanges struct {
ips []*net.IPAddr
mask string
firstIP net.IP
ipNet *net.IPNet
}
func newIPRanges() *IPRanges {
return &IPRanges{
ips: make([]*net.IPAddr, 0),
}
}
// 如果是单独 IP 则加上子网掩码,反之则获取子网掩码(r.mask)
func (r *IPRanges) fixIP(ip string) string {
// 如果不含有 '/' 则代表不是 IP 段,而是一个单独的 IP因此需要加上 /32 /128 子网掩码
if i := strings.IndexByte(ip, '/'); i < 0 {
if isIPv4(ip) {
r.mask = "/32"
} else {
r.mask = "/128"
}
ip += r.mask
} else {
r.mask = ip[i:]
}
return ip
}
// 解析 IP 段,获得 IP、IP 范围
func (r *IPRanges) parseCIDR(ip string) {
var err error
if r.firstIP, r.ipNet, err = net.ParseCIDR(r.fixIP(ip)); err != nil {
log.Fatalln("ParseCIDR err", err)
}
}
func (r *IPRanges) appendIPv4(d byte) {
r.appendIP(net.IPv4(r.firstIP[12], r.firstIP[13], r.firstIP[14], d))
}
func (r *IPRanges) appendIP(ip net.IP) {
r.ips = append(r.ips, &net.IPAddr{IP: ip})
}
// 返回第四段 ip 的最小值及可用数目
func (r *IPRanges) getIPRange() (minIP, hosts byte) {
minIP = r.firstIP[15] & r.ipNet.Mask[3] // IP 第四段最小值
// 根据子网掩码获取主机数量
m := net.IPv4Mask(255, 255, 255, 255)
for i, v := range r.ipNet.Mask {
m[i] ^= v
}
total, _ := strconv.ParseInt(m.String(), 16, 32) // 总可用 IP 数
if total > 255 { // 矫正 第四段 可用 IP 数
hosts = 255
return
}
hosts = byte(total)
return
}
func (r *IPRanges) chooseIPv4() {
minIP, hosts := r.getIPRange()
for r.ipNet.Contains(r.firstIP) {
if TestAll { // 如果是测速全部 IP
for i := 0; i <= int(hosts); i++ { // 遍历 IP 最后一段最小值到最大值
r.appendIPv4(byte(i) + minIP)
}
} else { // 随机 IP 的最后一段 0.0.0.X
r.appendIPv4(minIP + randIPEndWith(hosts))
}
r.firstIP[14]++ // 0.0.(X+1).X
if r.firstIP[14] == 0 {
r.firstIP[13]++ // 0.(X+1).X.X
if r.firstIP[13] == 0 {
r.firstIP[12]++ // (X+1).X.X.X
}
}
}
}
func (r *IPRanges) chooseIPv6() {
var tempIP uint8
for r.ipNet.Contains(r.firstIP) {
if r.mask != "/128" {
r.firstIP[15] = randIPEndWith(255) // 随机 IP 的最后一段
r.firstIP[14] = randIPEndWith(255) // 随机 IP 的最后一段
}
targetIP := make([]byte, len(r.firstIP))
copy(targetIP, r.firstIP)
r.appendIP(targetIP)
for i := 13; i >= 0; i-- {
tempIP = r.firstIP[i]
r.firstIP[i] += randIPEndWith(255)
if r.firstIP[i] >= tempIP {
break
}
}
}
}
func loadIPRanges() []*net.IPAddr {
ranges := newIPRanges()
if IPText != "" { // 从参数中获取 IP 段数据
IPs := strings.Split(IPText, ",") // 以逗号分隔为数组并循环遍历
for _, IP := range IPs {
IP = strings.TrimSpace(IP) // 去除首尾的空白字符(空格、制表符、换行符等)
if IP == "" { // 跳过空的(即开头、结尾或连续多个 ,, 的情况)
continue
}
ranges.parseCIDR(IP)
if isIPv4(IP) {
ranges.chooseIPv4()
} else {
ranges.chooseIPv6()
}
}
} else { // 从文件中获取 IP 段数据
if IPFile == "" {
IPFile = defaultInputFile
}
file, err := os.Open(IPFile)
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() { // 循环遍历文件每一行
line := strings.TrimSpace(scanner.Text()) // 去除首尾的空白字符(空格、制表符、换行符等)
if line == "" { // 跳过空行
continue
}
ranges.parseCIDR(line)
if isIPv4(line) {
ranges.chooseIPv4()
} else {
ranges.chooseIPv6()
}
}
}
return ranges.ips
}