func TestListenAndServe(t *testing.T) { t.Parallel() t.Skip() s, err := dnsp.NewServer(dnsp.Options{ Bind: ":0", }) if err != nil { t.Errorf("%T %#v", err, err) t.Fatal(err) } done := make(chan struct{}) go func() { if err := s.Shutdown(); err != nil { t.Error(err) } done <- struct{}{} }() if err = s.ListenAndServe(); err != nil { t.Fatal(err) } <-done // waint until the above goroutine finishes }
func TestIsAllowedBlack(t *testing.T) { t.Parallel() tmp, err := ioutil.TempFile("", "") if err != nil { t.Fatal(err) } defer os.Remove(tmp.Name()) tmp.Write([]byte("*.xxx\n")) tmp.Write([]byte("*.sex\n")) tmp.Write([]byte("doubleclick.net\n")) tmp.Write([]byte("p**n.com\n")) s, err := dnsp.NewServer(dnsp.Options{ Blacklist: tmp.Name(), }) if err != nil { t.Fatal(err) } for host, ok := range map[string]bool{ "bar.spam.xxx.": false, "doubleclick.net.": false, "example.com.": true, "foo.sex.": false, "github.com.": true, "google.com.": true, "p**n.com.": false, } { if act := s.IsAllowed(host); ok != act { t.Errorf("expected s.IsAllowed(%q) to be %v, got %v", host, ok, act) } } }
func TestIsAllowedWhite(t *testing.T) { t.Parallel() tmp, err := ioutil.TempFile("", "") if err != nil { t.Fatal(err) } defer os.Remove(tmp.Name()) tmp.Write([]byte("*.wikipedia.org\n")) tmp.Write([]byte("github.com\n")) tmp.Write([]byte("google.com\n")) s, err := dnsp.NewServer(dnsp.Options{ Whitelist: tmp.Name(), }) if err != nil { t.Fatal(err) } for host, ok := range map[string]bool{ "blocked.net.": false, "en.wikipedia.org.": true, "example.com.": false, "github.com.": true, "google.com.": true, "hu.wikipedia.org.": true, "wikipedia.org": false, } { if act := s.IsAllowed(host); ok != act { t.Errorf("expected s.IsAllowed(%q) to be %v, got %v", host, ok, act) } } }
func TestInvalidOptions(t *testing.T) { t.Parallel() s, err := dnsp.NewServer(dnsp.Options{ Poll: -time.Second, // negative poll }) if err == nil { t.Error("expected an error, got nil") } if s != nil { t.Errorf("expected nil, got %+v", s) } }
func Example() { // Create a server that listens on :1053, on all interfaces. // DNS queries will be proxied to Google's public nameservers. s, err := dnsp.NewServer(dnsp.Options{ Bind: ":1053", Resolve: []string{"8.8.4.4", "8.8.8.8"}, // Block hosts listed in a community-managed file: Blacklist: "http://hosts-file.net/download/hosts.txt", }) if err != nil { log.Fatal(err) } // Remember to close it: defer s.Shutdown() // Start accepting DNS queries: if err := s.ListenAndServe(); err != nil { log.Fatal(err) } }
func main() { app := cli.NewApp() app.Name = "dnsp" app.Usage = "DNS proxy with whitelist/blacklist support" app.Version = "0.9.2" app.Author, app.Email = "", "" app.Flags = []cli.Flag{ cli.StringFlag{ Name: "net, n", Value: "udp", Usage: "listen protocol (‘tcp’ or ‘udp’)", EnvVar: "DNSP_NET", }, cli.StringFlag{ Name: "listen, l", Value: ":dns", Usage: "listen address (host:port, host or :port)", EnvVar: "DNSP_BIND", }, cli.StringFlag{ Name: "resolve, r", Value: DefaultResolve, Usage: "comma-separated list of name servers (host:port or host)", EnvVar: "DNSP_SERVER", }, cli.StringFlag{ Name: "whitelist, w", Usage: "URL or path to file containing whitelisted hosts", EnvVar: "DNSP_WHITELIST", }, cli.StringFlag{ Name: "blacklist, b", Usage: "URL or path to file containing blacklisted hosts", EnvVar: "DNSP_BLACKLIST", }, cli.DurationFlag{ Name: "poll, p", Usage: "poll the whitelist or blacklist for updates", EnvVar: "DNSP_POLL", }, cli.StringFlag{ Name: "http, t", Usage: "start a web-based UI on the given address (host:port, host or port)", EnvVar: "DNSP_HTTP", }, } app.Action = func(c *cli.Context) { resolve := []string{} if res := c.String("resolve"); res != "false" && res != "" { resolve = strings.Split(res, ",") } o := &dnsp.Options{ Net: c.String("net"), Bind: c.String("listen"), Resolve: resolve, Poll: c.Duration("poll"), Whitelist: c.String("whitelist"), Blacklist: c.String("blacklist"), } s, err := dnsp.NewServer(*o) if err != nil { log.Fatalf("dnsp: %s", err) } if bind := c.String("http"); bind != "" { log.Printf("dnsp: starting web interface on %s", bind) go dnsp.RunHTTPServer(bind, s) } catch(func(sig os.Signal) int { os.Stderr.Write([]byte{'\r'}) log.Printf("dnsp: shutting down") s.Shutdown() return 0 }, syscall.SIGINT, syscall.SIGTERM) defer s.Shutdown() // in case of normal exit if len(o.Resolve) == 0 { log.Printf("dnsp: listening on %s", o.Bind) } else { log.Printf("dnsp: listening on %s, proxying to %s", o.Bind, o.Resolve) } if err := s.ListenAndServe(); err != nil { log.Fatalf("dnsp: %s", err) } } app.Run(os.Args) }