first commit

remotes/1680050961956510080/tmp_refs/heads/master 1.0.0
LowEel 2020-10-08 22:14:07 +02:00
parent 05afb0dace
commit 5c5e4e4417
685 changed files with 301506 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
zabov
killfile
killfile/*
db/zabov.db
binaries
binaries/*
build.sh
.vscode
.vscode/*

38
00.database.go Normal file
View File

@ -0,0 +1,38 @@
package main
import (
"fmt"
"os"
"github.com/syndtr/goleveldb/leveldb"
)
//MyZabovKDB is the storage where we'll put domains to block
var MyZabovKDB *leveldb.DB
//MyZabovCDB is the storage where we'll put domains to cache
var MyZabovCDB *leveldb.DB
func init() {
var err error
os.RemoveAll("./db")
os.MkdirAll("./db", 0755)
MyZabovKDB, err = leveldb.OpenFile("./db/killfile", nil)
if err != nil {
fmt.Println("Cannot create Killfile db: ", err.Error())
} else {
fmt.Println("Killfile DB created")
}
MyZabovCDB, err = leveldb.OpenFile("./db/cache", nil)
if err != nil {
fmt.Println("Cannot create Cache db: ", err.Error())
} else {
fmt.Println("Cache DB created")
}
}

26
00.memory.go Normal file
View File

@ -0,0 +1,26 @@
package main
import (
"fmt"
"runtime"
"time"
)
func init() {
fmt.Println("Garbage Collector Thread Starting")
go memoryCleanerThread()
}
func memoryCleanerThread() {
for {
time.Sleep(10 * time.Minute)
fmt.Println("Time to clean memory...")
runtime.GC()
fmt.Println("Garbage Collection done.")
}
}

69
01.conf.go Normal file
View File

@ -0,0 +1,69 @@
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"github.com/miekg/dns"
)
func init() {
//ZabovConf describes the Json we use for configuration
type ZabovConf struct {
Zabov struct {
Port string `json:"port"`
Proto string `json:"proto"`
Ipaddr string `json:"ipaddr"`
Upstream string `json:"upstream"`
Cachettl int `json:"cachettl"`
Killfilettl int `json:"killfilettl"`
Singlefilters string `json:"singlefilters"`
Doublefilters string `json:"doublefilters"`
Blackholeip string `json:"blackholeip"`
Hostsfile string `json:"hostsfile"`
} `json:"zabov"`
}
var MyConf ZabovConf
file, err := ioutil.ReadFile("config.json")
if err != nil {
log.Println("Cannot open config file", err.Error())
os.Exit(1)
}
err = json.Unmarshal([]byte(file), &MyConf)
if err != nil {
log.Println("Cannot marshal json: ", err.Error())
os.Exit(1)
}
// now we read configuration file
fmt.Println("Reading configuration file...")
ZabovPort := MyConf.Zabov.Port
ZabovType := MyConf.Zabov.Proto
ZabovAddr := MyConf.Zabov.Ipaddr
ZabovUpDNS = MyConf.Zabov.Upstream
ZabovSingleBL = MyConf.Zabov.Singlefilters
ZabovDoubleBL = MyConf.Zabov.Doublefilters
ZabovAddBL = MyConf.Zabov.Blackholeip
ZabovCacheTTL = MyConf.Zabov.Cachettl
ZabovKillTTL = MyConf.Zabov.Killfilettl
ZabovHostsFile = MyConf.Zabov.Hostsfile
zabovString := ZabovAddr + ":" + ZabovPort
MyDNS = new(dns.Server)
MyDNS.Addr = zabovString
MyDNS.Net = ZabovType
ZabovDNSArray = fileByLines(ZabovUpDNS)
}

37
01.dnscheck.go Normal file
View File

@ -0,0 +1,37 @@
package main
import (
"fmt"
"net/http"
"time"
)
//NetworkUp tells the system if the network is up or not
var NetworkUp bool
func checkNetworkUp() bool {
// RFC2606 test domain, should always work, unless internet is down.
_, err := http.Get("http://example.com")
if err != nil {
return false
}
return true
}
func checkNetworkUpThread() {
ticker := time.NewTicker(2 * time.Minute)
for range ticker.C {
NetworkUp = checkNetworkUp()
}
}
func init() {
fmt.Println("Network Checker starting....")
go checkNetworkUpThread()
}

79
01.killfile.go Normal file
View File

@ -0,0 +1,79 @@
package main
import (
"fmt"
"strings"
)
var zabovKbucket = []byte("killfile")
type killfileItem struct {
Kdomain string
Ksource string
}
var bChannel chan killfileItem
func init() {
bChannel = make(chan killfileItem, 1024)
fmt.Println("Initializing kill channel engine.")
go bWriteThread()
}
func bWriteThread() {
for item := range bChannel {
writeInKillfile(item.Kdomain, item.Ksource)
incrementStats("BL domains from "+item.Ksource, 1)
incrementStats("TOTAL", 1)
}
}
//DomainKill stores a domain name inside the killfile
func DomainKill(s, durl string) {
if len(s) > 2 {
s = strings.ToLower(s)
var k killfileItem
k.Kdomain = s
k.Ksource = durl
bChannel <- k
}
}
func writeInKillfile(key, value string) {
stK := []byte(key)
stV := []byte(value)
err := MyZabovKDB.Put(stK, stV, nil)
if err != nil {
fmt.Println("Cannot write to Killfile DB: ", err.Error())
}
}
func domainInKillfile(domain string) bool {
s := strings.ToLower(domain)
has, err := MyZabovKDB.Has([]byte(s), nil)
if err != nil {
fmt.Println("Cannot read from Killfile DB: ", err.Error())
}
return has
}

100
01.stats.go Normal file
View File

@ -0,0 +1,100 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
type send struct {
Payload string
Number int64
Operation string
}
//ZabovStats is used to keep statistics to print
var ZabovStats map[string]int64
var stats chan send
func init() {
stats = make(chan send, 1024)
ZabovStats = make(map[string]int64)
fmt.Println("Initializing stats engine.")
go reportPrintThread()
go statsThread()
}
func statsPrint() {
fmt.Println()
stat, _ := json.Marshal(ZabovStats)
fmt.Println(jsonPrettyPrint(string(stat)))
fmt.Println()
}
func incrementStats(key string, value int64) {
var s send
s.Payload = key
s.Number = value
s.Operation = "INC"
stats <- s
}
func setstatsvalue(key string, value int64) {
var s send
s.Payload = key
s.Number = value
s.Operation = "SET"
stats <- s
}
func reportPrintThread() {
for {
var s send
s.Operation = "PRI"
s.Payload = "-"
s.Number = 0
stats <- s
time.Sleep(2 * time.Minute)
}
}
func statsThread() {
fmt.Println("Starting Statistical Collection Thread")
for item := range stats {
switch item.Operation {
case "INC":
ZabovStats[item.Payload] += item.Number
case "SET":
ZabovStats[item.Payload] = item.Number
case "PRI":
statsPrint()
}
}
}
func jsonPrettyPrint(in string) string {
var out bytes.Buffer
err := json.Indent(&out, []byte(in), "", "\t")
if err != nil {
return in
}
return out.String()
}

104
02.cache.go Normal file
View File

@ -0,0 +1,104 @@
package main
import (
"bytes"
"encoding/gob"
"fmt"
"time"
"github.com/miekg/dns"
)
type cacheItem struct {
Query []byte
Date time.Time
}
//DomainCache stores a domain name inside the cache
func DomainCache(s string, resp *dns.Msg) {
var domain2cache cacheItem
var err error
var dom2 bytes.Buffer
enc := gob.NewEncoder(&dom2)
domain2cache.Query, err = resp.Pack()
if err != nil {
fmt.Println("Problems packing the response: ", err.Error())
}
domain2cache.Date = time.Now()
err = enc.Encode(domain2cache)
if err != nil {
fmt.Println("Cannot GOB the domain to cache: ", err.Error())
}
cacheDomain(s, dom2.Bytes())
}
func cacheDomain(key string, domain []byte) {
err := MyZabovCDB.Put([]byte(key), domain, nil)
if err != nil {
fmt.Println("Cannot write to Cache DB: ", err.Error())
}
}
//GetDomainFromCache stores a domain name inside the cache
func GetDomainFromCache(s string) *dns.Msg {
ret := new(dns.Msg)
var cache bytes.Buffer
dec := gob.NewDecoder(&cache)
var record cacheItem
var conf []byte
var errDB error
if domainInCache(s) == false {
return nil
}
conf, errDB = MyZabovCDB.Get([]byte(s), nil)
if errDB != nil {
fmt.Println("Cant READ DB :" , errDB.Error() )
return nil
}
cache.Write(conf)
err := dec.Decode(&record)
if err != nil {
fmt.Println("Decode error :", err.Error())
return nil
}
if time.Since(record.Date) > (time.Duration(ZabovCacheTTL) * time.Hour) {
return nil
}
err = ret.Unpack(record.Query)
if err != nil {
fmt.Println("Problem unpacking response: ", err.Error())
return nil
}
return ret
}
func domainInCache(domain string) bool {
has, err := MyZabovCDB.Has([]byte(domain), nil)
if err != nil {
fmt.Println("Cannot search Cache DB: ", err.Error())
return false
}
return has
}

18
Dockerfile.amd64 Normal file
View File

@ -0,0 +1,18 @@
FROM golang:1.14.1 AS builder
RUN apt install git -y
RUN mkdir -p /go/src/zabov
RUN git clone https://git.keinpfusch.net/loweel/zabov /go/src/zabov
WORKDIR /go/src/zabov
ENV GO111MODULE=auto
RUN go get ; go build -mod=vendor
FROM debian:latest
RUN apt update
RUN apt upgrade -y
RUN apt install ca-certificates -y
RUN mkdir -p /opt/zabov
WORKDIR /opt/zabov
COPY --from=builder /go/src/zabov /opt/zabov
EXPOSE 53/udp
ENTRYPOINT ["/opt/zabov/zabov"]

17
Dockerfile.arm32v7 Normal file
View File

@ -0,0 +1,17 @@
FROM arm32v7/golang:1.14.1 AS builder
RUN apt install git -y
RUN mkdir -p /go/src/zabov
RUN git clone https://git.keinpfusch.net/loweel/zabov /go/src/zabov
WORKDIR /go/src/zabov
ENV GO111MODULE=auto
RUN go get ; go build -mod=vendor
FROM arm32v7/debian:latest
RUN apt update
RUN apt upgrade -y
RUN apt install ca-certificates -y
RUN mkdir -p /opt/zabov
WORKDIR /opt/zabov
COPY --from=builder /go/src/zabov /opt/zabov
EXPOSE 53/udp
ENTRYPOINT ["/opt/zabov/zabov"]

17
Dockerfile.arm64v8 Normal file
View File

@ -0,0 +1,17 @@
FROM arm64v8/golang:1.14.1 AS builder
RUN apt install git -y
RUN mkdir -p /go/src/zabov
RUN git clone https://git.keinpfusch.net/loweel/zabov /go/src/zabov
WORKDIR /go/src/zabov
ENV GO111MODULE=auto
RUN go get ; go build -mod=vendor
FROM arm64v8/debian:latest
RUN apt update
RUN apt upgrade -y
RUN apt install ca-certificates -y
RUN mkdir -p /opt/zabov
WORKDIR /opt/zabov
COPY --from=builder /go/src/zabov /opt/zabov
EXPOSE 53/udp
ENTRYPOINT ["/opt/zabov/zabov"]

14
LICENSE Normal file
View File

@ -0,0 +1,14 @@
Copyright (C) 2020 loweel@keinpfusch.net
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.

91
README.md Normal file
View File

@ -0,0 +1,91 @@
# zabov
Tiny replacement for piHole DNS filter
Still Work in progress, usable.
Idea is to produce a very simple, no-web-interface , IP DNS blocker.
# INSTALL
Zabov requires golang 1.13 or later.
<pre>
git clone https://git.keinpfusch.net/Loweel/zabov.git
cd zabov
go get
go build -mod=vendor
</pre>
Then, edit config.json: please notice config.json must be in the same folder of the executable you run.
Just a few words about "singlefilters" and "doublefilters":
Data must be downloaded from URLs of blacklist mantainers.They may come in different formats.
There are two kinds of blacklists:
One is the format zabov calls "singlefilter", where we find a single column , full of domains:
<pre>
domain1.com
domain2.com
domain3.com
</pre>
The second is the format zabov calls "doublefilter" (a file in "/etc/hosts" format, to be precise), where there is an IP, usually localhost or 0.0.0.0 and then the domain:
<pre>
127.0.0.1 domain1.com
127.0.0.1 domain2.com
127.0.0.1 domain3.com
</pre>
This is why configuration file has two separated items.
The config file should look like:
<pre>
{
"zabov": {
"port":"53",
"proto":"udp",
"ipaddr":"127.0.0.1",
"upstream":"./dns-upstream.txt",
"cachettl": "4",
"killfilettl": "12",
"singlefilters":"./urls-hosts.txt" ,
"doublefilters":"./urls-domains.txt",
"blackholeip":"127.0.0.1",
"hostsfile":"./urls-local.txt"
}
}
</pre>
Where:
- port is the port number. Usually is 53, you can change for docker, if you like
- proto is the protocol. Choices are "udp", "tcp", "tcp/udp"
- ipaddr is the port to listen to. Maybe empty, (which will result in listening to 0.0.0.0) to avoid issues with docker.
- upstream: file containing all DNS we want to query : each line in format IP:PORT
- cachettl: amount of time the cache is kept (in hours)
- killfilettl: refresh time for _killfiles_
- singlefilters: name of the file for blacklists following the "singlefilter" schema.(one URL per line)
- doublefilters: name of the file, for blacklists following the "doublefilter" schema.(one URL per line)
- blackholeip: IP address to return when the IP is banned. This is because you may want to avoid MX issues, mail loops on localhost, or you have a web server running on localhost
- hostsfile: path where you keep your local blacklistfile : this is in the format "singlefilter", meaning one domain per line, unlike hosts file.
# DOCKER
Multistage Dockerfiles are provided for AMD64, ARMv7, ARM64V8
# TODO:
- ~~caching~~
- monitoring port

96
adlist_hosts.go Normal file
View File

@ -0,0 +1,96 @@
package main
import (
"bufio"
"errors"
"fmt"
"net"
"net/http"
"strings"
"time"
)
func init() {
go downloadDoubleThread()
}
//DoubleIndexFilter puts the domains inside file
func DoubleIndexFilter(durl string) error {
fmt.Println("Retrieving HostFile from: ", durl)
var err error
// Get the data
resp, err := http.Get(durl)
if err != nil {
fmt.Println("HTTP problem: ", err)
return err
}
defer resp.Body.Close()
if resp.StatusCode == 200 { // OK
fmt.Println(durl + " Response: OK")
} else {
fmt.Println("Server <"+durl+"> returned status code: ", resp.StatusCode)
return errors.New("Server <" + durl + "> returned status code: " + resp.Status)
}
scanner := bufio.NewScanner(resp.Body)
splitter := func(c rune) bool {
return c == ' ' || c == '\t'
}
var numLines int64
for scanner.Scan() {
line := scanner.Text()
h := strings.FieldsFunc(line, splitter)
if h == nil {
continue
}
if len(h) < 2 {
continue
}
if net.ParseIP(h[0]) != nil {
DomainKill(h[1], durl)
// fmt.Println("MATCH: ", h[1])
numLines++
} else {
incrementStats("Malformed HostLines "+durl, 1)
// fmt.Println("Malformed line: <" + line + ">")
}
}
fmt.Println("Finished to parse: "+durl+" ,number of lines", numLines)
return err
}
func getDoubleFilters() {
s := fileByLines(ZabovDoubleBL)
for _, a := range s {
DoubleIndexFilter(a)
}
}
func downloadDoubleThread() {
fmt.Println("Starting updater of DOUBLE lists, each (hours):", ZabovKillTTL)
for {
getDoubleFilters()
time.Sleep(time.Duration(ZabovKillTTL) * time.Hour)
}
}

93
adlist_single.go Normal file
View File

@ -0,0 +1,93 @@
package main
import (
"bufio"
"errors"
"fmt"
"net/http"
"strings"
"time"
)
func init() {
go downloadThread()
}
//SingleIndexFilter puts the domains inside file
func SingleIndexFilter(durl string) error {
fmt.Println("Retrieving DomainFile from: ", durl)
var err error
// Get the data
resp, err := http.Get(durl)
if err != nil {
fmt.Println("HTTP Problem: ", err)
return err
}
defer resp.Body.Close()
if resp.StatusCode == 200 { // OK
fmt.Println(durl + " Response: OK")
} else {
fmt.Println("Server <"+durl+"> returned status code: ", resp.StatusCode)
return errors.New("Server <" + durl + "> returned status code: " + resp.Status)
}
scanner := bufio.NewScanner(resp.Body)
splitter := func(c rune) bool {
return c == ' ' || c == '\t'
}
var numLines int64
for scanner.Scan() {
line := scanner.Text()
h := strings.FieldsFunc(line, splitter)
if h == nil {
continue
}
if len(h) < 1 {
continue
}
if !strings.Contains(h[0], "#") {
DomainKill(h[0], durl)
// fmt.Println("MATCH: ", h[1])
numLines++
} else {
incrementStats("Malformed DomainLines "+durl, 1)
// fmt.Println("Malformed line: <" + line + ">")
}
}
fmt.Println("Finished to parse: "+durl+" ,number of lines", numLines)
return err
}
func getSingleFilters() {
s := fileByLines(ZabovSingleBL)
for _, a := range s {
SingleIndexFilter(a)
}
}
func downloadThread() {
fmt.Println("Starting updater of SINGLE lists, each (hours): ", ZabovKillTTL)
for {
getSingleFilters()
time.Sleep(time.Duration(ZabovKillTTL) * time.Hour)
}
}

15
config.json Normal file
View File

@ -0,0 +1,15 @@
{
"zabov": {
"port":"53",
"proto":"udp",
"ipaddr":"0.0.0.0",
"upstream":"./dns-upstream.txt" ,
"cachettl": 1,
"killfilettl": 12,
"singlefilters":"./urls-domains.txt" ,
"doublefilters":"./urls-hosts.txt",
"blackholeip":"127.0.0.1",
"hostsfile":"./urls-local.txt"
}
}

387
dns-upstream.txt Normal file
View File

@ -0,0 +1,387 @@
194.150.168.168:53
194.25.0.68:53
141.1.1.1:53
213.239.204.35:53
194.25.0.52:53
212.211.132.4:53
213.68.194.51:53
195.243.214.4:53
141.1.27.249:53
80.237.197.14:53
217.28.98.62:53
82.96.64.2:53
82.96.65.2:53
194.25.0.60:53
193.101.111.10:53
193.101.111.20:53
192.76.144.66:53
217.69.169.25:53
85.88.19.10:53
85.88.19.11:53
85.214.20.141:53
194.169.239.10:53
194.172.160.4:53
212.102.225.2:53
212.51.16.1:53
212.51.17.1:53
212.66.129.98:53
212.89.130.180:53
213.209.122.11:53
213.23.108.129:53
91.204.4.133:53
84.200.69.80:53
62.146.63.211:53
212.77.178.83:53
78.46.58.246:53
85.214.102.25:53
87.106.62.128:53
81.20.87.84:53
81.20.87.181:53
217.5.159.227:53
185.38.9.99:53
62.146.25.130:53
37.59.218.50:53
212.184.191.193:53
213.23.143.154:53
178.32.187.10:53
62.154.214.86:53
85.214.151.164:53
5.175.225.2:53
193.105.38.142:53
145.253.183.21:53
178.15.146.43:53
62.245.233.22:53
212.224.71.71:53
213.136.78.213:53
80.156.196.196:53
193.158.99.67:53
194.95.75.230:53
212.184.191.2:53
213.138.38.22:53
195.145.80.150:53
139.18.25.34:53
79.143.180.116:53
213.240.172.200:53
217.160.238.238:53
213.61.185.238:53
84.201.0.34:53
82.194.105.219:53
62.157.89.178:53
46.189.26.123:53
85.214.208.8:53
87.239.128.130:53
78.111.65.40:53
85.214.69.126:53
109.75.29.1:53
80.81.19.226:53
81.169.162.74:53
217.14.164.35:53
5.9.172.92:53
62.225.102.180:53
217.7.71.203:53
217.6.71.61:53
62.154.138.43:53
146.0.38.140:53
78.111.67.10:53
217.6.110.20:53
87.245.18.221:53
62.225.66.19:53
81.169.212.52:53
178.162.205.123:53
212.227.83.183:53
139.18.25.33:53
193.29.2.4:53
212.91.246.11:53
62.153.141.15:53
148.251.120.228:53
62.154.253.226:53
194.25.218.2:53
194.174.73.36:53
62.245.226.182:53
87.234.222.68:53
194.25.169.130:53
62.225.15.253:53
176.94.20.4:53
188.40.115.29:53
188.40.115.22:53
194.187.240.10:53
80.150.109.197:53
217.86.149.109:53
91.208.193.1:53
195.243.99.35:53
62.225.102.177:53
178.210.102.9:53
80.228.113.125:53
178.210.102.12:53
130.255.121.9:53
212.204.56.218:53
37.59.218.151:53
80.148.52.109:53
194.30.174.222:53
5.199.141.5:53
94.135.173.22:53
88.79.208.11:53
141.16.180.9:53
82.193.241.125:53
212.8.216.37:53
109.75.29.2:53
78.46.17.82:53
81.169.185.49:53
217.244.13.14:53
93.104.209.27:53
79.143.182.174:53
81.20.82.131:53
213.136.68.181:53
213.136.68.189:53
193.107.145.233:53
195.145.241.3:53
80.242.182.182:53
193.159.181.250:53
195.243.124.75:53
62.159.104.102:53
92.222.202.244:53
85.214.254.13:53
85.114.128.115:53
145.253.176.50:53
217.7.63.1:53
78.35.40.149:53
81.169.187.253:53
94.249.192.20:53
85.214.43.157:53
80.149.83.60:53
178.210.102.225:53
178.210.102.193:53
62.154.236.126:53
213.183.185.50:53
212.60.229.242:53
80.146.192.66:53
79.133.62.62:53
178.33.33.219:53
62.245.225.225:53
46.38.235.212:53
213.136.88.31:53
212.66.135.250:53
194.231.138.26:53
62.225.1.33:53
80.148.34.131:53
94.23.163.114:53
80.64.189.94:53
81.169.241.28:53
212.38.26.132:53
62.91.19.67:53
87.239.128.25:53
212.185.196.10:53
89.221.2.171:53
217.243.239.11:53
213.136.69.214:53
213.138.56.75:53
212.122.52.11:53
46.4.166.113:53
77.37.30.12:53
194.187.242.10:53
188.40.132.212:53
194.150.168.169:53
85.25.105.193:53
185.93.180.131:53
109.234.249.10:53
109.234.248.10:53
138.201.120.250:53
81.3.27.54:53
78.46.231.161:53
78.46.231.162:53
212.51.16.197:53
212.28.34.65:53
148.251.24.48:53
212.75.32.4:53
91.103.112.150:53
217.69.169.26:53
195.63.103.144:53
213.209.121.30:53
88.79.149.4:53
185.194.143.243:53
46.182.19.48:53
217.111.24.246:53
62.96.37.74:53
213.61.64.174:53
213.61.65.226:53
62.96.190.134:53
217.111.123.166:53
213.61.176.118:53
185.216.33.82:53
185.220.70.50:53
188.138.57.95:53
195.145.137.164:53
195.167.223.164:53
195.226.69.82:53
195.37.174.194:53
195.4.138.12:53
195.63.61.189:53
212.124.35.25:53
212.184.191.100:53
212.38.2.130:53
212.51.16.193:53
212.66.129.107:53
212.8.216.41:53
212.89.128.28:53
213.133.116.14:53
213.166.247.100:53
217.243.173.82:53
217.5.182.118:53
217.7.80.40:53
217.7.81.136:53
217.9.50.199:53
46.237.220.2:53
5.189.179.105:53
52.28.79.14:53
52.29.2.17:53
62.146.202.2:53
62.146.2.48:53
62.153.122.2:53
62.153.237.200:53
62.153.237.201:53
62.154.139.99:53
62.154.159.12:53
62.154.159.5:53
62.154.160.3:53
62.209.40.75:53
62.217.61.162:53
62.245.225.55:53
78.111.224.224:53
78.111.226.226:53
78.138.80.42:53
80.149.112.139:53
80.156.6.209:53
80.190.209.218:53
80.228.231.122:53
80.228.231.48:53
80.245.65.100:53
81.14.182.169:53
81.27.162.100:53
83.97.23.178:53
83.97.23.226:53
84.16.240.43:53
85.214.98.185:53
89.19.228.52:53
89.200.168.203:53
91.217.86.4:53
93.104.195.2:53
94.247.43.254:53
109.234.248.8:53
131.220.20.199:53
131.220.23.123:53
144.76.173.169:53
144.76.83.104:53
148.251.92.241:53
176.9.136.236:53
195.10.195.195:53
173.212.249.41:53
85.214.41.155:53
54.37.75.2:53
194.55.13.75:53
5.189.138.153:53
159.69.51.18:53
51.75.77.179:53
138.201.169.84:53
138.201.239.66:53
138.68.106.109:53
145.253.109.162:53
159.69.68.181:53
167.86.78.56:53
173.212.208.116:53
173.212.218.206:53
173.212.219.129:53
173.212.239.87:53
173.212.242.89:53
173.212.244.78:53
173.249.41.233:53
173.249.48.6:53
176.9.233.171:53
176.9.58.218:53
178.162.199.27:53
178.162.208.135:53
178.238.230.127:53
178.238.235.218:53
18.195.121.224:53
185.139.98.100:53
185.40.135.11:53
185.53.169.22:53
185.90.131.194:53
188.40.239.99:53
188.68.35.145:53
192.162.85.48:53
193.159.232.5:53
194.77.237.31:53
194.77.253.32:53
195.201.192.29:53
195.202.52.30:53
195.243.101.5:53
207.180.203.42:53
207.180.243.200:53
207.180.247.212:53
213.136.71.68:53
213.136.77.39:53
213.144.24.234:53
217.147.96.210:53
217.182.198.203:53
217.6.131.248:53
217.6.247.237:53
217.6.64.5:53
217.79.177.220:53
46.163.119.155:53
46.228.199.116:53
5.175.26.208:53
51.77.65.15:53
5.189.133.151:53
5.189.141.216:53
5.189.186.154:53
5.189.186.93:53
5.189.187.34:53
5.199.141.30:53
5.45.96.220:53
62.138.20.211:53
62.144.82.252:53
62.153.165.107:53
62.153.201.91:53
62.154.214.84:53
62.157.242.85:53
79.143.177.243:53
79.143.183.45:53
80.156.198.146:53
80.156.6.206:53
80.237.207.100:53
80.82.223.94:53
81.169.215.29:53
81.169.223.126:53
81.169.230.157:53
81.20.80.79:53
83.236.183.211:53
84.16.240.224:53
85.214.224.76:53
85.214.238.190:53
85.214.246.133:53
85.214.62.160:53
85.93.91.101:53
87.106.63.208:53
87.118.126.225:53
88.198.37.146:53
88.99.66.18:53
89.163.150.209:53
89.163.220.114:53
89.19.236.152:53
93.104.213.74:53
93.186.196.137:53
93.190.71.172:53
94.177.246.221:53
80.241.218.68:53
172.105.81.90:53
172.105.81.92:53
84.200.70.40:53
94.16.114.254:53
93.90.207.192:53
93.90.201.211:53
144.91.68.146:53
176.9.37.132:53
176.9.93.198:53
176.9.1.117:53
144.91.115.47:53
91.237.100.4:53

98
dns_client.go Normal file
View File

@ -0,0 +1,98 @@
package main
import (
"fmt"
"time"
"math/rand"
"strings"
"github.com/miekg/dns"
)
//ForwardQuery forwards the query to the upstream server
//first server to answer wins
func ForwardQuery(query *dns.Msg) *dns.Msg {
go incrementStats("ForwardQueries", 1)
r := new(dns.Msg)
r.SetReply(query)
r.Authoritative = true
fqdn := strings.TrimRight(query.Question[0].Name, ".")
lfqdn := fmt.Sprintf("%d", query.Question[0].Qtype) + "." + fqdn
if cached := GetDomainFromCache(lfqdn); cached != nil {
go incrementStats("CacheHit", 1)
cached.SetReply(query)
cached.Authoritative = true
return cached
}
c := new(dns.Client)
c.ReadTimeout = 500 * time.Millisecond
c.WriteTimeout = 500 * time.Millisecond
for {
// round robin with retry
if !NetworkUp {
time.Sleep(10 * time.Second)
go incrementStats("Network Problems ", 1)
continue
}
d := oneTimeDNS()
in, _, err := c.Exchange(query, d)
if err != nil {
fmt.Printf("Problem with DNS %s : %s\n", d, err.Error())
go incrementStats("DNS Problems "+d, 1)
continue
} else {
go incrementStats(d, 1)
in.SetReply(query)
in.Authoritative = true
go DomainCache(lfqdn, in)
return in
}
}
}
func init() {
fmt.Println("DNS client engine starting")
NetworkUp = checkNetworkUp()
if NetworkUp {
fmt.Println("[OK]: Network is UP")
} else {
fmt.Println("[KO] Network is DOWN: system will check again in 2 minutes")
}
}
func oneTimeDNS() (dns string) {
rand.Seed(time.Now().Unix())
upl := ZabovDNSArray
if len(upl) < 1 {
fmt.Println("No DNS defined, using default 127.0.0.53:53. Hope it works!")
return "127.0.0.53:53"
}
n := rand.Intn(128*len(upl)) % len(upl)
dns = upl[n]
return
}

44
dns_handler.go Normal file
View File

@ -0,0 +1,44 @@
package main
import (
"net"
"strings"
"github.com/miekg/dns"
)
func (mydns *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
go incrementStats("TotalQueries", 1)
remIP, _, e := net.SplitHostPort(w.RemoteAddr().String())
if e != nil {
go incrementStats("CLIENT: "+remIP, 1)
}
msg := dns.Msg{}
msg.SetReply(r)
switch r.Question[0].Qtype {
case dns.TypeA:
msg.Authoritative = true
domain := msg.Question[0].Name
fqdn := strings.TrimRight(domain, ".")
if domainInKillfile(fqdn) {
go incrementStats("Killed", 1)
msg.Answer = append(msg.Answer, &dns.A{
Hdr: dns.RR_Header{Name: domain, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60},
A: net.ParseIP(ZabovAddBL),
})
} else {
ret := ForwardQuery(r)
w.WriteMsg(ret)
}
default:
ret := ForwardQuery(r)
w.WriteMsg(ret)
}
w.WriteMsg(&msg)
}

8
go.mod Normal file
View File

@ -0,0 +1,8 @@
module zabov
go 1.13
require (
github.com/miekg/dns v1.1.27
github.com/syndtr/goleveldb v1.0.0
)

36
go.sum Normal file
View File

@ -0,0 +1,36 @@
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/miekg/dns v1.1.27 h1:aEH/kqUzUxGJ/UHcEKdJY+ugH6WEzsEBBSPa8zuy1aM=
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

59
hostfile.go Normal file
View File

@ -0,0 +1,59 @@
package main
import (
"bufio"
"fmt"
"os"
)
func init() {
fmt.Println("Ingesting local hosts file")
ingestLocalBlacklist()
}
func ingestLocalBlacklist() {
file, err := os.Open(ZabovHostsFile)
if err != nil {
fmt.Println(err.Error())
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
d := scanner.Text()
DomainKill(d, ZabovHostsFile)
incrementStats("Blacklist", 1)
}
if err := scanner.Err(); err != nil {
fmt.Println(err.Error())
}
}
func fileByLines(filename string) (blurls []string) {
file, err := os.Open(filename)
if err != nil {
fmt.Println(err.Error())
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
d := scanner.Text()
blurls = append(blurls, d)
}
if err := scanner.Err(); err != nil {
fmt.Println(err.Error())
}
return
}

46
main.go Normal file
View File

@ -0,0 +1,46 @@
package main
import (
"log"
"github.com/miekg/dns"
)
//MyDNS is my dns server
var MyDNS *dns.Server
//ZabovUpDNS keeps the name of upstream DNSs
var ZabovUpDNS string
//ZabovSingleBL list of urls returning a file with just names of domains
var ZabovSingleBL string
//ZabovDoubleBL list of urls returning a file with IP<space>domain
var ZabovDoubleBL string
//ZabovAddBL is the IP we want to send all the clients to. Usually is 127.0.0.1
var ZabovAddBL string
//ZabovCacheTTL is the amount of hours we cache records of DNS
var ZabovCacheTTL int
//ZabovKillTTL is the amount of hours we cache the killfile
var ZabovKillTTL int
//ZabovHostsFile is the file we use to keep our hosts
var ZabovHostsFile string
//ZabovDNSArray is the array containing all the DNS we mention
var ZabovDNSArray []string
type handler struct{}
func main() {
MyDNS.Handler = &handler{}
if err := MyDNS.ListenAndServe(); err != nil {
log.Printf("Failed to set udp listener %s\n", err.Error())
} else {
log.Printf("Listener running \n")
}
}

37
urls-domains.txt Normal file
View File

@ -0,0 +1,37 @@
https://mirror1.malwaredomains.com/files/justdomains
https://raw.githubusercontent.com/hectorm/hmirror/master/data/adaway.org/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/adblock-nocoin-list/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/adguard-simplified/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/anudeepnd-adservers/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/disconnect.me-ad/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/disconnect.me-malvertising/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/disconnect.me-malware/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/disconnect.me-tracking/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/easyprivacy/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/eth-phishing-detect/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/fademind-add.2o7net/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/fademind-add.dead/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/fademind-add.risk/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/fademind-add.spam/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/kadhosts/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/malwaredomainlist.com/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/malwaredomains.com-immortaldomains/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/malwaredomains.com-justdomains/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/matomo.org-spammers/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/mitchellkrogza-badd-boyz-hosts/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/pgl.yoyo.org/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/ransomwaretracker.abuse.ch/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/someonewhocares.org/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/spam404.com/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/stevenblack/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/winhelp2002.mvps.org/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/zerodot1-coinblockerlists-browser/list.txt
https://raw.githubusercontent.com/hectorm/hmirror/master/data/zeustracker.abuse.ch/list.txt
https://raw.githubusercontent.com/CHEF-KOCH/Audio-fingerprint-pages/master/AudioFp.txt
https://raw.githubusercontent.com/CHEF-KOCH/Canvas-fingerprinting-pages/master/Canvas.txt
https://raw.githubusercontent.com/CHEF-KOCH/WebRTC-tracking/master/WebRTC.txt
https://raw.githubusercontent.com/CHEF-KOCH/CKs-FilterList/master/Anti-Corp/hosts/NSABlocklist.txt
https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-blocklist.txt
https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-malware.txt
https://www.stopforumspam.com/downloads/toxic_domains_whole.txt

12
urls-hosts.txt Normal file
View File

@ -0,0 +1,12 @@
http://sysctl.org/cameleon/hosts
https://www.malwaredomainlist.com/hostslist/hosts.txt
https://adaway.org/hosts.txt
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/fakenews/hosts
https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/gambling/hosts
https://someonewhocares.org/hosts/hosts
https://getadhell.com/standard-package.txt
https://raw.githubusercontent.com/hoshsadiq/adblock-nocoin-list/master/hosts.txt
https://raw.githubusercontent.com/notracking/hosts-blocklists/master/hostnames.txt
https://raw.githubusercontent.com/anudeepND/blacklist/master/adservers.txt
https://raw.githubusercontent.com/anudeepND/blacklist/master/facebook.txt

8
urls-local.txt Normal file
View File

@ -0,0 +1,8 @@
blc.vodafone.com
gab.com
gab.ai
freespeechextremist.com
neckbeard.xyz
funkwhale.it
social.byoblu.com

16
vendor/github.com/golang/snappy/.gitignore generated vendored Normal file
View File

@ -0,0 +1,16 @@
cmd/snappytool/snappytool
testdata/bench
# These explicitly listed benchmark data files are for an obsolete version of
# snappy_test.go.
testdata/alice29.txt
testdata/asyoulik.txt
testdata/fireworks.jpeg
testdata/geo.protodata
testdata/html
testdata/html_x_4
testdata/kppkn.gtb
testdata/lcet10.txt
testdata/paper-100k.pdf
testdata/plrabn12.txt
testdata/urls.10K

15
vendor/github.com/golang/snappy/AUTHORS generated vendored Normal file
View File

@ -0,0 +1,15 @@
# This is the official list of Snappy-Go authors for copyright purposes.
# This file is distinct from the CONTRIBUTORS files.
# See the latter for an explanation.
# Names should be added to this file as
# Name or Organization <email address>
# The email address is not required for organizations.
# Please keep the list sorted.
Damian Gryski <dgryski@gmail.com>
Google Inc.
Jan Mercl <0xjnml@gmail.com>
Rodolfo Carvalho <rhcarvalho@gmail.com>
Sebastien Binet <seb.binet@gmail.com>