diff --git a/README.md b/README.md index 6a84604..b878c37 100644 --- a/README.md +++ b/README.md @@ -44,42 +44,133 @@ The second is the format zabov calls "doublefilter" (a file in "/etc/hosts" form This is why configuration file has two separated items. -The config file should look like: +Minimal config file should look like:
{
- "zabov": {
+ "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"
+ "ipaddr":"0.0.0.0",
+ "cachettl": 1,
+ "killfilettl": 12
+ },
+ "configs":{
+ "default":{
+ "upstream":"./dns-upstream.txt",
+ "singlefilters":"./urls-domains.txt",
+ "doublefilters":"./urls-hosts.txt",
+ "blackholeip":"127.0.0.1",
+ "hostsfile":"./urls-local.txt"
+ },
}
-
}
-
-
-
-Where:
+Global zabov settings:
- 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_
+
+configs:
+- contains multiple zabov configuration dictionaries. "default" configuration name is mandatory
+- upstream: file containing all DNS we want to query : each line in format IP:PORT
- 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.
+
+Advanced configuration includes support for multiple configuration based on IP Soruce and timetables:
+
+{
+ "zabov":{
+ "port":"53",
+ "proto":"udp",
+ "ipaddr":"0.0.0.0",
+ "cachettl": 1,
+ "killfilettl": 12
+ },
+ "localresponder":{
+ "responder":"192.168.178.1:53",
+ "localdomain":"fritz.box"
+ },
+ "ipaliases":{
+ "pc8":"192.168.178.29",
+ "localhost":"127.0.0.1"
+ },
+ "ipgroups":[
+ {
+ "ips":["localhost", "::1", "192.168.178.30", "192.168.178.31", "pc8"],
+ "cfg":"",
+ "timetable":"tt_children"
+ }
+ ],
+ "timetables":{
+ "tt_children":{
+ "tables":[{"times":"00:00-05:00;8:30-12:30;18:30-22:59", "days":"Mo;Tu;We;Th;Fr;Sa;Su"}],
+ "cfgin":"children_restricted",
+ "cfgout":"default"
+ }
+ },
+ "configs":{
+ "default":{
+ "upstream":"./dns-upstream.txt",
+ "singlefilters":"./urls-domains.txt",
+ "doublefilters":"./urls-hosts.txt",
+ "blackholeip":"127.0.0.1",
+ "hostsfile":"./urls-local.txt"
+ },
+ "children":{
+ "upstream":"./dns-upstream-safe.txt",
+ "singlefilters":"./urls-domains.txt",
+ "doublefilters":"./urls-hosts.txt",
+ "blackholeip":"127.0.0.1",
+ "hostsfile":"./urls-local.txt"
+ },
+ "children_restricted":{
+ "upstream":"./dns-upstream-safe.txt",
+ "singlefilters":"./urls-domains-restricted.txt",
+ "doublefilters":"./urls-hosts-restricted.txt",
+ "blackholeip":"127.0.0.1",
+ "hostsfile":"./urls-local.txt"
+ }
+ }
+}
+
+
+localresponder:
+ - allows to set a local DNS to respond for "local" domains. A domain name is handled as "local" if dosen't contains "." (dots) or if it ends with a well known prefix, such as ".local".
+ Note: the cache is not used for local responder.
+ - responder: is the local DNS server address in the IP:PORT format.
+ - localdomain: is the suffix for local domain names. All domains ending with this prefix are resolved by local responder
+
+ipaliases: a dictionary of IPs
+ - each entry in this dictionary define a domain-alias name and his IP address. It works as replacement of /etc/hosts file.
+ - each entry is used by Zabov to resolve that names and to replace any value in the ipgroups.ips array.
+
+timetables: a dictionary of timetable dictionaries
+ - allow to define timetables in the format "time-ranges" and "days-of-week"
+ - tables: contain an array of dictionaries, each defining a time rule.
+ - each table is a dictinary containing "time" and "days" values
+ - time: is a string in the form "start:time1-stop:time1;start:time2-stop:time2..."
+ - days: is a string containing semicolon separated day names to apply the rule such as "Mo;Tu;We;Th;Fr"
+ - days names are: "Mo", "Tu" "We", "Th", "Fr", "Sa", "Su"
+ - empty value means all week-days
+ You can define complex time rules using more than one entry in this dictionay
+ - cfgin: is the name of the configuration to apply if current time is "inside" the timetable
+ - cfgout: is the name of the configuration to apply if current time is "outside" the timetable
+
+ipgroups: an array of ipgroup dictionaries
+ - let you define a set of IP addresses that shall use a configuration other than "default"
+ - ips: is an array of strings, each containing an ip address or a name defined in the "ipaliases" config branch
+ - cfg: is a string containing the name of the configuration to be used for this group; ignored if timetable is also defined
+ - timetable: is a string containing the name of the tiemtable to be aplied to this group
+
+
# DOCKER
Multistage Dockerfiles are provided for AMD64, ARMv7, ARM64V8
diff --git a/dns_handler.go b/dns_handler.go
index ed88805..c09a046 100644
--- a/dns_handler.go
+++ b/dns_handler.go
@@ -1,7 +1,6 @@
package main
import (
- "fmt"
"net"
"strings"
"time"
@@ -22,7 +21,7 @@ func getCurTime() (time.Time, error) {
func confFromTimeTable(timetable string) string {
tt := ZabovTimetables[timetable]
if tt == nil {
- fmt.Println("confFromTimeTable: return default")
+ //fmt.Println("confFromTimeTable: return default")
return "default"
}
for _, ttentry := range tt.table {
@@ -36,14 +35,14 @@ func confFromTimeTable(timetable string) string {
if (nowHour > t.start.hour || (nowHour == t.start.hour && nowMinute >= t.start.minute)) &&
(nowHour < t.stop.hour || (nowHour == t.stop.hour && nowMinute <= t.stop.minute)) {
go incrementStats("TIMETABLE IN: "+timetable, 1)
- fmt.Println("confFromTimeTable: return IN", tt.cfgin)
+ //fmt.Println("confFromTimeTable: return IN", tt.cfgin)
return tt.cfgin
}
}
}
}
go incrementStats("TIMETABLE OUT: "+timetable, 1)
- fmt.Println("confFromTimeTable: return OUT", tt.cfgout)
+ //fmt.Println("confFromTimeTable: return OUT", tt.cfgout)
return tt.cfgout
}
@@ -55,12 +54,12 @@ func confFromIP(clientIP net.IP) string {
if len(ipgroup.timetable) > 0 {
return confFromTimeTable(ipgroup.timetable)
}
- fmt.Println("confFromIP: ipgroup.cfg")
+ //fmt.Println("confFromIP: ipgroup.cfg")
return ipgroup.cfg
}
}
}
- fmt.Println("confFromIP: return default")
+ //fmt.Println("confFromIP: return default")
return "default"
}
func (mydns *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {