package main import ( "context" "flag" "fmt" "log" "net/http" "regexp" "strings" "time" "github.com/adamveld12/gopherhole/internal" "github.com/miekg/dns" ) var ( configFilePath = flag.String("config", "./config.json", "Config file") // dbPath = flag.String("db-path", ".", "Directory to write database files to") // httpAddr = flag.String("http-address", ":8080", "Bind address for http server") // dnsAddr = flag.String("dns-address", ":53", "Bind address for dns server") ) func main() { flag.Parse() var conf StartupConfig if err := LoadStartupConfig(&conf, *configFilePath); err != nil { log.Fatalf("%+v", err) } // conf.HTTPAddr = *httpAddr // conf.DNSAddr = *dnsAddr log.Printf("%+v", conf) store := &internal.Sqlite{ Path: conf.DatabaseURL, } if err := store.Open(); err != nil { log.Fatalf("COULD NOT OPEN SQLITE DB: %v", err) } re := &internal.RuleEngine{ Rules: conf.Rules, } cache := &internal.Memory{} dnsClient := &dns.Client{ Net: "udp", DialTimeout: time.Millisecond * 250, ReadTimeout: time.Second, WriteTimeout: time.Second, } dm := &internal.DomainManager{ Cache: cache, Storage: store, RuleEvaluator: re, Recursors: internal.Recursor{ Upstreams: cleanRecursors(conf.Recursors), Client: dnsClient, }, } go func() { dnsSrv := &internal.DNSServer{Handler: dm} if err := dnsSrv.ListenAndServe(context.Background(), conf.DNSAddr); err != nil { log.Fatal(err) } }() httpApi := internal.NewAdminHandler(cache, store, re) if err := http.ListenAndServe(conf.HTTPAddr, httpApi); err != nil { log.Fatal(err) } } func cleanRecursors(recursors []string) []string { cr := []string{} reg := regexp.MustCompile(`^((?:\d{1,4}\.?){4})(?::(\d{0,5}))?`) for _, r := range recursors { if !reg.MatchString(r) { log.Fatalf("%s is not a valid DNS server. Must be in ip:addr format.", r) } cleanedIPAddr := r if !strings.Contains(r, ":") { cleanedIPAddr = fmt.Sprintf("%s:53", r) } cr = append(cr, cleanedIPAddr) } log.Println(cr) return cr }