- config:
- added new global setting "debugdbpath": if set to a directory name enables DNS queries logging in CLIENTIP-DATE.log file formatpull/1/head
							parent
							
								
									aef07c50d6
								
							
						
					
					
						commit
						0f046cf18e
					
				| 
						 | 
					@ -43,11 +43,16 @@ func init() {
 | 
				
			||||||
	ZabovPort := zabov["port"].(string)
 | 
						ZabovPort := zabov["port"].(string)
 | 
				
			||||||
	ZabovType := zabov["proto"].(string)
 | 
						ZabovType := zabov["proto"].(string)
 | 
				
			||||||
	ZabovAddr := zabov["ipaddr"].(string)
 | 
						ZabovAddr := zabov["ipaddr"].(string)
 | 
				
			||||||
	DebugStr := (zabov["debug"].(string))
 | 
					
 | 
				
			||||||
	ZabovCacheTTL = int(zabov["cachettl"].(float64))
 | 
						ZabovCacheTTL = int(zabov["cachettl"].(float64))
 | 
				
			||||||
	ZabovKillTTL = int(zabov["killfilettl"].(float64))
 | 
						ZabovKillTTL = int(zabov["killfilettl"].(float64))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ZabovDebug = DebugStr == "true"
 | 
						if zabov["debug"] != nil {
 | 
				
			||||||
 | 
							ZabovDebug = zabov["debug"].(string) == "true"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if zabov["debugdbpath"] != nil {
 | 
				
			||||||
 | 
							ZabovDebugDBPath = (zabov["debugdbpath"].(string))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if MyConf["configs"] == nil {
 | 
						if MyConf["configs"] == nil {
 | 
				
			||||||
		log.Println("configs not set: you shall set at least 'default' config")
 | 
							log.Println("configs not set: you shall set at least 'default' config")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										142
									
								
								dns_handler.go
								
								
								
								
							
							
						
						
									
										142
									
								
								dns_handler.go
								
								
								
								
							| 
						 | 
					@ -1,18 +1,139 @@
 | 
				
			||||||
package main
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/miekg/dns"
 | 
						"github.com/miekg/dns"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var reqTypes map[uint16]string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var weekdays []string
 | 
					var weekdays []string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	weekdays = []string{"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"}
 | 
						weekdays = []string{"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(ZabovDebugDBPath) > 0 {
 | 
				
			||||||
 | 
							os.MkdirAll(ZabovDebugDBPath, 0755)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reqTypes = map[uint16]string{
 | 
				
			||||||
 | 
							dns.TypeNone:       "TypeNone",
 | 
				
			||||||
 | 
							dns.TypeA:          "TypeA",
 | 
				
			||||||
 | 
							dns.TypeNS:         "TypeNS",
 | 
				
			||||||
 | 
							dns.TypeMD:         "TypeMD",
 | 
				
			||||||
 | 
							dns.TypeMF:         "TypeMF",
 | 
				
			||||||
 | 
							dns.TypeCNAME:      "TypeCNAME",
 | 
				
			||||||
 | 
							dns.TypeSOA:        "TypeSOA",
 | 
				
			||||||
 | 
							dns.TypeMB:         "TypeMB",
 | 
				
			||||||
 | 
							dns.TypeMG:         "TypeMG",
 | 
				
			||||||
 | 
							dns.TypeMR:         "TypeMR",
 | 
				
			||||||
 | 
							dns.TypeNULL:       "TypeNULL",
 | 
				
			||||||
 | 
							dns.TypePTR:        "TypePTR",
 | 
				
			||||||
 | 
							dns.TypeHINFO:      "TypeHINFO",
 | 
				
			||||||
 | 
							dns.TypeMINFO:      "TypeMINFO",
 | 
				
			||||||
 | 
							dns.TypeMX:         "TypeMX",
 | 
				
			||||||
 | 
							dns.TypeTXT:        "TypeTXT",
 | 
				
			||||||
 | 
							dns.TypeRP:         "TypeRP",
 | 
				
			||||||
 | 
							dns.TypeAFSDB:      "TypeAFSDB",
 | 
				
			||||||
 | 
							dns.TypeX25:        "TypeX25",
 | 
				
			||||||
 | 
							dns.TypeISDN:       "TypeISDN",
 | 
				
			||||||
 | 
							dns.TypeRT:         "TypeRT",
 | 
				
			||||||
 | 
							dns.TypeNSAPPTR:    "TypeNSAPPTR",
 | 
				
			||||||
 | 
							dns.TypeSIG:        "TypeSIG",
 | 
				
			||||||
 | 
							dns.TypeKEY:        "TypeKEY",
 | 
				
			||||||
 | 
							dns.TypePX:         "TypePX",
 | 
				
			||||||
 | 
							dns.TypeGPOS:       "TypeGPOS",
 | 
				
			||||||
 | 
							dns.TypeAAAA:       "TypeAAAA",
 | 
				
			||||||
 | 
							dns.TypeLOC:        "TypeLOC",
 | 
				
			||||||
 | 
							dns.TypeNXT:        "TypeNXT",
 | 
				
			||||||
 | 
							dns.TypeEID:        "TypeEID",
 | 
				
			||||||
 | 
							dns.TypeNIMLOC:     "TypeNIMLOC",
 | 
				
			||||||
 | 
							dns.TypeSRV:        "TypeSRV",
 | 
				
			||||||
 | 
							dns.TypeATMA:       "TypeATMA",
 | 
				
			||||||
 | 
							dns.TypeNAPTR:      "TypeNAPTR",
 | 
				
			||||||
 | 
							dns.TypeKX:         "TypeKX",
 | 
				
			||||||
 | 
							dns.TypeCERT:       "TypeCERT",
 | 
				
			||||||
 | 
							dns.TypeDNAME:      "TypeDNAME",
 | 
				
			||||||
 | 
							dns.TypeOPT:        "TypeOPT",
 | 
				
			||||||
 | 
							dns.TypeAPL:        "TypeAPL",
 | 
				
			||||||
 | 
							dns.TypeDS:         "TypeDS",
 | 
				
			||||||
 | 
							dns.TypeSSHFP:      "TypeSSHFP",
 | 
				
			||||||
 | 
							dns.TypeRRSIG:      "TypeRRSIG",
 | 
				
			||||||
 | 
							dns.TypeNSEC:       "TypeNSEC",
 | 
				
			||||||
 | 
							dns.TypeDNSKEY:     "TypeDNSKEY",
 | 
				
			||||||
 | 
							dns.TypeDHCID:      "TypeDHCID",
 | 
				
			||||||
 | 
							dns.TypeNSEC3:      "TypeNSEC3",
 | 
				
			||||||
 | 
							dns.TypeNSEC3PARAM: "TypeNSEC3PARAM",
 | 
				
			||||||
 | 
							dns.TypeTLSA:       "TypeTLSA",
 | 
				
			||||||
 | 
							dns.TypeSMIMEA:     "TypeSMIMEA",
 | 
				
			||||||
 | 
							dns.TypeHIP:        "TypeHIP",
 | 
				
			||||||
 | 
							dns.TypeNINFO:      "TypeNINFO",
 | 
				
			||||||
 | 
							dns.TypeRKEY:       "TypeRKEY",
 | 
				
			||||||
 | 
							dns.TypeTALINK:     "TypeTALINK",
 | 
				
			||||||
 | 
							dns.TypeCDS:        "TypeCDS",
 | 
				
			||||||
 | 
							dns.TypeCDNSKEY:    "TypeCDNSKEY",
 | 
				
			||||||
 | 
							dns.TypeOPENPGPKEY: "TypeOPENPGPKEY",
 | 
				
			||||||
 | 
							dns.TypeCSYNC:      "TypeCSYNC",
 | 
				
			||||||
 | 
							dns.TypeSPF:        "TypeSPF",
 | 
				
			||||||
 | 
							dns.TypeUINFO:      "TypeUINFO",
 | 
				
			||||||
 | 
							dns.TypeUID:        "TypeUID",
 | 
				
			||||||
 | 
							dns.TypeGID:        "TypeGID",
 | 
				
			||||||
 | 
							dns.TypeUNSPEC:     "TypeUNSPEC",
 | 
				
			||||||
 | 
							dns.TypeNID:        "TypeNID",
 | 
				
			||||||
 | 
							dns.TypeL32:        "TypeL32",
 | 
				
			||||||
 | 
							dns.TypeL64:        "TypeL64",
 | 
				
			||||||
 | 
							dns.TypeLP:         "TypeLP",
 | 
				
			||||||
 | 
							dns.TypeEUI48:      "TypeEUI48",
 | 
				
			||||||
 | 
							dns.TypeEUI64:      "TypeEUI64",
 | 
				
			||||||
 | 
							dns.TypeURI:        "TypeURI",
 | 
				
			||||||
 | 
							dns.TypeCAA:        "TypeCAA",
 | 
				
			||||||
 | 
							dns.TypeAVC:        "TypeAVC",
 | 
				
			||||||
 | 
							dns.TypeTKEY:       "TypeTKEY",
 | 
				
			||||||
 | 
							dns.TypeTSIG:       "TypeTSIG",
 | 
				
			||||||
 | 
							dns.TypeIXFR:       "TypeIXFR",
 | 
				
			||||||
 | 
							dns.TypeAXFR:       "TypeAXFR",
 | 
				
			||||||
 | 
							dns.TypeMAILB:      "TypeMAILB",
 | 
				
			||||||
 | 
							dns.TypeMAILA:      "TypeMAILA",
 | 
				
			||||||
 | 
							dns.TypeANY:        "TypeANY",
 | 
				
			||||||
 | 
							dns.TypeTA:         "TypeTA",
 | 
				
			||||||
 | 
							dns.TypeDLV:        "TypeDLV",
 | 
				
			||||||
 | 
							dns.TypeReserved:   "TypeReserved"}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func logQuery(clientIP string, name string, reqType uint16, config string, timetable string, killed string) {
 | 
				
			||||||
 | 
						if len(ZabovDebugDBPath) > 0 {
 | 
				
			||||||
 | 
							var header string
 | 
				
			||||||
 | 
							d := time.Now().Format("2006-01-02")
 | 
				
			||||||
 | 
							logpath := path.Join(ZabovDebugDBPath, strings.Replace(clientIP, ":", "_", -1)+"-"+d+".log")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							_, err1 := os.Stat(logpath)
 | 
				
			||||||
 | 
							if os.IsNotExist(err1) {
 | 
				
			||||||
 | 
								header = strings.Join([]string{"time", "clientIP", "name", "reqType", "config", "timetable", "killed"}, "\t")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							f, err := os.OpenFile(logpath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
 | 
				
			||||||
 | 
							if err == nil {
 | 
				
			||||||
 | 
								reqTypeName, err := reqTypes[reqType]
 | 
				
			||||||
 | 
								if !err {
 | 
				
			||||||
 | 
									reqTypeName = fmt.Sprintf("%d", reqType)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								ct := time.Now().Format(time.RFC3339)
 | 
				
			||||||
 | 
								log := strings.Join([]string{ct, clientIP, strings.TrimRight(name, "."), reqTypeName, config, timetable, killed}, "\t")
 | 
				
			||||||
 | 
								if len(header) > 0 {
 | 
				
			||||||
 | 
									f.Write([]byte(header))
 | 
				
			||||||
 | 
									f.Write([]byte("\n"))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								f.Write([]byte(log))
 | 
				
			||||||
 | 
								f.Write([]byte("\n"))
 | 
				
			||||||
 | 
								f.Close()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getCurTime() (time.Time, error) {
 | 
					func getCurTime() (time.Time, error) {
 | 
				
			||||||
| 
						 | 
					@ -53,25 +174,25 @@ func confFromTimeTable(timetable string) string {
 | 
				
			||||||
	return tt.cfgout
 | 
						return tt.cfgout
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func confFromIP(clientIP net.IP) string {
 | 
					func confFromIP(clientIP net.IP) (string, string) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, ipgroup := range ZabovIPGroups {
 | 
						for _, ipgroup := range ZabovIPGroups {
 | 
				
			||||||
		for _, ip := range ipgroup.ips {
 | 
							for _, ip := range ipgroup.ips {
 | 
				
			||||||
			if clientIP.Equal(ip) {
 | 
								if clientIP.Equal(ip) {
 | 
				
			||||||
				if len(ipgroup.timetable) > 0 {
 | 
									if len(ipgroup.timetable) > 0 {
 | 
				
			||||||
					return confFromTimeTable(ipgroup.timetable)
 | 
										return confFromTimeTable(ipgroup.timetable), ipgroup.timetable
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if ZabovDebug {
 | 
									if ZabovDebug {
 | 
				
			||||||
					log.Println("confFromIP: ipgroup.cfg")
 | 
										log.Println("confFromIP: ipgroup.cfg")
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return ipgroup.cfg
 | 
									return ipgroup.cfg, ""
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if ZabovDebug {
 | 
						if ZabovDebug {
 | 
				
			||||||
		log.Println("confFromIP: return default")
 | 
							log.Println("confFromIP: return default")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return "default"
 | 
						return "default", ""
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
func (mydns *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
 | 
					func (mydns *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
 | 
				
			||||||
	go incrementStats("TotalQueries", 1)
 | 
						go incrementStats("TotalQueries", 1)
 | 
				
			||||||
| 
						 | 
					@ -86,13 +207,14 @@ func (mydns *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
 | 
				
			||||||
	msg := dns.Msg{}
 | 
						msg := dns.Msg{}
 | 
				
			||||||
	msg.SetReply(r)
 | 
						msg.SetReply(r)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config := confFromIP(net.ParseIP(remIP))
 | 
						config, timetable := confFromIP(net.ParseIP(remIP))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ZabovDebug {
 | 
						if ZabovDebug {
 | 
				
			||||||
		log.Println("REQUEST:", remIP, config)
 | 
							log.Println("REQUEST:", remIP, config)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ZabovConfig := ZabovConfigs[config]
 | 
						ZabovConfig := ZabovConfigs[config]
 | 
				
			||||||
	switch r.Question[0].Qtype {
 | 
						QType := r.Question[0].Qtype
 | 
				
			||||||
 | 
						switch QType {
 | 
				
			||||||
	case dns.TypeA:
 | 
						case dns.TypeA:
 | 
				
			||||||
		msg.Authoritative = true
 | 
							msg.Authoritative = true
 | 
				
			||||||
		domain := msg.Question[0].Name
 | 
							domain := msg.Question[0].Name
 | 
				
			||||||
| 
						 | 
					@ -108,6 +230,7 @@ func (mydns *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
 | 
				
			||||||
				Hdr: dns.RR_Header{Name: domain, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60},
 | 
									Hdr: dns.RR_Header{Name: domain, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60},
 | 
				
			||||||
				A:   net.ParseIP(ZabovIPAliases[fqdn]),
 | 
									A:   net.ParseIP(ZabovIPAliases[fqdn]),
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
 | 
								go logQuery(remIP, fqdn, QType, config, timetable, "alias")
 | 
				
			||||||
			break
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if len(ZabovLocalResponder) > 0 {
 | 
							if len(ZabovLocalResponder) > 0 {
 | 
				
			||||||
| 
						 | 
					@ -116,6 +239,7 @@ func (mydns *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
 | 
				
			||||||
				config = "__localresponder__"
 | 
									config = "__localresponder__"
 | 
				
			||||||
				ret := ForwardQuery(r, config, true)
 | 
									ret := ForwardQuery(r, config, true)
 | 
				
			||||||
				w.WriteMsg(ret)
 | 
									w.WriteMsg(ret)
 | 
				
			||||||
 | 
									go logQuery(remIP, fqdn, QType, config, timetable, "localresponder")
 | 
				
			||||||
				break
 | 
									break
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -127,7 +251,9 @@ func (mydns *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
 | 
				
			||||||
				Hdr: dns.RR_Header{Name: domain, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60},
 | 
									Hdr: dns.RR_Header{Name: domain, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60},
 | 
				
			||||||
				A:   net.ParseIP(ZabovConfig.ZabovAddBL),
 | 
									A:   net.ParseIP(ZabovConfig.ZabovAddBL),
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
 | 
								go logQuery(remIP, fqdn, QType, config, timetable, "killed")
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
 | 
								go logQuery(remIP, fqdn, QType, config, timetable, "forwarded")
 | 
				
			||||||
			ret := ForwardQuery(r, config, false)
 | 
								ret := ForwardQuery(r, config, false)
 | 
				
			||||||
			w.WriteMsg(ret)
 | 
								w.WriteMsg(ret)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -142,9 +268,13 @@ func (mydns *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ret := ForwardQuery(r, config, true)
 | 
							ret := ForwardQuery(r, config, true)
 | 
				
			||||||
		w.WriteMsg(ret)
 | 
							w.WriteMsg(ret)
 | 
				
			||||||
 | 
							go logQuery(remIP, msg.Question[0].Name, QType, config, timetable, "localresponder")
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		ret := ForwardQuery(r, config, false)
 | 
							ret := ForwardQuery(r, config, false)
 | 
				
			||||||
		w.WriteMsg(ret)
 | 
							w.WriteMsg(ret)
 | 
				
			||||||
 | 
							if len(ZabovDebugDBPath) > 0 {
 | 
				
			||||||
 | 
								go logQuery(remIP, msg.Question[0].Name, QType, config, timetable, "forwarded")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	go incrementStats("CONFIG: "+config, 1)
 | 
						go incrementStats("CONFIG: "+config, 1)
 | 
				
			||||||
	w.WriteMsg(&msg)
 | 
						w.WriteMsg(&msg)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								main.go
								
								
								
								
							
							
						
						
									
										3
									
								
								main.go
								
								
								
								
							| 
						 | 
					@ -25,6 +25,9 @@ var ZabovLocalDomain string
 | 
				
			||||||
//ZabovDebug activate more logging if set to true (global)
 | 
					//ZabovDebug activate more logging if set to true (global)
 | 
				
			||||||
var ZabovDebug bool
 | 
					var ZabovDebug bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//ZabovDebugDBPath path to store debug query logs: activate logging of each single query in a csv like file (global)
 | 
				
			||||||
 | 
					var ZabovDebugDBPath string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type handler struct{}
 | 
					type handler struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ZabovConfig contains all Zabov configs
 | 
					// ZabovConfig contains all Zabov configs
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue