浏览代码

Initial commit

Signed-off-by: Antoine Tenart <antoine.tenart@ack.tf>
Antoine Tenart 6 年之前
当前提交
bb2c320b63
共有 2 个文件被更改,包括 141 次插入0 次删除
  1. 1 0
      .gitignore
  2. 140 0
      main.go

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+blacklist-zone

+ 140 - 0
main.go

@@ -0,0 +1,140 @@
+package main
+
+import (
+	"errors"
+	"io/ioutil"
+	"log"
+	"net"
+	"net/http"
+	"os"
+	"strings"
+)
+
+var (
+	zone_file = "tmp"
+
+	lists = []string{
+		"https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts",
+		"https://mirror1.malwaredomains.com/files/justdomains",
+		"http://sysctl.org/cameleon/hosts",
+		"https://zeustracker.abuse.ch/blocklist.php?download=domainblocklist",
+		"https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt",
+		"https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt",
+		"https://hosts-file.net/ad_servers.txt",
+	}
+
+	invalid = []string{
+		"localhost", "localhost.localdomain", "local", "broadcasthost",
+		"ip6-localhost", "ip6-loopback", "ip6-localnet",
+		"ip6-mcastprefix", "ip6-allnodes", "ip6-allrouters",
+		"ip6-allhosts",
+	}
+)
+
+func main() {
+	// Open the zone file, and create it if needed
+	f, err := os.OpenFile(zone_file, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer f.Close()
+
+	// Override the current content
+	if err := f.Truncate(0); err != nil {
+		log.Fatal(err)
+	}
+
+	// Fetch and parse the zone content from lists
+	c := make(chan string)
+	for _, list := range lists {
+		go handle(list, c)
+	}
+
+	// Write the zones
+	for range lists {
+		if _, err = f.WriteString(<-c); err != nil {
+			log.Fatal(err)
+		}
+	}
+}
+
+func handle(url string, zone chan string) {
+	body, err := fetch(url)
+	if err != nil {
+		return
+	}
+
+	zone <- sanitize(body)
+}
+
+func fetch(url string) (string, error) {
+	req, err := http.Get(url)
+	if err != nil {
+		return "", err
+	}
+	defer req.Body.Close()
+
+	body, err := ioutil.ReadAll(req.Body)
+	if err != nil {
+		return "", err
+	}
+
+	return string(body), nil
+}
+
+func sanitize(records string) string {
+	var sanitized []string
+
+	for _, line := range strings.Split(records, "\n") {
+		ip, domain, err := parse_record(line)
+		if err != nil {
+			continue
+		}
+
+		// Domain is invalid (e.g., "localhost")
+		if is_invalid(domain) {
+			continue
+		}
+
+		// Domain is an IP address
+		if net.ParseIP(domain) != nil {
+			continue
+		}
+
+		// Unify the records
+		if ip != "127.0.0.1" {
+			ip = "127.0.0.1"
+		}
+
+		sanitized = append(sanitized, ip + " " + domain)
+	}
+
+	return strings.Join(sanitized, "\n")
+}
+
+func parse_record(record string) (string, string, error) {
+	if len(record) == 0 {
+		return "", "", errors.New("Empty line")
+	}
+
+	if strings.HasPrefix(record, "#") {
+		return "", "", errors.New("Comment")
+	}
+
+	words := strings.Fields(record)
+	// Domain-only list
+	if len(words) == 1 {
+		return "", words[0], nil
+	}
+
+	return words[0], words[1], nil
+}
+
+func is_invalid(domain string) bool {
+	for _, i := range invalid {
+		if domain == i {
+			return true
+		}
+	}
+	return false
+}