func TestProtocolHandler(t *testing.T) { var ( answers = rand.Intn(12) + 3 want = answers / 2 testHandler = dns.HandlerFunc(func(w dns.ResponseWriter, r *dns.Msg) { res := &dns.Msg{} for i := 0; i < answers; i++ { rr := &dns.A{ Hdr: dns.RR_Header{ Name: r.Question[0].Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 5, }, A: net.ParseIP(fmt.Sprintf("1.2.3.%d", i)), } res.Answer = append(res.Answer, rr) } err := w.WriteMsg(res) if err != nil { t.Fatalf("write response failed: %s", err) } }) ) w := &testWriter{ remoteAddr: &net.UDPAddr{}, } m := &dns.Msg{} m.SetQuestion(dns.Fqdn("app.glimpse.io"), dns.TypeA) protocolHandler(want, testHandler).ServeDNS(w, m) if have := len(w.msg.Answer); want != have { t.Errorf("want %d answers, have %d", want, have) } e := &errorWriter{w} errorHandler := dns.HandlerFunc(func(w dns.ResponseWriter, req *dns.Msg) { err := w.WriteMsg(&dns.Msg{}) if err == nil { t.Fatalf("want WriteMsg() to fail with errorWriter") } }) m = &dns.Msg{} m.SetQuestion(dns.Fqdn("app.glimpse.io"), dns.TypeA) protocolHandler(42, errorHandler).ServeDNS(e, m) }
func (s *Server) systemdServe() { // We will usually have at least one TCP socket and one UDP socket. // PacketConns are UDP sockets, Listeners are TCP sockets. // To make things more annoying, both can (and usually will) have nil // entries for the file descriptors that don't match. pconns, err := activation.PacketConns(false) if err != nil { glog.Fatalf("Error getting systemd packet conns: %v", err) } listeners, err := activation.Listeners(false) if err != nil { glog.Fatalf("Error getting systemd listeners: %v", err) } var wg sync.WaitGroup for _, pconn := range pconns { if pconn == nil { continue } wg.Add(1) go func(c net.PacketConn) { defer wg.Done() glog.Infof("Activate on packet connection (UDP)") err := dns.ActivateAndServe(nil, c, dns.HandlerFunc(s.Handler)) glog.Fatalf("Exiting UDP listener: %v", err) }(pconn) } for _, lis := range listeners { if lis == nil { continue } wg.Add(1) go func(l net.Listener) { defer wg.Done() glog.Infof("Activate on listening socket (TCP)") err := dns.ActivateAndServe(l, nil, dns.HandlerFunc(s.Handler)) glog.Fatalf("Exiting TCP listener: %v", err) }(lis) } wg.Wait() // We should only get here if there were no useful sockets. glog.Fatalf("No systemd sockets, did you forget the .socket?") }
func TestDNSLoggingHandlerError(t *testing.T) { var ( b = &bytes.Buffer{} l = log.New(b, "glimpse-agent ", log.Lmicroseconds) m = &dns.Msg{} e = &errorWriter{ &testWriter{ remoteAddr: &net.UDPAddr{}, }, } errorHandler = dns.HandlerFunc(func(w dns.ResponseWriter, req *dns.Msg) { err := w.WriteMsg(&dns.Msg{}) if err == nil { t.Fatalf("want WriteMsg() to fail with errorWriter") } }) ) m.SetQuestion(dns.Fqdn("app.glimpse.io"), dns.TypeA) dnsLoggingHandler(l, errorHandler).ServeDNS(e, m) sp := strings.SplitN(strings.Trim(b.String(), "\n"), " ", 10) if want, have := "error: failed write", sp[9]; want != have { t.Errorf("want %#v, have %#v", want, have) } }
func (c *MDNSClient) Start(ifi *net.Interface) (err error) { if c.running { return nil } if c.conn, err = net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: 0}); err != nil { return err } multicast, err := LinkLocalMulticastListener(ifi) if err != nil { return err } handleMDNS := func(w dns.ResponseWriter, r *dns.Msg) { // Don't want to handle queries here, so filter anything out that isn't a response if len(r.Answer) > 0 { c.ResponseCallback(r) } } c.listener = &dns.Server{Unsafe: true, PacketConn: multicast, Handler: dns.HandlerFunc(handleMDNS)} go c.listener.ActivateAndServe() actionChan := make(chan MDNSAction, MailboxSize) c.actionChan = actionChan go c.actorLoop(actionChan) return nil }
func TestDNSLoggingHandler(t *testing.T) { var ( b = &bytes.Buffer{} l = log.New(b, "glimpse-agent ", log.Lmicroseconds) fqdn = dns.Fqdn("db.glimpse.io") w = &testWriter{ remoteAddr: &net.UDPAddr{ IP: net.ParseIP("8.7.6.5"), Port: 4321, }, } testHandler = dns.HandlerFunc(func(w dns.ResponseWriter, req *dns.Msg) { res := &dns.Msg{} res.SetReply(req) res.SetRcode(req, dns.RcodeNotImplemented) err := w.WriteMsg(res) if err != nil { t.Fatalf("write response failed: %s", err) } }) ) m := &dns.Msg{} m.SetQuestion(fqdn, dns.TypeA) dnsLoggingHandler(l, testHandler).ServeDNS(w, m) sp := strings.SplitN(strings.Trim(b.String(), "\n"), " ", 10) if want, have := 9, len(sp); want != have { t.Fatalf("want %d fields, have %d fields", want, have) } if want, have := "DNS", sp[2]; want != have { t.Errorf("want %s, have %s", want, have) } if want, have := "8.7.6.5:4321", sp[4]; want != have { t.Errorf("want %s, have %s", want, have) } if want, have := "A", sp[5]; want != have { t.Errorf("want %s, have %s", want, have) } if want, have := fqdn, sp[6]; want != have { t.Errorf("want %s, have %s", want, have) } if want, have := dns.RcodeToString[dns.RcodeNotImplemented], sp[7]; want != have { t.Errorf("want %s, have %s", want, have) } if want, have := "0", sp[8]; want != have { t.Errorf("want %s, have %s", want, have) } }
func main() { var listenports, ipranges StringList var remote = flag.Bool("remote", false, "Run as the remote-end of the tunnel.") var dnsaddr = flag.String("dns-addr", ":53", "Listen address for local DNS server.") flag.Var(&ipranges, "iprange", "The IP address range to use for the proxy pool. Acceptable "+ "values are CIDR-style network addresses & single IP addresses. Can be set multiple "+ "times for multiple ranges.") flag.Var(&listenports, "port", "TCP port to proxy. Can be set multiple times for multiple "+ "ports.") flag.StringVar(&tunneladdr, "tunnel-addr", "", "Address for the remote-end of the tunnel.") flag.StringVar(&dnsserver, "upstream-dns-server", "8.8.8.8:53", "DNS server to rely our "+ "incoming requests to.") flag.Parse() if *remote { log.Fatal(listenAndTunnel(tunneladdr)) } addrpool.pool.OnEvicted = func(key lru.Key, value interface{}) { log.Printf("Evicting %s -> %v", uint32toip4(key.(uint32)), value.(string)) addrpool.freeaddr = uint32toip4(key.(uint32)) delete(addrpool.domains, value.(string)) } // We pass IPs onto this channel as we parse them. ipchan := make(chan uint32) go func() { for ip := range ipchan { log.Printf("Adding %v", uint32toip4(ip)) addrpool.pool.Add(ip, "--invalid--") for _, port := range listenports { go listenAndProxy(uint32toip4(ip).String() + ":" + port) } } }() for _, r := range ipranges { if err := parseCIDR(r, ipchan); err == nil { continue } if err := parseIP(r, ipchan); err == nil { continue } // TODO nmap-style octet addressing ip-range parsing. log.Fatalf("Couldn't parse address range %v", r) } close(ipchan) server := &dns.Server{ Addr: *dnsaddr, Net: "udp", Handler: dns.HandlerFunc(resolver), } log.Fatal(server.ListenAndServe()) }
// NewServer creates a new Server with the given options. func NewServer(o Options) (*Server, error) { if err := o.validate(); err != nil { return nil, err } s := Server{ c: &dns.Client{}, s: &dns.Server{ Net: o.Net, Addr: o.Bind, }, white: o.Whitelist != "", hosts: hosts{}, hostsRX: hostsRX{}, privateHosts: map[string]struct{}{}, privateHostsRX: map[string]*regexp.Regexp{}, } hostListPath := o.Whitelist if hostListPath == "" { hostListPath = o.Blacklist } s.hostsFile.path = hostListPath if err := s.loadHostEntries(); err != nil { return nil, err } if o.Poll != 0 { go s.monitorHostEntries(o.Poll) } s.s.Handler = dns.HandlerFunc(func(w dns.ResponseWriter, r *dns.Msg) { // If no upstream proxy is present, drop the query: if len(o.Resolve) == 0 { dns.HandleFailed(w, r) return } // Filter Questions: if r.Question = s.filter(r.Question); len(r.Question) == 0 { w.WriteMsg(r) return } // Proxy Query: for _, addr := range o.Resolve { in, _, err := s.c.Exchange(r, addr) if err != nil { continue } w.WriteMsg(in) return } dns.HandleFailed(w, r) }) return &s, nil }
func (d *DNS) ListenAndServe() error { udpErr := make(chan error) tcpErr := make(chan error) go func() { udpErr <- dns.ListenAndServe(d.Config.Bind, "udp", dns.HandlerFunc(d.handler)) }() go func() { tcpErr <- dns.ListenAndServe(d.Config.Bind, "tcp", dns.HandlerFunc(d.handler)) }() select { case err := <-udpErr: return err case err := <-tcpErr: return err } return nil }
func TestDnsMetricsHandler(t *testing.T) { testHandler := dns.HandlerFunc(func(w dns.ResponseWriter, req *dns.Msg) { res := &dns.Msg{} res.SetReply(req) res.SetRcode(req, dns.RcodeNotImplemented) err := w.WriteMsg(res) if err != nil { t.Fatalf("write response failed: %s", err) } }) w := &testWriter{ remoteAddr: &net.UDPAddr{}, } m := &dns.Msg{} m.SetQuestion(dns.Fqdn("app.glimpse.io"), dns.TypeA) dnsMetricsHandler(testHandler).ServeDNS(w, m) r := w.msg if want, have := dns.RcodeNotImplemented, r.Rcode; want != have { t.Errorf( "want rcode %s, have %s", dns.RcodeToString[want], dns.RcodeToString[have], ) } e := &errorWriter{w} errorHandler := dns.HandlerFunc(func(w dns.ResponseWriter, req *dns.Msg) { err := w.WriteMsg(&dns.Msg{}) if err == nil { t.Fatalf("want WriteMsg() to fail with errorWriter") } }) m = &dns.Msg{} m.SetQuestion(dns.Fqdn("app.glimpse.io"), dns.TypeA) dnsMetricsHandler(errorHandler).ServeDNS(e, m) }
func NewServer() Server { server := Server{ records: make(map[string][]miekgdns.RR), truncatedDomainNames: make(map[string]bool), } server.udpServer = &miekgdns.Server{ Addr: ":53", Net: "udp", Handler: miekgdns.HandlerFunc(server.handleUDPDNSRequest), } server.tcpServer = &miekgdns.Server{ Addr: ":53", Net: "tcp", Handler: miekgdns.HandlerFunc(server.handleTCPDNSRequest), } return server }
func initDNS() { if GConf.LocalDNS.CacheSize > 0 { dnsCache, _ = lru.New(GConf.LocalDNS.CacheSize) } if len(GConf.LocalDNS.Listen) > 0 { err := dns.ListenAndServe(GConf.LocalDNS.Listen, "udp", dns.HandlerFunc(proxyDNS)) if nil != err { log.Printf("Failed to start dns server:%v", err) } } }
func (s *Server) classicServe() { glog.Infof("DNS listening on %s", s.Addr) var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() err := dns.ListenAndServe(s.Addr, "udp", dns.HandlerFunc(s.Handler)) glog.Fatalf("Exiting UDP: %v", err) }() wg.Add(1) go func() { defer wg.Done() err := dns.ListenAndServe(s.Addr, "tcp", dns.HandlerFunc(s.Handler)) glog.Fatalf("Exiting TCP: %v", err) }() wg.Wait() }
func dnsDispatch() { udpConn, err := net.ListenUDP("udp", dnsThis) if err != nil { kilog.Critical("%v", err.Error()) os.Exit(-1) } // hack to make Windows happy nameToIP["dns.msftncsi.com."] = "131.107.255.255" dns.ActivateAndServe(nil, udpConn, dns.HandlerFunc(dnsHandle)) }
func RunLocalMulticastServer() (*dns.Server, error) { multicast, err := LinkLocalMulticastListener(nil) if err != nil { return nil, err } server := &dns.Server{ PacketConn: multicast, Handler: dns.HandlerFunc(minimalServer), ReadTimeout: 100 * time.Millisecond} go server.ActivateAndServe() return server, nil }
func (s HelixServer) Start() { server := &dns.Server{ Addr: ":" + strconv.Itoa(s.Port), Net: "udp", Handler: dns.HandlerFunc(s.Handler), ReadTimeout: 10, WriteTimeout: 10, } log.Print("Starting server...") server.ListenAndServe() }
// TvproxySrv is the main exported method to run the dns server // It will forward requests we're not interested in, otherwise it'll // intercept for us and return the external address of this server as // specified in the config func TvproxySrv(port string) { pc, err := net.ListenPacket("udp", port) if err != nil { fmt.Printf("Cannot listen on address %s", port) return } fmt.Printf("Starting server on %s\n", port) srv := &dns.Server{Addr: port, Net: "udp", PacketConn: pc, Handler: dns.HandlerFunc(interceptRequest)} defer srv.Shutdown() // periodically update the cache //go refreshCache() // start the dns server. Ctrl + C (etc) to kill srv.ActivateAndServe() }
func (s *dnsServer) ListenAndServe() { var err error s.answerRR, err = dns.NewRR("test.blah A 1.2.3.4") if err != nil { panic(err) } s.srv = &dns.Server{ Addr: s.Addr, Net: "udp", Handler: dns.HandlerFunc(s.Handler), } err = s.srv.ListenAndServe() if err != nil { panic(err) } }
func main() { var addr = flag.String("addr", "127.0.0.1:5300", "listen address") var ip = flag.String("ip", "127.0.0.1", "resolve ipv4 address") flag.Parse() resolveIP = net.ParseIP(*ip) if resolveIP == nil { log.Fatalf("Invalid ip address: %s\n", *ip) } if resolveIP.To4() == nil { log.Fatalf("Invalid ipv4 address: %s\n", *ip) } server := &dns.Server{Addr: *addr, Net: "udp"} server.Handler = dns.HandlerFunc(handleRequest) log.Printf("Listening on %s, resolving to %s\n", *addr, *ip) log.Fatal(server.ListenAndServe()) }
func startUpstreamTestServer(c *C) (string, string, func()) { h := dns.HandlerFunc(func(w dns.ResponseWriter, req *dns.Msg) { res := &dns.Msg{} res.SetReply(req) switch req.Question[0].Name { case "long-compressed-response.": for i := 0; i < 25; i++ { res.Answer = append(res.Answer, &dns.A{ Hdr: dns.RR_Header{ Name: req.Question[0].Name, Rrtype: dns.TypeA, Class: dns.ClassINET, }, A: net.IP{192, 168, 0, byte(i)}, }) } if res.Len() <= 512 { panic("not huge") } res.Compress = true if res.Len() > 512 { panic("too big compressed") } w.WriteMsg(res) } }) up := make(chan struct{}, 2) notifyStart := func() { up <- struct{}{} } udpListener, err := net.ListenPacket("udp4", "127.0.0.1:0") c.Assert(err, IsNil) udp := &dns.Server{ Net: "udp", PacketConn: udpListener, Handler: h, NotifyStartedFunc: notifyStart, } go udp.ActivateAndServe() tcpListener, err := net.Listen("tcp4", "127.0.0.1:0") c.Assert(err, IsNil) tcp := &dns.Server{ Net: "tcp", Listener: tcpListener, Handler: h, NotifyStartedFunc: notifyStart, } go tcp.ActivateAndServe() for i := 0; i < 2; i++ { select { case <-up: case <-time.After(5 * time.Second): c.Fatal("timed out waiting for server to start") } } return udpListener.(*net.UDPConn).LocalAddr().String(), tcpListener.Addr().String(), func() { udp.Shutdown() tcp.Shutdown() } }
func main() { l := lever.New("struggledns", nil) l.Add(lever.Param{ Name: "--listen-addr", Description: "Address to listen on for dns requests. Will bind to both tcp and udp", Default: ":53", }) l.Add(lever.Param{ Name: "--fwd-to", Description: "Address (ip:port) of a dns server to attempt forward requests to. Specify multiple times to make multiple request attempts. Order specified dictates precedence should more than one server respond for a request", }) l.Add(lever.Param{ Name: "--parallel", Description: "If sent the query will be sent to all addresses in parallel", Flag: true, }) l.Add(lever.Param{ Name: "--timeout", Description: "Timeout in milliseconds for each request", Default: "300", }) l.Add(lever.Param{ Name: "--log-level", Description: "Minimum log level to show, either debug, info, warn, error, or fatal", Default: "warn", }) l.Add(lever.Param{ Name: "--allow-truncated", Description: "If we should allow truncated responses to be proxied", Flag: true, }) if version != "" { l.Add(lever.Param{ Name: "--version", Aliases: []string{"-v"}, Description: "Print version info", Flag: true, }) } l.Parse() if l.ParamFlag("--version") { fmt.Println(version) return } addr, _ := l.ParamStr("--listen-addr") dnsServers, _ := l.ParamStrs("--fwd-to") combineGroups := l.ParamFlag("--parallel") timeout, _ := l.ParamInt("--timeout") logLevel, _ := l.ParamStr("--log-level") llog.SetLevelFromString(logLevel) allowTruncated = l.ParamFlag("--allow-truncated") if combineGroups { //combine all the servers sent into one group dnsServerGroups = make([][]string, 1) var groupServers []string for i := range dnsServers { groupServers = strings.Split(dnsServers[i], ",") dnsServerGroups[0] = append(dnsServerGroups[0], groupServers...) } } else { dnsServerGroups = make([][]string, len(dnsServers)) for i := range dnsServers { dnsServerGroups[i] = strings.Split(dnsServers[i], ",") } } client = dns.Client{ //since this is UDP, the Dial/Write timeouts don't mean much //we really only care about setting the read DialTimeout: time.Millisecond * 100, WriteTimeout: time.Millisecond * 100, ReadTimeout: time.Millisecond * time.Duration(timeout), UDPSize: 4096, } handler := dns.HandlerFunc(handleRequest) go func() { llog.Info("listening on udp", llog.KV{"addr": addr}) err := dns.ListenAndServe(addr, "udp", handler) llog.Fatal("error listening on udp", llog.KV{"err": err}) }() go func() { llog.Info("listening on tcp", llog.KV{"addr": addr}) err := dns.ListenAndServe(addr, "tcp", handler) llog.Fatal("error listening on tcp", llog.KV{"err": err}) }() select {} }
// TODO(alx): Settle on naming for handlers acting as middleware. func protocolHandler(maxAnswers int, next dns.Handler) dns.Handler { return dns.HandlerFunc(func(w dns.ResponseWriter, r *dns.Msg) { next.ServeDNS(&truncatingWriter{w, maxAnswers}, r) }) }
func TestServerSimpleQuery(t *testing.T) { var ( testRecord1 = Record{"test.weave.local.", net.ParseIP("10.20.20.10"), 0, 0, 0} testRecord2 = Record{"test.weave.local.", net.ParseIP("10.20.20.20"), 0, 0, 0} testInAddr1 = "10.20.20.10.in-addr.arpa." ) InitDefaultLogging(testing.Verbose()) Info.Println("TestServerSimpleQuery starting") mzone := newMockedZoneWithRecords([]ZoneRecord{testRecord1, testRecord2}) mdnsServer, err := NewMDNSServer(mzone, true, DefaultLocalTTL) require.NoError(t, err) err = mdnsServer.Start(nil) require.NoError(t, err) defer mdnsServer.Stop() var receivedAddrs []net.IP receivedName := "" recvChan := make(chan interface{}) receivedCount := 0 // Implement a minimal listener for responses multicast, err := LinkLocalMulticastListener(nil) require.NoError(t, err) handleMDNS := func(w dns.ResponseWriter, r *dns.Msg) { // Only handle responses here if len(r.Answer) > 0 { t.Logf("Received %d answer(s)", len(r.Answer)) for _, answer := range r.Answer { recvChan <- answer } recvChan <- "ok" } } sendQuery := func(name string, querytype uint16) { receivedAddrs = make([]net.IP, 0) receivedName = "" receivedCount = 0 m := new(dns.Msg) m.SetQuestion(name, querytype) m.RecursionDesired = false buf, err := m.Pack() require.NoError(t, err) conn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: 0}) require.NoError(t, err) Debug.Printf("Sending UDP packet to %s", ipv4Addr) _, err = conn.WriteTo(buf, ipv4Addr) require.NoError(t, err) Debug.Printf("Waiting for response") for { select { case x := <-recvChan: switch rr := x.(type) { case *dns.A: t.Logf("... A:\n%+v", rr) receivedAddrs = append(receivedAddrs, rr.A) receivedCount++ case *dns.PTR: t.Logf("... PTR:\n%+v", rr) receivedName = rr.Ptr receivedCount++ case string: return } case <-time.After(100 * time.Millisecond): Debug.Printf("Timeout while waiting for response") return } } } listener := &dns.Server{ Unsafe: true, PacketConn: multicast, Handler: dns.HandlerFunc(handleMDNS), ReadTimeout: 100 * time.Millisecond} go listener.ActivateAndServe() defer listener.Shutdown() time.Sleep(100 * time.Millisecond) // Allow for server to get going Debug.Printf("Checking that we get 2 IPs fo name '%s' [A]", testRecord1.Name()) sendQuery(testRecord1.Name(), dns.TypeA) if receivedCount != 2 { t.Fatalf("Unexpected result count %d for %s", receivedCount, testRecord1.Name()) } if !(receivedAddrs[0].Equal(testRecord1.IP()) || receivedAddrs[0].Equal(testRecord2.IP())) { t.Fatalf("Unexpected result %s for %s", receivedAddrs, testRecord1.Name()) } if !(receivedAddrs[1].Equal(testRecord1.IP()) || receivedAddrs[1].Equal(testRecord2.IP())) { t.Fatalf("Unexpected result %s for %s", receivedAddrs, testRecord1.Name()) } Debug.Printf("Checking that 'testfail.weave.' [A] gets no answers") sendQuery("testfail.weave.", dns.TypeA) if receivedCount != 0 { t.Fatalf("Unexpected result count %d for testfail.weave", receivedCount) } Debug.Printf("Checking that '%s' [PTR] gets one name", testInAddr1) sendQuery(testInAddr1, dns.TypePTR) if receivedCount != 1 { t.Fatalf("Expected an answer to %s, got %d answers", testInAddr1, receivedCount) } else if !(testRecord1.Name() == receivedName) { t.Fatalf("Expected answer %s to query for %s, got %s", testRecord1.Name(), testInAddr1, receivedName) } }