From 404086f5fbafc285c1d4c570758182adc73b8af4 Mon Sep 17 00:00:00 2001 From: yasutakatou Date: Thu, 27 Aug 2020 22:25:24 +0900 Subject: [PATCH] 1st --- LICENSE | 21 ++ README.md | 137 +++++++++++++ config | 16 ++ go.mod | 10 + go.sum | 57 ++++++ goScore.go | 502 ++++++++++++++++++++++++++++++++++++++++++++++ localhost-key.pem | 28 +++ localhost.pem | 24 +++ 8 files changed, 795 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 config create mode 100644 go.mod create mode 100644 go.sum create mode 100644 goScore.go create mode 100644 localhost-key.pem create mode 100644 localhost.pem diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cb97737 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2020 yasutakatou + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a62e085 --- /dev/null +++ b/README.md @@ -0,0 +1,137 @@ +# goScore + +**Simple URL's security score check tool. (implement by Golang and Chrome Extension.)**. + +# solution + +When you're search knowledge, suddenly you may see a alert by Security Scan tool.
+You have unfortunately displayed a site that contains a *malware script*.
+But you've search a lot of for learn. I don't blame you.
+
+**Can't we at least easily check if it's suspicious before we open it?**
+
+I created this tool with that in mind *for you*!
+ +# features + +When you right-click and select **context menu**, it opens a **temporary tab** before URL be opened.
+In that tab, **request Golang API** on server and will check the following.
+ +- Can name **resolve on the Secure DNS server**? +- Is SSL certificate is **not free type**? +- Is **higher rank search results** on search engines? + +Check results are displayed with a **score(star rate)**. + +# installation + +If you want to put it under the path, you can use the following. + +``` +go get github.com/yasutakatou/goScore +``` + +If you want to create a binary and copy it yourself, use the following. + +``` +git clone https://github.com/yasutakatou/goScore +cd goScore +go build goScore.go +``` + +[or download binary from release page](https://github.com/yasutakatou/goScore/releases).
+save binary file, copy to entryed execute path directory. + +# uninstall + +delete that binary. del or rm command. (it's simple!) + +# usecase + +1. prepare server + +- run server and **space or enter press** will display **ip addres and port**. + +2. setting on Chrome extension + +- input server address to chrome extension. + +- in case of success, **it will be added**. + +3. Check URL + +- in case of checking url, **right click on link, display context menu, send to server**. + +- new tab will open, waiting for making score from server. + +- **score displayed**. + +note) **if url cached, server return old result**. So, it's fast.
+ +# config file + +This tool have config file, detail is following. + +note) default config file name is **"config"**. + +## [CACHE] + +cached time. +this value format is value and unit multiplication. +unit is +"d", "D": 12 * 60 * 60 + "h", "H": 60 * 60 +"m", "M": 60 +"s", "S": 1 +example) +12 D -> 12days +30 M -> 30minuts + +[DNS] +9.9.9.9 +1.1.1.1 + +define DNS servers to resolve. + + + + + +[SEARCH] +1 + +define google page rank. +If your search results rank lower than this value, Return a star to the client. + + +[SSL] +DigiCert +GlobalSign +Google Trust Services +GeoTrust +SECOM Passport +Sectigo RSA Organization +Cybertrust + +define you trusted ssl certificate authority. + + + +[HISTORY] +https://www.google.co.jp/ 1598448280 000 + +this value is server cache. +format +url, cached unit time, score. +score "0" is star, "1" is no star. + + + +# FYI (many thanks!) + + - A simple Chrome extension that replaces your new tab page with the to-do list of the day along with your to-learn checklist
+https://github.com/PoojaB26/ToDoList-ChromeExtension + +# LICENSE + +MIT License diff --git a/config b/config new file mode 100644 index 0000000..c7b6514 --- /dev/null +++ b/config @@ -0,0 +1,16 @@ +[CACHE] +1 M +[DNS] +9.9.9.9 +1.1.1.1 +[SEARCH] +8 +[SSL] +DigiCert +GlobalSign +Google Trust Services +GeoTrust +SECOM Passport +Sectigo RSA Organization +Cybertrust +[HISTORY] diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f382f96 --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module yasutakatou/goRate + +go 1.14 + +require ( + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 + github.com/rocketlaunchr/google-search v1.0.0 + gopkg.in/ini.v1 v1.60.1 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b16b9a3 --- /dev/null +++ b/go.sum @@ -0,0 +1,57 @@ +github.com/PuerkitoBio/goquery v1.5.0 h1:uGvmFXOA73IKluu/F84Xd1tt/z07GYm8X49XKHP7EJk= +github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg= +github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o= +github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= +github.com/antchfx/htmlquery v1.0.0 h1:O5IXz8fZF3B3MW+B33MZWbTHBlYmcfw0BAxgErHuaMA= +github.com/antchfx/htmlquery v1.0.0/go.mod h1:MS9yksVSQXls00iXkiMqXr0J+umL/AmxXKuP28SUJM8= +github.com/antchfx/xmlquery v1.0.0 h1:YuEPqexGG2opZKNc9JU3Zw6zFXwC47wNcy6/F8oKsrM= +github.com/antchfx/xmlquery v1.0.0/go.mod h1:/+CnyD/DzHRnv2eRxrVbieRU/FIF6N0C+7oTtyUtCKk= +github.com/antchfx/xpath v1.0.0 h1:Q5gFgh2O40VTSwMOVbFE7nFNRBu3tS21Tn0KAWeEjtk= +github.com/antchfx/xpath v1.0.0/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gocolly/colly/v2 v2.0.1 h1:GGPzBEdrEsavhzVK00FQXMMHBHRpwrbbCCcEKM/0Evw= +github.com/gocolly/colly/v2 v2.0.1/go.mod h1:ePrRZlJcLTU2C/f8pJzXfkdBtBDHL5hOaKLcBoiJcq8= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/jawher/mow.cli v1.1.0/go.mod h1:aNaQlc7ozF3vw6IJ2dHjp2ZFiA4ozMIYY6PyuRJwlUg= +github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o= +github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 h1:lh3PyZvY+B9nFliSGTn5uFuqQQJGuNrD0MLCokv09ag= +github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rocketlaunchr/google-search v1.0.0 h1:ISYhL0OIa6NYEnJZ8dfyz83/5y1BbTgngi6aTSTONRs= +github.com/rocketlaunchr/google-search v1.0.0/go.mod h1:WQ9uwsIFP7+LkNyTLOoSBB0o70KCkUYUGUBvLzms7dw= +github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI= +github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/temoto/robotstxt v1.1.1 h1:Gh8RCs8ouX3hRSxxK7B1mO5RFByQ4CmJZDwgom++JaA= +github.com/temoto/robotstxt v1.1.1/go.mod h1:+1AmkuG3IYkh1kv0d2qEB9Le88ehNO0zwOr3ujewlOo= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +gopkg.in/ini.v1 v1.60.1 h1:P5y5shSkb0CFe44qEeMBgn8JLow09MP17jlJHanke5g= +gopkg.in/ini.v1 v1.60.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= diff --git a/goScore.go b/goScore.go new file mode 100644 index 0000000..9110a19 --- /dev/null +++ b/goScore.go @@ -0,0 +1,502 @@ +/* + * Simple URL's security score check tool. + * + * @author yasutakatou + * @copyright 2020 yasutakatou + * @license MIT License + */ +package main + +import ( + "flag" + "fmt" + "os" + "regexp" + "gopkg.in/ini.v1" + "net/http" + "strings" + "strconv" + "github.com/rocketlaunchr/google-search" + "context" + "net" + "time" + "github.com/nsf/termbox-go" + "errors" + "log" + "encoding/json" + "encoding/base64" + "math/rand" +) + +type responseData struct { + Status string `json:"status"` + Message string `json:"message"` +} + +type scoreData struct { + CACHE int64 + pCACHE string + DNS []string + SEARCH int + SSL []string +} + +type historyData struct { + URL string + TIME int64 + score string +} + +var ( + rs1Letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + Debug bool + score scoreData + history []historyData + Token string +) + +func init() { + rand.Seed(time.Now().UnixNano()) + Token = RandStr(8) +} + +func main() { + err := termbox.Init() + if err != nil { + panic(err) + } + defer termbox.Close() + termbox.Flush() + + _Debug := flag.Bool("debug", false, "[-debug=debug mode (true is enable)]") + _cert := flag.String("cert", "localhost.pem", "[-cert=ssl_certificate file path (if you don't use https, haven't to use this option)]") + _key := flag.String("key", "localhost-key.pem", "[-key=ssl_certificate_key file path (if you don't use https, haven't to use this option)]") + _port := flag.String("port", "8080", "[-port=port number]") + _config := flag.String("config", "config", "[-config=config file name]") + + flag.Parse() + + Debug = bool(*_Debug) + + loadConfig(string(*_config)) + + go func() { + http.HandleFunc("/token", startHandler) + + http.HandleFunc("/"+Token+"/api/",func(w http.ResponseWriter, r *http.Request) { + serverName,err := base64.URLEncoding.DecodeString(r.URL.Path[strings.LastIndex(r.URL.Path, "/")+1:]) + if err == nil { + if Debug == true { + fmt.Println("api call: " + r.RemoteAddr + " " + string(serverName)) + } + apiHandler(w, r, string(serverName)) + } + }) + + err := http.ListenAndServeTLS(":"+string(*_port), string(*_cert), string(*_key), nil) + if err != nil { + log.Fatal("ListenAndServeTLS: ", err) + } + }() + fmt.Println("[ Press enter or space key. Server Status display. Escape is exit.]") + startServer(string(*_port)) + + saveConfig(string(*_config)) +} + +func startHandler(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") + w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") + w.Header().Set("Content-Type", "application/json") + + if Debug == true { + fmt.Println("token call: ", r.RemoteAddr, r.URL.Path) + } + + data := &responseData{Status: "Success", Message: Token} + outputJson, err := json.Marshal(data) + if err != nil { + fmt.Println("%s") + return + } + + w.Write(outputJson) +} + +func saveConfig(filename string) bool { + if len(filename) == 0 { + return false + } + + file, err := os.Create(filename) + if err != nil { + fmt.Println(err) + return false + } + defer file.Close() + + writeFile(file, "[CACHE]") + writeFile(file, score.pCACHE) + + writeFile(file, "[DNS]") + for i := 0; i < len(score.DNS); i++ { + writeFile(file, score.DNS[i]) + } + + writeFile(file, "[SEARCH]") + writeFile(file, strconv.Itoa(score.SEARCH)) + + writeFile(file, "[SSL]") + for i := 0; i < len(score.SSL); i++ { + writeFile(file, score.SSL[i]) + } + + writeFile(file, "[HISTORY]") + for i := 0; i < len(history); i++ { + writeFile(file, history[i].URL+" "+strconv.FormatInt(history[i].TIME, 10)+" "+history[i].score) + } + + return true +} + +func writeFile(file *os.File, strs string) bool { + _, err := file.WriteString(strs + "\n") + if err != nil { + fmt.Println(err) + return false + } + return true +} + +func checkHistory(serverName string) (string) { + t := time.Now() + for i := 0; i < len(history); i++ { + if serverName == history[i].URL { + if t.Unix() < history[i].TIME { + return history[i].score + } + } + } + return "" +} + +func printStar(strs string) (string) { + buff := "" + for _, c := range strs { + if string([]rune{c}) == "0" { + buff = buff + "★" + } else { + buff = buff + "☆" + } + } + return buff +} + +func apiHandler(w http.ResponseWriter, r *http.Request, serverName string) { + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") + w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") + w.Header().Set("Content-Type", "application/json") + + scores := checkHistory(serverName) + + if len(scores) == 0 { + if matchDNS(serverName) == true { + scores = scores + "0" + } else { + scores = scores + "1" + } + + if matchSearch(serverName) == true { + scores = scores + "0" + } else { + scores = scores + "1" + } + + if matchSSL(serverName) == true { + scores = scores + "0" + } else { + scores = scores + "1" + } + + t := time.Now() + history = append(history, historyData{URL: serverName, TIME: (t.Unix() + score.CACHE), score: scores}) + } + + fmt.Println("Securescore: " + printStar(scores)) + + data := &responseData{Status: "Success", Message: scores} + outputJson, err := json.Marshal(data) + if err != nil { + fmt.Println("%s") + return + } + w.Write(outputJson) +} + + +func startServer(port string) { + termbox.SetInputMode(termbox.InputEsc) + + for { + switch ev := termbox.PollEvent(); ev.Type { + case termbox.EventKey: + switch ev.Key { + case 13, 32: //Enter, Space + _, ip, err := getIFandIP() + if err != nil { + fmt.Println(err) + } else { + fmt.Println("source ip: ", ip, " port: ", port) + } + case 27: //Escape + termbox.Flush() + return + default: + } + } + } +} + +// FYI: https://stackoverflow.com/questions/23558425/how-do-i-get-the-local-ip-address-in-go +func getIFandIP() (string, string, error) { + ifaces, err := net.Interfaces() + if err != nil { + return "", "", err + } + for _, iface := range ifaces { + if iface.Flags&net.FlagUp == 0 { + continue // interface down + } + if iface.Flags&net.FlagLoopback != 0 { + continue // loopback interface + } + addrs, err := iface.Addrs() + if err != nil { + return "", "", err + } + for _, addr := range addrs { + var ip net.IP + switch v := addr.(type) { + case *net.IPNet: + ip = v.IP + case *net.IPAddr: + ip = v.IP + } + if ip == nil || ip.IsLoopback() { + continue + } + ip = ip.To4() + if ip == nil { + continue // not an ipv4 address + } + return iface.Name, ip.String(), nil + } + } + return "", "", errors.New("are you connected to the network?") +} + +func matchDNS(url string) bool { + for i := 0; i < len(score.DNS); i++ { + if DNSLookup(score.DNS[i], cleanURL(url)) == true { + return true + } + } + return false +} + +func DNSLookup(DNSServer, url string) bool { + r := &net.Resolver{ + PreferGo: true, + Dial: func(ctx context.Context, network, address string) (net.Conn, error) { + d := net.Dialer{ + Timeout: time.Millisecond * time.Duration(10000), + } + return d.DialContext(ctx, "udp", DNSServer + ":53") + }, + } + ip, _ := r.LookupHost(context.Background(), url) + if ip != nil { + if len(ip[0]) > 6 { + if Debug == true { + fmt.Println(" -- [DNS]: " + DNSServer + " --") + fmt.Println(ip[0]) + } + return true + } + } + return false +} + + +func matchSearch(url string) bool { + ctx := context.Background() + result,err := googlesearch.Search(ctx, cleanURL(url)) + + if err != nil { + fmt.Println(err) + return false + } + + fmt.Println(" -- [SEARCH]: " + url + " --") + if Debug == true { + for i := 0; i < len(result); i++ { + fmt.Println(strconv.Itoa(result[i].Rank) + " " + result[i].URL) + } + } + + for i := 0; i < len(result); i++ { + if strings.Index(result[i].URL, url) != -1 && result[i].Rank <= score.SEARCH { + return true + } + } + return false +} + +func cleanURL(tmpStr string) (string) { + tmpStr = strings.Replace(tmpStr, "https://", "", -1) + tmpStr = strings.Replace(tmpStr, "http://", "", -1) + return strings.Split(tmpStr, "/")[0] +} + +func matchSSL(url string) bool { + if strings.Index(url, "http://") != -1 { + return false + } + + resp, err := http.Get(url) + if err != nil { + fmt.Println(err) + return false + } + defer resp.Body.Close() + + strs := fmt.Sprintf("%s",resp.TLS.PeerCertificates[0].Issuer) + if Debug == true { + fmt.Println(" -- [SSL]: " + url + " --") + fmt.Println(strs) + } + + for i := 0; i < len(score.SSL); i++ { + if strings.Index(strs, score.SSL[i]) != -1 { + return true + } + } + return false +} + +func loadConfig(filename string) { + loadOptions := ini.LoadOptions{} + loadOptions.UnparseableSections = []string{"CACHE","DNS", "SEARCH", "SSL", "HISTORY"} + + cfg, err := ini.LoadSources(loadOptions, filename) + if err != nil { + fmt.Printf("Fail to read file: %v", err) + os.Exit(1) + } + + setCache(&score.CACHE, "CACHE", cfg.Section("CACHE").Body()) + setSingleConfigStr(&score.DNS, "DNS", cfg.Section("DNS").Body()) + setSingleConfigInt(&score.SEARCH, "SEARCH", cfg.Section("SEARCH").Body()) + setSingleConfigStr(&score.SSL, "SSL", cfg.Section("SSL").Body()) + setHistorys("HISTORY", cfg.Section("HISTORY").Body()) +} + +func setCache(config *int64, configType, datas string) { + if Debug == true { + fmt.Println(" -- " + configType + " --") + } + for _, v := range regexp.MustCompile("\r\n|\n\r|\n|\r").Split(datas, -1) { + if len(v) > 0 { + tabs := strings.Split(v, " ") + count, err := strconv.Atoi(tabs[0]) + if err != nil { + return + } + unit := setUnit(tabs[1]) + if unit != 0 { + *config = int64(count) * unit + } + score.pCACHE = v + } + if Debug == true { + fmt.Println(v) + } + } +} + +func setUnit(unit string) (int64) { + switch unit { + case "d", "D": + return 12 * 60 * 60 + case "h", "H": + return 60 * 60 + case "m", "M": + return 60 + case "s", "S": + return 1 + default: + return 0 + } + return 0 +} + +func setSingleConfigInt(config *int, configType, datas string) { + if Debug == true { + fmt.Println(" -- " + configType + " --") + } + for _, v := range regexp.MustCompile("\r\n|\n\r|\n|\r").Split(datas, -1) { + if len(v) > 0 { + tmp, err := strconv.Atoi(v) + if err == nil { + *config = tmp + } + } + if Debug == true { + fmt.Println(v) + } + } +} + +func setSingleConfigStr(config *[]string, configType, datas string) { + if Debug == true { + fmt.Println(" -- " + configType + " --") + } + for _, v := range regexp.MustCompile("\r\n|\n\r|\n|\r").Split(datas, -1) { + if len(v) > 0 { + *config = append(*config, v) + } + if Debug == true { + fmt.Println(v) + } + } +} + +func setHistorys(configType, datas string) { + t := time.Now() + if Debug == true { + fmt.Println(" -- " + configType + " --") + } + for _, v := range regexp.MustCompile("\r\n|\n\r|\n|\r").Split(datas, -1) { + if len(v) > 0 { + tabs := strings.Split(v, " ") + + times, _ := strconv.ParseInt(tabs[1], 10, 64) + if t.Unix() < times { + history = append(history, historyData{URL: tabs[0], TIME: times, score: tabs[2]}) + } + } + } + if Debug == true { + fmt.Println(history) + } +} + +func RandStr(n int) string { + b := make([]rune, n) + for i := range b { + b[i] = rs1Letters[rand.Intn(len(rs1Letters))] + } + return string(b) +} diff --git a/localhost-key.pem b/localhost-key.pem new file mode 100644 index 0000000..84834ca --- /dev/null +++ b/localhost-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDiP/pOHWYju8ul +WfLSQBgfiNaXnQRcdtlQ5AE8AY0akWlrjNtvIBt9Gw0iLa/08xsMdXPiFSUwztcb +CIg7huWT0dfgMDkxfFOSD4YILSUxwWZRKpLiTtQpiWtiA6JGAcWL7QMXwdmiyvyf +2JOYXcTTr70cPjlOrjQifazdxHDdMpS6lKiEnsau96uAEfa3oY7DE7foAY7Q+c8Z +XFyCBgL8WvLBinMLzJTtqvfSi3a+O9IewsmaqzKDxgZA4zANO2XtHc1qz0qdL6KJ +fy8OtYOybe40fRojGNIkU9mzdMp9mNyhxWR0lNjijGMd8kcxhwtV5DWA+hjma1sq +dwkUO+fjAgMBAAECggEBALSY7xtVekeByw/FGf/cK6VYXDsPmgCY2eUo6xdUAac4 +dVblS++LSIX3hudGYtL7DxdF1eeci2BHawroJ56kkjMJaPFKbQzkOe04OPvj1XG+ ++AZIHpFI7S/uwmmtjuWk2mRUH4jiMvAwabDKdx5Dky6KdEDMJoB4q6LwgIFRIepd +ylGhQfHlHGu33VDf+diIzuLyiWjnXMfWe38obz6AOjlfMl3vn0xEOKmvIMO4AMGx +jNbnPm6eqiiNO/cpNSep27N0DNYS0AZyhtOeji3AWpb5Xqi1Sp89KNEpay/xYqAg +1utqqHH4cmK9+JyCacH3LwK20riDVKTC+sIpDAYAO2ECgYEA6PbeHENi8GgWYWRC +4+DcOwU5/+2wMDN0DIUV7VnI3wQO2Pjd0RHe1ojjk2BcRiLeFbcCacumJSvj0Ror +++awTzlETJ1bsZNwQF9LyBQYuK7g462H0NaS6aB6h+zAX9V+zLzEmc3NR45EfzTS +aqvniZmSkDDpyb4Y0uOI7BfG39MCgYEA+J8lJpMMx0YcP2cUxRisxhUOv8QrycKa +5h0RHcHLIBibmA7oW7RVfmU15d5OHX+w9EsJCHkO02WZOLx/rdxF09WmrTOm0uEg +udza8PZ/zTHfyMVuK/0JfNgRJOehkYnx7eR1Asm8N7df+ZZHvPxRcaBWiEg6kJq2 +bt0iyYo23bECgYBy7GXBt5R1WEPCI73DwMej7f4gvNav0JItIvIgNqybJ9tTOeHj +I1e0qa7qoxyiFM1OFQwBuM7rg21NWAXerHzJeEyzJuV3Am7bsqclupQ/dzXF23Mm +mNO8oMgRib+VBzMYOP8biKT96bbssdgje04rWTEuJJMQTNDeKBUBsvEOtQKBgQCm +3KDhd9YetGZnAzcEZWAn/aANgork+dBeWunO7+71Vq6u6mp2idzLXQBEi+QflkDc +ZLPmVOFnbgvc8V48ANd4qi8Ylc8EP4ZoV9s12CrEPBH2vNMJgOVqPdWb0D424L9X +q3oA6gaB2nf2mi8BntLGkRcill+AB+YjGBWt8C6MsQKBgQCERZNAch6RRs2Itghl +djnRlXDto8Ay2DjVnQNLKosWiCubz97CRLIUbMmPpwtU/8sl+zrpPnlEF94rYq4H +Z58Q2CiEdwZ+aqnnkknFELvY/Fp5Gxf7XBxF+yYZOJIH0uBVgwyhU7AwaT4xkt8W +nrUXIdVOiH8ixaea94R/G27YzQ== +-----END PRIVATE KEY----- diff --git a/localhost.pem b/localhost.pem new file mode 100644 index 0000000..56ec0c3 --- /dev/null +++ b/localhost.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEADCCAmigAwIBAgIRALGfNI/pWwJgrlkfiMfWCnowDQYJKoZIhvcNAQELBQAw +TTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMREwDwYDVQQLDAhyb290 +QHN2cjEYMBYGA1UEAwwPbWtjZXJ0IHJvb3RAc3ZyMB4XDTIwMDIwNzA0NTY1MFoX +DTMwMDIwNzA0NTY1MFowPDEnMCUGA1UEChMebWtjZXJ0IGRldmVsb3BtZW50IGNl +cnRpZmljYXRlMREwDwYDVQQLDAhyb290QHN2cjCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAOI/+k4dZiO7y6VZ8tJAGB+I1pedBFx22VDkATwBjRqRaWuM +228gG30bDSItr/TzGwx1c+IVJTDO1xsIiDuG5ZPR1+AwOTF8U5IPhggtJTHBZlEq +kuJO1CmJa2IDokYBxYvtAxfB2aLK/J/Yk5hdxNOvvRw+OU6uNCJ9rN3EcN0ylLqU +qISexq73q4AR9rehjsMTt+gBjtD5zxlcXIIGAvxa8sGKcwvMlO2q99KLdr470h7C +yZqrMoPGBkDjMA07Ze0dzWrPSp0vool/Lw61g7Jt7jR9GiMY0iRT2bN0yn2Y3KHF +ZHSU2OKMYx3yRzGHC1XkNYD6GOZrWyp3CRQ75+MCAwEAAaNsMGowDgYDVR0PAQH/ +BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHwYDVR0j +BBgwFoAUfZHA9SgoAj3ta6UfvMZQDqMwJqswFAYDVR0RBA0wC4IJbG9jYWxob3N0 +MA0GCSqGSIb3DQEBCwUAA4IBgQAtxUPpoyFeo02hmT54El2HG8gIZS/2WPfXaF3y +/fS1o5rC4Rt10jNelDBe/gP9Pgg3En0xKbEkRqHe1/NIy2LGryf/5GQgDuMyaU/M +E9ec9bh79+6J/s6Jmtlcbon57dlIfF1mg3H9UOpGPRv0R09gZjfk8yEnbv/5HopD +0AViDwsYvOJpknppVGqw6k/WUMA6LT2p+e6Zf0uHfl9V674FEGOCBCOgKXV5/T+d +C1HI85ZyDidK0eEcx3MrP2lVZqtJqMNal/W/OpcBahou0T+hr6IuvxxDpLVGfa3D +2Lv4HDoKRRo0pDLXEft9DFX9ukQ0hZQZtIUh/FUraw3bRXtOfkrIWkIUTjKk7mbL +xHpXZvuGE4uFiJkP1SuQftMZW4FWBsCvsvDj69bNlfA8vJDlStxArSGtgDjjRlZw +MHL/aKVxg+sq/e41Q1g7t9NDeDv1Hn2SmbUfRXrNf9BqmFxHU9bdffv1ltC6vfQX +ptKLF27Oi3HxUv2xko+OhVKz+dk= +-----END CERTIFICATE-----