Skip to content
Snippets Groups Projects
Select Git revision
  • 8460b284d34f68f3d71c1b24b3acb958624736ac
  • main default protected
  • rosification
  • refactoring
  • pp
  • mpc
  • realtimelogplotter
  • alv
  • gitlab_ci_podman
  • restructuring
  • viz_fix
11 results

development_plan.toml

Blame
  • main.go 4.39 KiB
    //+build !test
    
    package main
    
    import (
    	"crypto/tls"
    	"flag"
    	stdlog "log"
    	"net/http"
    	"os"
    	"strings"
    	"syscall"
    
    	"github.com/julienschmidt/httprouter"
    	"github.com/rs/cors"
    	log "github.com/sirupsen/logrus"
    	"golang.org/x/crypto/acme/autocert"
    )
    
    func main() {
    	// Created files are not world writable
    	syscall.Umask(0077)
    	configPtr := flag.String("c", "/etc/acme-dns/config.cfg", "config file location")
    	flag.Parse()
    	// Read global config
    	var err error
    	if fileIsAccessible(*configPtr) {
    		log.WithFields(log.Fields{"file": *configPtr}).Info("Using config file")
    		Config, err = readConfig(*configPtr)
    	} else if fileIsAccessible("./config.cfg") {
    		log.WithFields(log.Fields{"file": "./config.cfg"}).Info("Using config file")
    		Config, err = readConfig("./config.cfg")
    	} else {
    		log.Errorf("Configuration file not found.")
    		os.Exit(1)
    	}
    	if err != nil {
    		log.Errorf("Encountered an error while trying to read configuration file:  %s", err)
    		os.Exit(1)
    	}
    
    	setupLogging(Config.Logconfig.Format, Config.Logconfig.Level)
    
    	// Open database
    	newDB := new(acmedb)
    	err = newDB.Init(Config.Database.Engine, Config.Database.Connection)
    	if err != nil {
    		log.Errorf("Could not open database [%v]", err)
    		os.Exit(1)
    	} else {
    		log.Info("Connected to database")
    	}
    	DB = newDB
    	defer DB.Close()
    
    	// Error channel for servers
    	errChan := make(chan error, 1)
    
    	// DNS server
    	if strings.HasPrefix(Config.General.Proto, "both") {
    		// Handle the case where DNS server should be started for both udp and tcp
    		udpProto := "udp"
    		tcpProto := "tcp"
    		if strings.HasSuffix(Config.General.Proto, "4") {
    			udpProto += "4"
    			tcpProto += "4"
    		} else if strings.HasSuffix(Config.General.Proto, "6") {
    			udpProto += "6"
    			tcpProto += "6"
    		}
    		dnsServerUDP := NewDNSServer(DB, Config.General.Listen, udpProto)
    		dnsServerUDP.ParseRecords(Config)
    		dnsServerTCP := NewDNSServer(DB, Config.General.Listen, tcpProto)
    		// No need to parse records from config again
    		dnsServerTCP.Domains = dnsServerUDP.Domains
    		dnsServerTCP.SOA = dnsServerUDP.SOA
    		go dnsServerUDP.Start(errChan)
    		go dnsServerTCP.Start(errChan)
    	} else {
    		dnsServer := NewDNSServer(DB, Config.General.Listen, Config.General.Proto)
    		dnsServer.ParseRecords(Config)
    		go dnsServer.Start(errChan)
    	}
    
    	// HTTP API
    	go startHTTPAPI(errChan)
    
    	// block waiting for error
    	select {
    	case err = <-errChan:
    		if err != nil {
    			log.Fatal(err)
    		}
    	}
    	log.Debugf("Shutting down...")
    }
    
    func startHTTPAPI(errChan chan error) {
    	// Setup http logger
    	logger := log.New()
    	logwriter := logger.Writer()
    	defer logwriter.Close()
    	api := httprouter.New()
    	c := cors.New(cors.Options{
    		AllowedOrigins:     Config.API.CorsOrigins,
    		AllowedMethods:     []string{"GET", "POST"},
    		OptionsPassthrough: false,
    		Debug:              Config.General.Debug,
    	})
    	if Config.General.Debug {
    		// Logwriter for saner log output
    		c.Log = stdlog.New(logwriter, "", 0)
    	}
    	if !Config.API.DisableRegistration {
    		api.POST("/register", webRegisterPost)
    	}
    	api.POST("/update", Auth(webUpdatePost))
    	api.GET("/health", healthCheck)
    
    	host := Config.API.IP + ":" + Config.API.Port
    
    	cfg := &tls.Config{
    		MinVersion: tls.VersionTLS12,
    	}
    	var err error
    	switch Config.API.TLS {
    	case "letsencrypt":
    		m := autocert.Manager{
    			Cache:      autocert.DirCache(Config.API.ACMECacheDir),
    			Prompt:     autocert.AcceptTOS,
    			HostPolicy: autocert.HostWhitelist(Config.API.Domain),
    		}
    		autocerthost := Config.API.IP + ":" + Config.API.AutocertPort
    		log.WithFields(log.Fields{"autocerthost": autocerthost, "domain": Config.API.Domain}).Debug("Opening HTTP port for autocert")
    		go http.ListenAndServe(autocerthost, m.HTTPHandler(nil))
    		cfg.GetCertificate = m.GetCertificate
    		srv := &http.Server{
    			Addr:      host,
    			Handler:   c.Handler(api),
    			TLSConfig: cfg,
    			ErrorLog:  stdlog.New(logwriter, "", 0),
    		}
    		log.WithFields(log.Fields{"host": host, "domain": Config.API.Domain}).Info("Listening HTTPS, using certificate from autocert")
    		err = srv.ListenAndServeTLS("", "")
    	case "cert":
    		srv := &http.Server{
    			Addr:      host,
    			Handler:   c.Handler(api),
    			TLSConfig: cfg,
    			ErrorLog:  stdlog.New(logwriter, "", 0),
    		}
    		log.WithFields(log.Fields{"host": host}).Info("Listening HTTPS")
    		err = srv.ListenAndServeTLS(Config.API.TLSCertFullchain, Config.API.TLSCertPrivkey)
    	default:
    		log.WithFields(log.Fields{"host": host}).Info("Listening HTTP")
    		err = http.ListenAndServe(host, c.Handler(api))
    	}
    	if err != nil {
    		errChan <- err
    	}
    }