ip.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package task
  2. import (
  3. "bufio"
  4. "log"
  5. "math/rand"
  6. "net"
  7. "os"
  8. "strconv"
  9. "strings"
  10. "time"
  11. )
  12. const defaultInputFile = "ip.txt"
  13. var (
  14. // TestAll test all ip
  15. TestAll = false
  16. // IPFile is the filename of IP Rangs
  17. IPFile = defaultInputFile
  18. IPText string
  19. )
  20. func InitRandSeed() {
  21. rand.Seed(time.Now().UnixNano())
  22. }
  23. func isIPv4(ip string) bool {
  24. return strings.Contains(ip, ".")
  25. }
  26. func randIPEndWith(num byte) byte {
  27. if num == 0 { // 对于 /32 这种单独的 IP
  28. return byte(0)
  29. }
  30. return byte(rand.Intn(int(num)))
  31. }
  32. type IPRanges struct {
  33. ips []*net.IPAddr
  34. mask string
  35. firstIP net.IP
  36. ipNet *net.IPNet
  37. }
  38. func newIPRanges() *IPRanges {
  39. return &IPRanges{
  40. ips: make([]*net.IPAddr, 0),
  41. }
  42. }
  43. // 如果是单独 IP 则加上子网掩码,反之则获取子网掩码(r.mask)
  44. func (r *IPRanges) fixIP(ip string) string {
  45. // 如果不含有 '/' 则代表不是 IP 段,而是一个单独的 IP,因此需要加上 /32 /128 子网掩码
  46. if i := strings.IndexByte(ip, '/'); i < 0 {
  47. if isIPv4(ip) {
  48. r.mask = "/32"
  49. } else {
  50. r.mask = "/128"
  51. }
  52. ip += r.mask
  53. } else {
  54. r.mask = ip[i:]
  55. }
  56. return ip
  57. }
  58. // 解析 IP 段,获得 IP、IP 范围、子网掩码
  59. func (r *IPRanges) parseCIDR(ip string) {
  60. var err error
  61. if r.firstIP, r.ipNet, err = net.ParseCIDR(r.fixIP(ip)); err != nil {
  62. log.Fatalln("ParseCIDR err", err)
  63. }
  64. }
  65. func (r *IPRanges) appendIPv4(d byte) {
  66. r.appendIP(net.IPv4(r.firstIP[12], r.firstIP[13], r.firstIP[14], d))
  67. }
  68. func (r *IPRanges) appendIP(ip net.IP) {
  69. r.ips = append(r.ips, &net.IPAddr{IP: ip})
  70. }
  71. // 返回第四段 ip 的最小值及可用数目
  72. func (r *IPRanges) getIPRange() (minIP, hosts byte) {
  73. minIP = r.firstIP[15] & r.ipNet.Mask[3] // IP 第四段最小值
  74. // 根据子网掩码获取主机数量
  75. m := net.IPv4Mask(255, 255, 255, 255)
  76. for i, v := range r.ipNet.Mask {
  77. m[i] ^= v
  78. }
  79. total, _ := strconv.ParseInt(m.String(), 16, 32) // 总可用 IP 数
  80. if total > 255 { // 矫正 第四段 可用 IP 数
  81. hosts = 255
  82. return
  83. }
  84. hosts = byte(total)
  85. return
  86. }
  87. func (r *IPRanges) chooseIPv4() {
  88. if r.mask == "/32" { // 单个 IP 则无需随机,直接加入自身即可
  89. r.appendIP(r.firstIP)
  90. } else {
  91. minIP, hosts := r.getIPRange() // 返回第四段 IP 的最小值及可用数目
  92. for r.ipNet.Contains(r.firstIP) { // 只要该 IP 没有超出 IP 网段范围,就继续循环随机
  93. if TestAll { // 如果是测速全部 IP
  94. for i := 0; i <= int(hosts); i++ { // 遍历 IP 最后一段最小值到最大值
  95. r.appendIPv4(byte(i) + minIP)
  96. }
  97. } else { // 随机 IP 的最后一段 0.0.0.X
  98. r.appendIPv4(minIP + randIPEndWith(hosts))
  99. }
  100. r.firstIP[14]++ // 0.0.(X+1).X
  101. if r.firstIP[14] == 0 {
  102. r.firstIP[13]++ // 0.(X+1).X.X
  103. if r.firstIP[13] == 0 {
  104. r.firstIP[12]++ // (X+1).X.X.X
  105. }
  106. }
  107. }
  108. }
  109. }
  110. func (r *IPRanges) chooseIPv6() {
  111. if r.mask == "/128" { // 单个 IP 则无需随机,直接加入自身即可
  112. r.appendIP(r.firstIP)
  113. } else {
  114. var tempIP uint8 // 临时变量,用于记录前一位的值
  115. for r.ipNet.Contains(r.firstIP) { // 只要该 IP 没有超出 IP 网段范围,就继续循环随机
  116. r.firstIP[15] = randIPEndWith(255) // 随机 IP 的最后一段
  117. r.firstIP[14] = randIPEndWith(255) // 随机 IP 的最后一段
  118. targetIP := make([]byte, len(r.firstIP))
  119. copy(targetIP, r.firstIP)
  120. r.appendIP(targetIP) // 加入 IP 地址池
  121. for i := 13; i >= 0; i-- { // 从倒数第三位开始往前随机
  122. tempIP = r.firstIP[i] // 保存前一位的值
  123. r.firstIP[i] += randIPEndWith(255) // 随机 0~255,加到当前位上
  124. if r.firstIP[i] >= tempIP { // 如果当前位的值大于等于前一位的值,说明随机成功了,可以退出该循环
  125. break
  126. }
  127. }
  128. }
  129. }
  130. }
  131. func loadIPRanges() []*net.IPAddr {
  132. ranges := newIPRanges()
  133. if IPText != "" { // 从参数中获取 IP 段数据
  134. IPs := strings.Split(IPText, ",") // 以逗号分隔为数组并循环遍历
  135. for _, IP := range IPs {
  136. IP = strings.TrimSpace(IP) // 去除首尾的空白字符(空格、制表符、换行符等)
  137. if IP == "" { // 跳过空的(即开头、结尾或连续多个 ,, 的情况)
  138. continue
  139. }
  140. ranges.parseCIDR(IP) // 解析 IP 段,获得 IP、IP 范围、子网掩码
  141. if isIPv4(IP) { // 生成要测速的所有 IPv4 / IPv6 地址(单个/随机/全部)
  142. ranges.chooseIPv4()
  143. } else {
  144. ranges.chooseIPv6()
  145. }
  146. }
  147. } else { // 从文件中获取 IP 段数据
  148. if IPFile == "" {
  149. IPFile = defaultInputFile
  150. }
  151. file, err := os.Open(IPFile)
  152. if err != nil {
  153. log.Fatal(err)
  154. }
  155. defer file.Close()
  156. scanner := bufio.NewScanner(file)
  157. for scanner.Scan() { // 循环遍历文件每一行
  158. line := strings.TrimSpace(scanner.Text()) // 去除首尾的空白字符(空格、制表符、换行符等)
  159. if line == "" { // 跳过空行
  160. continue
  161. }
  162. ranges.parseCIDR(line) // 解析 IP 段,获得 IP、IP 范围、子网掩码
  163. if isIPv4(line) { // 生成要测速的所有 IPv4 / IPv6 地址(单个/随机/全部)
  164. ranges.chooseIPv4()
  165. } else {
  166. ranges.chooseIPv6()
  167. }
  168. }
  169. }
  170. return ranges.ips
  171. }