├── .gitignore ├── README.md ├── cacert.pem ├── config.json ├── file.go ├── ip.go ├── iprange.txt └── main.go /.gitignore: -------------------------------------------------------------------------------- 1 | go-checkip 2 | go-checkip.exe 3 | okip.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 下载: 2 | 3 | https://github.com/hjolin/go-checkip/releases 4 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "concurrency" : 100, 3 | "server" : [ 4 | "gws", 5 | "gvs 1.0" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /file.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/golang/glog" 6 | "io/ioutil" 7 | "os" 8 | "runtime" 9 | "strings" 10 | ) 11 | 12 | const ( 13 | defaultFileMode = 0644 14 | ) 15 | 16 | var sep string 17 | 18 | func init() { 19 | if runtime.GOOS == "windows" { 20 | sep = "\r\n" 21 | } else { 22 | sep = "\n" 23 | } 24 | } 25 | 26 | func readIPFile(file string) []string { 27 | bytes, err := ioutil.ReadFile(file) 28 | if err != nil { 29 | glog.Fatal(err) 30 | } 31 | 32 | return strings.Split(string(bytes), sep) 33 | } 34 | 35 | func writeOKIP(okIPList IPList) { 36 | f, err := os.Create("./okip.txt") 37 | checkErr(err) 38 | defer f.Close() 39 | for _, ip := range okIPList.IPList { 40 | f.WriteString(fmt.Sprintf("%s %d %s %s%s", ip.addr, ip.timeDelay, ip.commonName, ip.serverName, sep)) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ip.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "net" 6 | "sort" 7 | "strings" 8 | ) 9 | 10 | type IP struct { 11 | addr string 12 | commonName string 13 | orgName string 14 | serverName string 15 | timeDelay int 16 | } 17 | 18 | type IPList struct { 19 | sort.Interface 20 | IPList []IP 21 | } 22 | 23 | func (iplist IPList) Len() int { 24 | return len(iplist.IPList) 25 | } 26 | 27 | func (iplist IPList) Less(i, j int) bool { 28 | if iplist.IPList[i].timeDelay <= iplist.IPList[j].timeDelay { 29 | return true 30 | } 31 | 32 | return false 33 | } 34 | 35 | func (iplist *IPList) Swap(i, j int) { 36 | t := *new(IP) 37 | t = (*iplist).IPList[i] 38 | (*iplist).IPList[i] = (*iplist).IPList[j] 39 | (*iplist).IPList[j] = t 40 | } 41 | 42 | func inc(ip net.IP) { 43 | for i := len(ip) - 1; i >= 0; i-- { 44 | ip[i]++ 45 | if ip[i] > 0 { 46 | break 47 | } 48 | } 49 | } 50 | 51 | func parseIPRange(iprange string) []string { 52 | var ipStrList []string 53 | if strings.Contains(iprange, "-") { 54 | parts := strings.Split(iprange, "-") 55 | startip := net.ParseIP(parts[0]) 56 | endip := net.ParseIP(parts[1]) 57 | for ip := startip; bytes.Compare(ip, endip) <= 0; inc(ip) { 58 | ipStrList = append(ipStrList, ip.String()) 59 | } 60 | if strings.HasSuffix(ipStrList[0], ".0") { 61 | ipStrList = ipStrList[1:] 62 | } 63 | if strings.HasSuffix(ipStrList[len(ipStrList)-1], ".0") { 64 | ipStrList = ipStrList[:len(ipStrList)-2] 65 | } 66 | return ipStrList 67 | 68 | } else if strings.Contains(iprange, "/") { 69 | ip, ipnet, err := net.ParseCIDR(iprange) 70 | checkErr(err) 71 | for ip = ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) { 72 | ipStrList = append(ipStrList, ip.String()) 73 | } 74 | return ipStrList[1 : len(ipStrList)-1] 75 | } else { 76 | ipStrList = append(ipStrList, iprange) 77 | return ipStrList 78 | } 79 | 80 | } 81 | 82 | func getAllIP(file string) []string { 83 | alliprange := readIPFile(file) 84 | var allip []string 85 | for _, iprange := range alliprange { 86 | allip = append(allip, parseIPRange(iprange)...) 87 | } 88 | return allip 89 | } 90 | -------------------------------------------------------------------------------- /iprange.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjolin/go-checkip/f79b9d4e714b022a08db560060afebddc3c515d5/iprange.txt -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "crypto/x509" 6 | "encoding/json" 7 | "flag" 8 | "fmt" 9 | "github.com/golang/glog" 10 | "io/ioutil" 11 | "net" 12 | "os" 13 | "os/signal" 14 | "sort" 15 | "time" 16 | ) 17 | 18 | type config struct { 19 | Concurrency int 20 | Server []string 21 | } 22 | 23 | var ( 24 | tlsOkIPList []IP 25 | conf config 26 | cacertPool *x509.CertPool 27 | 28 | tlsConfig = &tls.Config{ 29 | RootCAs: cacertPool, 30 | InsecureSkipVerify: true, 31 | } 32 | ) 33 | 34 | func init() { 35 | configJson, err := ioutil.ReadFile("./config.json") 36 | checkErr(err) 37 | err = json.Unmarshal(configJson, &conf) 38 | cacertFile, err := ioutil.ReadFile("./cacert.pem") 39 | checkErr(err) 40 | cacertPool = x509.NewCertPool() 41 | cacertPool.AppendCertsFromPEM(cacertFile) 42 | } 43 | 44 | func checkErr(err error) { 45 | if err != nil { 46 | glog.Fatalln(err) 47 | } 48 | } 49 | 50 | func tlsCheckip(ip string, sem chan bool) { 51 | defer func() { <-sem }() 52 | dialer := net.Dialer{ 53 | KeepAlive: 0, 54 | Timeout: time.Millisecond * 7000, 55 | DualStack: false, 56 | } 57 | conn, err := dialer.Dial("tcp", fmt.Sprintf("%s:443", ip)) 58 | 59 | if err != nil { 60 | glog.Infoln(err) 61 | return 62 | } 63 | defer conn.Close() 64 | 65 | start := time.Now() 66 | tlsClient := tls.Client(conn, tlsConfig) 67 | if err = tlsClient.Handshake(); err != nil { 68 | glog.Infoln(err) 69 | } 70 | end := time.Now() 71 | 72 | if tlsClient.ConnectionState().PeerCertificates == nil { 73 | return 74 | } 75 | 76 | peerCertSubject := tlsClient.ConnectionState().PeerCertificates[0].Subject 77 | commonName := peerCertSubject.CommonName 78 | orgName := peerCertSubject.Organization[0] 79 | 80 | checkedip := IP{ 81 | addr: ip, 82 | commonName: commonName, 83 | orgName: orgName, 84 | timeDelay: int(end.Sub(start).Seconds() * 1000), 85 | } 86 | 87 | if checkedip.orgName == "Google Inc" { 88 | if checkedip.commonName == "google.com" { 89 | checkedip.serverName = "gws" 90 | } else if checkedip.commonName == "*.c.docs.google.com" || checkedip.commonName == "*.googlevideo.com" { 91 | checkedip.serverName = "gvs 1.0" 92 | } 93 | } else { 94 | return 95 | } 96 | glog.Infof("%s %s %s %d", checkedip.addr, checkedip.commonName, checkedip.serverName, checkedip.timeDelay) 97 | 98 | if strInSlice(checkedip.serverName, conf.Server) { 99 | tlsOkIPList = append(tlsOkIPList, checkedip) 100 | } 101 | 102 | } 103 | 104 | func strInSlice(str string, strslice []string) bool { 105 | for _, s := range strslice { 106 | if str == s { 107 | return true 108 | } 109 | } 110 | return false 111 | } 112 | 113 | func main() { 114 | defer writeOKIPFile() 115 | 116 | fmt.Printf("Concurrency: %d%s", conf.Concurrency, sep) 117 | fmt.Printf("%#v%s", conf.Server, sep) 118 | 119 | c := make(chan os.Signal, 1) 120 | signal.Notify(c, os.Interrupt) 121 | go func() { 122 | for _ = range c { 123 | writeOKIPFile() 124 | os.Exit(1) 125 | } 126 | }() 127 | flag.Set("logtostderr", "true") 128 | flag.Parse() 129 | 130 | sem := make(chan bool, conf.Concurrency) 131 | var ipstrlist []string 132 | ipstrlist = getAllIP("./iprange.txt") 133 | fmt.Printf("IP to be checked: %d\n", len(ipstrlist)) 134 | time.Sleep(time.Second * 2) 135 | 136 | for _, ip := range ipstrlist { 137 | sem <- true 138 | go tlsCheckip(ip, sem) 139 | } 140 | 141 | for i := 0; i < cap(sem); i++ { 142 | sem <- true 143 | } 144 | 145 | println(len(tlsOkIPList)) 146 | 147 | } 148 | 149 | func writeOKIPFile() { 150 | if len(tlsOkIPList) > 0 { 151 | okips := &IPList{ 152 | IPList: tlsOkIPList, 153 | } 154 | sort.Sort(okips) 155 | writeOKIP(*okips) 156 | } 157 | } 158 | --------------------------------------------------------------------------------