add iprange_gws_c.txt
[gscan_quic.git] / iprange.go
blobd99d283e15fd542149519cce7504bc8095c10744
1 package main
3 import (
4 "bufio"
5 "math/rand"
6 "net"
7 "os"
8 "sort"
9 "strings"
10 "time"
12 "github.com/mikioh/ipaddr"
15 // 从每组地址中分离出起始IP以及结束IP
16 // 参考自 moonshawdo 的代码
17 func splitIP(strline string) []ipaddr.Prefix {
18 var begin, end string
19 if strings.Contains(strline, "-") && strings.Contains(strline, "/") {
20 ss := strings.Split(strline, "-")
21 if len(ss) == 2 {
22 iprange1, iprange2 := ss[0], ss[1]
23 // "1.9.22.0/24-1.9.22.0"
24 if strings.Contains(iprange1, "/") && !strings.Contains(iprange2, "/") {
25 begin = iprange1[:strings.Index(iprange1, "/")]
26 if begin == iprange2 {
27 iprange2 = iprange1
29 } else if strings.Contains(iprange2, "/") {
30 // 1.9.22.0/24-1.9.22.0/24
31 begin = iprange1[:strings.Index(iprange1, "/")]
32 } else {
33 // 1.9.22.0-1.9.23.0/24
34 begin = iprange1
36 // c, err := ipaddr.Parse(begin + "," + iprange2)
37 // if err != nil {
38 // panic(err)
39 // }
40 // return ipaddr.Aggregate(c.List())
42 if c, err := ipaddr.Parse(iprange2); err == nil {
43 end = c.Last().IP.String()
46 } else if strings.Contains(strline, "-") {
47 num_regions := strings.Split(strline, ".")
48 if len(num_regions) == 4 {
49 // "xxx.xxx.xxx-xxx.xxx-xxx"
50 for _, region := range num_regions {
51 if strings.Contains(region, "-") {
52 a := strings.Split(region, "-")
53 s, e := a[0], a[1]
54 begin += "." + s
55 end += "." + e
56 } else {
57 begin += "." + region
58 end += "." + region
61 begin = begin[1:]
62 end = end[1:]
63 } else {
64 // "xxx.xxx.xxx.xxx-xxx.xxx.xxx.xxx"
65 a := strings.Split(strline, "-")
66 begin, end = a[0], a[1]
67 if 1 <= len(end) && len(end) <= 3 {
68 prefix := begin[0:strings.LastIndex(begin, ".")]
69 end = prefix + "." + end
72 } else if strings.HasSuffix(strline, ".") {
73 // "xxx.xxx.xxx."
74 begin = strline + "0"
75 end = strline + "255"
76 } else if strings.Contains(strline, "/") {
77 // "xxx.xxx.xxx.xxx/xx"
78 if c, err := ipaddr.Parse(strline); err == nil {
79 return c.List()
81 return nil
82 } else {
83 // "xxx.xxx.xxx.xxx"
84 // 如果IP带有端口, 那么就分离端口
85 if i := strings.LastIndex(strline, ":"); i != -1 {
86 if c, err := ipaddr.Parse(strline[:i]); err == nil {
87 return c.List()
90 begin = strline
91 end = strline
94 return ipaddr.Summarize(net.ParseIP(begin), net.ParseIP(end))
97 var sepReplacer = strings.NewReplacer(`","`, ",", `", "`, ",", "|", ",")
99 func parseIPRangeFile(file string) (chan string, error) {
100 f, err := os.Open(file)
101 if err != nil {
102 return nil, err
104 defer f.Close()
106 ipranges := make([]ipaddr.Prefix, 0)
107 scanner := bufio.NewScanner(f)
108 // 一行最大 4MB
109 buf := make([]byte, 1024*1024*4)
110 scanner.Buffer(buf, 1024*1024*4)
112 for scanner.Scan() {
113 line := strings.TrimFunc(scanner.Text(), func(r rune) bool {
114 switch r {
115 case ',', '|', '"', '\'':
116 return true
117 case '\t', '\n', '\v', '\f', '\r', ' ', 0x85, 0xA0:
118 return true
120 return false
122 if line == "" || strings.HasPrefix(line, "#") {
123 continue
126 // 支持 gop 的 "xxx","xxx" 和 goa 的 xxx|xxx 格式
127 if s := sepReplacer.Replace(line); strings.Contains(s, ",") {
128 if c, err := ipaddr.Parse(s); err == nil {
129 ipranges = append(ipranges, c.List()...)
131 } else {
132 ipranges = append(ipranges, splitIP(line)...)
136 /* IP段去重 (此描述对当前算法不适用-2017/09/21)
138 "1.9.22.0-255"
139 "1.9.0.0/16"
140 "1.9.22.0-255"
141 "1.9.22.0/24"
142 "1.9.22.0-255"
143 "1.9.22.0-1.9.22.100"
144 "1.9.22.0-1.9.22.255"
145 "1.9.0.0/16"
146 "3.3.3.0/24"
147 "3.3.0.0/16"
148 "3.3.3.0-255"
149 "1.1.1.0/24"
150 "1.9.0.0/16"
151 "2001:db8::1/128"
155 [1.9.0.0/16 3.3.0.0/16 1.1.1.0/24 203.0.113.0/24 2001:db8::1/128]
158 out := make(chan string, 200)
159 go func() {
160 defer close(out)
161 if len(ipranges) > 0 {
162 sort.Slice(ipranges, func(i int, j int) bool {
163 return strings.Compare(ipranges[i].String(), ipranges[j].String()) == -1
165 ipranges = dedup(ipranges)
167 // 打乱IP段扫描顺序
168 rand.Seed(time.Now().Unix())
169 perm := rand.Perm(len(ipranges))
170 for _, v := range perm {
171 c := ipaddr.NewCursor([]ipaddr.Prefix{ipranges[v]})
172 for ip := c.First(); ip != nil; ip = c.Next() {
173 out <- ip.IP.String()
179 return out, nil
182 func dedup(s []ipaddr.Prefix) []ipaddr.Prefix {
183 out := s[:1]
184 t := s[0]
185 for _, s := range s[1:] {
186 if !t.Contains(&s) && !t.Equal(&s) {
187 out = append(out, s)
188 t = s
191 return out