From e86ead83b72e1bd8c42309a76b40a015c16677f8 Mon Sep 17 00:00:00 2001 From: bloved Date: Wed, 13 Jan 2021 22:30:04 +0100 Subject: [PATCH] - config - sanity checks - parsing of timetables - removed unused global variables (moved at config level) - added new stat: DNS request for each "CONFIG" - implemented configuration from ip groups / timetables --- 01.conf.go | 85 +++++++++++++++++++++++++++++++----------------- adlist_hosts.go | 1 + adlist_single.go | 1 + config.json | 7 ++-- dns_client.go | 3 +- dns_handler.go | 62 +++++++++++++++++++++++++++++++++-- main.go | 62 +++++++++++++++-------------------- 7 files changed, 148 insertions(+), 73 deletions(-) diff --git a/01.conf.go b/01.conf.go index efdbb96..90ae23a 100644 --- a/01.conf.go +++ b/01.conf.go @@ -5,7 +5,9 @@ import ( "fmt" "io/ioutil" "log" + "net" "os" + "strconv" "strings" "github.com/miekg/dns" @@ -46,13 +48,15 @@ func init() { configs := MyConf["configs"].(map[string]interface{}) - defaultConf := configs["default"].(map[string]interface{}) + if len(configs) == 0 { + log.Println("you shall set at least default config") + os.Exit(1) + } - ZabovUpDNS = defaultConf["upstream"].(string) - ZabovSingleBL = defaultConf["singlefilters"].(string) - ZabovDoubleBL = defaultConf["doublefilters"].(string) - ZabovAddBL = defaultConf["blackholeip"].(string) - ZabovHostsFile = defaultConf["hostsfile"].(string) + if configs["default"] == nil { + log.Println("default config is required") + os.Exit(1) + } zabovString := ZabovAddr + ":" + ZabovPort @@ -60,13 +64,11 @@ func init() { MyDNS.Addr = zabovString MyDNS.Net = ZabovType - ZabovDNSArray = fileByLines(ZabovUpDNS) - ZabovConfigs = map[string]ZabovConfig{} ZabovIPGroups = []ZabovIPGroup{} - ZabovTimetables = map[string]ZabovTimetable{} + ZabovTimetables = map[string]*ZabovTimetable{} ZabovIPAliases = map[string]string{} - ZabovDNSArrays = map[string][]string{} + IPAliasesRaw := MyConf["ipaliases"].(map[string]interface{}) for alias, ip := range IPAliasesRaw { @@ -84,11 +86,8 @@ func init() { conf.ZabovAddBL = confRaw["blackholeip"].(string) conf.ZabovHostsFile = confRaw["hostsfile"].(string) - ZabovDNSArrays[name] = fileByLines(conf.ZabovUpDNS) + conf.ZabovDNSArray = fileByLines(conf.ZabovUpDNS) ZabovConfigs[name] = conf - if name == "default" { - ZabovConfigDefault = conf - } ZabovCreateKDB(name) } @@ -111,13 +110,13 @@ func init() { _, ok := ZabovConfigs[timetable.cfgin] if !ok { - log.Println("inexistent cfgin:", timetable.cfgin) + log.Println("timetable: inexistent cfgin:", timetable.cfgin) os.Exit(1) } _, ok = ZabovConfigs[timetable.cfgout] if !ok { - log.Println("inexistent cfgout:", timetable.cfgout) + log.Println("timetable: inexistent cfgout:", timetable.cfgout) os.Exit(1) } @@ -126,11 +125,36 @@ func init() { for i := range tables { table := tables[i].(map[string]interface{}) var ttEntry ZabovTimetableEntry - ttEntry.times = strings.Split(table["times"].(string), ";") - ttEntry.days = strings.Split(table["days"].(string), ";") - timetable.table = append(timetable.table, ttEntry) + ttEntry.times = []*ZabovTimeRange{} + for _, tRaw := range strings.Split(table["times"].(string), ";") { + tRawArr := strings.Split(tRaw, "-") + if len(tRawArr) > 1 { + startArr := strings.Split(tRawArr[0], ":") + stopArr := strings.Split(tRawArr[1], ":") + + if len(startArr) > 1 && len(stopArr) > 1 { + hourStart, _ := strconv.Atoi(startArr[0]) + minuteStart, _ := strconv.Atoi(startArr[1]) + start := ZabovTime{hour: hourStart, minute: minuteStart} + + hourStop, _ := strconv.Atoi(stopArr[0]) + minuteStop, _ := strconv.Atoi(stopArr[1]) + stop := ZabovTime{hour: hourStop, minute: minuteStop} + t := ZabovTimeRange{start: start, stop: stop} + ttEntry.times = append(ttEntry.times, &t) + } + } + + } + + ttEntry.days = map[string]bool{} + for _, day := range strings.Split(table["days"].(string), ";") { + ttEntry.days[day] = true + } + + timetable.table = append(timetable.table, &ttEntry) } - ZabovTimetables[name] = timetable + ZabovTimetables[name] = &timetable } IPGroups := MyConf["ipgroups"].([]interface{}) @@ -141,15 +165,16 @@ func init() { var groupStruct ZabovIPGroup groupMap := IPGroups[i].(map[string]interface{}) IPsRaw := groupMap["ips"].([]interface{}) - groupStruct.ips = []string{} + groupStruct.ips = []net.IP{} for x := range IPsRaw { - ip := IPsRaw[x].(string) - fmt.Println("adding IP ", ip) + ipRaw := IPsRaw[x].(string) + ip := net.ParseIP(ipRaw) + fmt.Println("adding IP ", ipRaw) - alias, ok := ZabovIPAliases[ip] + alias, ok := ZabovIPAliases[ipRaw] if ok { - fmt.Println("IP alias: ", ip, alias) - ip = alias + fmt.Println("IP alias: ", ipRaw, alias) + ip = net.ParseIP(alias) } groupStruct.ips = append(groupStruct.ips, ip) } @@ -164,9 +189,9 @@ func init() { } ZabovIPGroups = append(ZabovIPGroups, groupStruct) } - fmt.Println("ZabovConfigs:", ZabovConfigs) - fmt.Println("ZabovTimetables:", ZabovTimetables) - fmt.Println("ZabovIPAliases:", ZabovIPAliases) - fmt.Println("ZabovIPGroups:", ZabovIPGroups) + //fmt.Println("ZabovConfigs:", ZabovConfigs) + //fmt.Println("ZabovTimetables:", ZabovTimetables) + //fmt.Println("ZabovIPAliases:", ZabovIPAliases) + //fmt.Println("ZabovIPGroups:", ZabovIPGroups) } diff --git a/adlist_hosts.go b/adlist_hosts.go index 32dfb47..daac544 100644 --- a/adlist_hosts.go +++ b/adlist_hosts.go @@ -89,6 +89,7 @@ func getDoubleFilters(urls urlsMap) { for url, configs := range urls { DoubleIndexFilter(url, configs) } + fmt.Println("getDoubleFilters: DONE!") } diff --git a/adlist_single.go b/adlist_single.go index 9f5318f..e08af54 100644 --- a/adlist_single.go +++ b/adlist_single.go @@ -87,6 +87,7 @@ func getSingleFilters(urls urlsMap) { for url, configs := range urls { SingleIndexFilter(url, configs) } + fmt.Println("getSingleFilters: DONE!") } diff --git a/config.json b/config.json index c104a8c..cec4562 100644 --- a/config.json +++ b/config.json @@ -7,18 +7,19 @@ "killfilettl": 12 }, "ipaliases":{ - "pc8":"192.168.178.29" + "pc8":"192.168.178.29", + "localhost":"127.0.0.1" }, "ipgroups":[ { - "ips":["192.168.178.30/32", "192.168.178.31/32", "pc8"], + "ips":["localhost", "::1", "192.168.178.30", "192.168.178.31", "pc8"], "cfg":"", "timetable":"tt_children" } ], "timetables":{ "tt_children":{ - "tables":[{"times":"8:30-12:30;18:30-22:30", "days":"Mo;Tu;We;Th;Fr;Sa;Su"}], + "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":"children" } diff --git a/dns_client.go b/dns_client.go index 7ce761c..866ab32 100644 --- a/dns_client.go +++ b/dns_client.go @@ -83,8 +83,7 @@ func oneTimeDNS(config string) (dns string) { rand.Seed(time.Now().Unix()) - ZabovDNSArray := ZabovDNSArrays[config] - upl := ZabovDNSArray + upl := ZabovConfigs[config].ZabovDNSArray if len(upl) < 1 { fmt.Println("No DNS defined, using default 127.0.0.53:53. Hope it works!") diff --git a/dns_handler.go b/dns_handler.go index 9bff55d..7cfb769 100644 --- a/dns_handler.go +++ b/dns_handler.go @@ -1,12 +1,68 @@ package main import ( + "fmt" "net" "strings" + "time" "github.com/miekg/dns" ) +var weekdays []string + +func init() { + weekdays = []string{"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"} +} + +func getCurTime() (time.Time, error) { + return time.Parse("15:04", time.Now().Format("15:04")) +} + +func confFromTimeTable(timetable string) string { + tt := ZabovTimetables[timetable] + if tt == nil { + fmt.Println("confFromTimeTable: return default") + return "default" + } + for _, ttentry := range tt.table { + now := time.Now() + nowHour := now.Hour() + nowMinute := now.Minute() + weekday := weekdays[now.Weekday()] + if ttentry.days == nil || len(ttentry.days) == 0 || ttentry.days[weekday] || ttentry.days[strings.ToLower(weekday)] { + for _, t := range ttentry.times { + + 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)) { + incrementStats("TIMETABLE IN: "+timetable, 1) + fmt.Println("confFromTimeTable: return IN", tt.cfgin) + return tt.cfgin + } + } + } + } + incrementStats("TIMETABLE OUT: "+timetable, 1) + fmt.Println("confFromTimeTable: return OUT", tt.cfgout) + return tt.cfgout +} + +func confFromIP(clientIP net.IP) string { + + for _, ipgroup := range ZabovIPGroups { + for _, ip := range ipgroup.ips { + if clientIP.Equal(ip) { + if len(ipgroup.timetable) > 0 { + return confFromTimeTable(ipgroup.timetable) + } + fmt.Println("confFromIP: ipgroup.cfg") + return ipgroup.cfg + } + } + } + fmt.Println("confFromIP: return default") + return "default" +} func (mydns *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { go incrementStats("TotalQueries", 1) @@ -20,8 +76,10 @@ func (mydns *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { msg := dns.Msg{} msg.SetReply(r) - config := "default" // TODO: get config from client IP & timetable + config := confFromIP(net.ParseIP(remIP)) + incrementStats("CONFIG: "+config, 1) + ZabovConfig := ZabovConfigs[config] switch r.Question[0].Qtype { case dns.TypeA: msg.Authoritative = true @@ -33,7 +91,7 @@ func (mydns *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { 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), + A: net.ParseIP(ZabovConfig.ZabovAddBL), }) } else { ret := ForwardQuery(r, config) diff --git a/main.go b/main.go index a9178f5..e79b1de 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "log" + "net" "github.com/miekg/dns" ) @@ -9,53 +10,30 @@ import ( //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 IPdomain -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 +//ZabovCacheTTL is the amount of hours we cache records of DNS (global) var ZabovCacheTTL int -//ZabovKillTTL is the amount of hours we cache the killfile +//ZabovKillTTL is the amount of hours we cache the killfile (global) 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{} -//ZabovDNSArrays contains the arrays containing all the DNS we mention -var ZabovDNSArrays map[string][]string - // ZabovConfig contains all Zabov configs type ZabovConfig struct { - ZabovUpDNS string // json:upstream -> ZabovDNSArray - ZabovSingleBL string // json:singlefilters - ZabovDoubleBL string // json:doublefilters - ZabovAddBL string // json:blackholeip - ZabovHostsFile string // json:hostsfile + ZabovSingleBL string // json:singlefilters -> ZabovSingleBL list of urls returning a file with just names of domains + ZabovDoubleBL string // json:doublefilters -> ZabovDoubleBL list of urls returning a file with IPdomain + ZabovAddBL string // json:blackholeip -> ZabovAddBL is the IP we want to send all the clients to. Usually is 127.0.0.1 + ZabovHostsFile string // json:hostsfile -> ZabovHostsFile is the file we use to keep our hosts + ZabovUpDNS string // json:upstream -> ZabovUpDNS keeps the name of upstream DNSs + ZabovDNSArray []string // contains all the DNS we mention, parsed from ZabovUpDNS file } // ZabovConfigs contains all Zabov configs var ZabovConfigs map[string]ZabovConfig -// ZabovConfigDefault contains only "default" config -var ZabovConfigDefault ZabovConfig - // ZabovIPGroup contains Zabov groups of IPs type ZabovIPGroup struct { - ips []string // IPs in this group + ips []net.IP // IPs in this group cfg string // config name to be used if there is no timetable timetable string // timetable name to be used for this group; timetable SHALL reference to config name to use } @@ -63,21 +41,33 @@ type ZabovIPGroup struct { // ZabovIPGroups contains an array of all Zabov groups of IP rules var ZabovIPGroups []ZabovIPGroup +// ZabovTime contains Zabov single time +type ZabovTime struct { + hour int + minute int +} + +// ZabovTimeRange contains Zabov single time range +type ZabovTimeRange struct { + start ZabovTime + stop ZabovTime +} + // ZabovTimetableEntry contains Zabov single time table entry type ZabovTimetableEntry struct { - times []string - days []string + times []*ZabovTimeRange + days map[string]bool } // ZabovTimetable contains a Zabov time table type ZabovTimetable struct { - table []ZabovTimetableEntry + table []*ZabovTimetableEntry cfgin string // configuration name to be used if "inside" timetable cfgout string // configuration name to be used if "outiside" timetable } // ZabovTimetables contains all Zabov time tables, by name -var ZabovTimetables map[string]ZabovTimetable +var ZabovTimetables map[string]*ZabovTimetable // ZabovIPAliases contains an array of all Zabov IP aliases var ZabovIPAliases map[string]string