Beispiel #1
0
func startDNSServer(state *server.State, addr string, recursors []string) error {
	dns := server.DNSServer{
		UDPAddr:   addr,
		TCPAddr:   addr,
		Store:     state,
		Recursors: recursors,
	}
	return dns.ListenAndServe()
}
Beispiel #2
0
func main() {
	defer shutdown.Exit()

	httpAddr := flag.String("http-addr", ":1111", "address to serve HTTP API from")
	dnsAddr := flag.String("dns-addr", ":53", "address to service DNS from")
	resolvers := flag.String("recursors", "8.8.8.8,8.8.4.4", "upstream recursive DNS servers")
	etcdAddrs := flag.String("etcd", "http://127.0.0.1:2379", "etcd servers (comma separated)")
	notify := flag.String("notify", "", "url to send webhook to after starting listener")
	flag.Parse()

	etcdClient := etcd.NewClient(strings.Split(*etcdAddrs, ","))

	// Check to make sure that etcd is online and accepting connections
	// etcd takes a while to come online, so we attempt a GET multiple times
	err := attempt.Strategy{
		Min:   5,
		Total: 10 * time.Minute,
		Delay: 200 * time.Millisecond,
	}.Run(func() (err error) {
		_, err = etcdClient.Get("/", false, false)
		if e, ok := err.(*etcd.EtcdError); ok && e.ErrorCode == 100 {
			// Valid 404 from etcd (> v2.0)
			err = nil
		}
		return
	})
	if err != nil {
		log.Fatalf("Failed to connect to etcd at %v: %q", etcdAddrs, err)
	}

	state := server.NewState()
	backend := server.NewEtcdBackend(etcdClient, "/discoverd", state)
	if err := backend.StartSync(); err != nil {
		log.Fatalf("Failed to perform initial etcd sync: %s", err)
	}

	dns := server.DNSServer{
		UDPAddr: *dnsAddr,
		TCPAddr: *dnsAddr,
		Store:   state,
	}
	if *resolvers != "" {
		dns.Recursors = strings.Split(*resolvers, ",")
	}
	if err := dns.ListenAndServe(); err != nil {
		log.Fatalf("Failed to start DNS server: %s", err)
	}

	l, err := net.Listen("tcp4", *httpAddr)
	if err != nil {
		log.Fatalf("Failed to start HTTP listener: %s", err)
	}
	log.Printf("discoverd listening for HTTP on %s and DNS on %s", *httpAddr, *dnsAddr)

	if *notify != "" {
		addr := l.Addr().String()
		host, port, _ := net.SplitHostPort(addr)
		if host == "0.0.0.0" {
			// try to get real address from dns addr
			if dnsHost, _, _ := net.SplitHostPort(*dnsAddr); dnsHost != "" {
				addr = net.JoinHostPort(dnsHost, port)
			}
		}
		data := struct {
			URL string `json:"url"`
		}{fmt.Sprintf("http://%s", addr)}
		payload, _ := json.Marshal(data)
		res, err := http.Post(*notify, "application/json", bytes.NewReader(payload))
		if err != nil {
			log.Printf("failed to notify: %s", err)
		} else {
			res.Body.Close()
		}
	}

	http.Serve(l, server.NewHTTPHandler(server.NewBasicDatastore(state, backend)))
}