acme-dns/main.go

211 lines
5.9 KiB
Go
Raw Permalink Normal View History

//go:build !test
// +build !test
2016-11-11 21:48:00 +07:00
package main
import (
"context"
"crypto/tls"
"flag"
stdlog "log"
"net/http"
2016-11-11 21:48:00 +07:00
"os"
"strings"
"syscall"
2017-01-30 17:19:22 +07:00
"github.com/caddyserver/certmagic"
legolog "github.com/go-acme/lego/v3/log"
"github.com/julienschmidt/httprouter"
"github.com/rs/cors"
log "github.com/sirupsen/logrus"
2016-11-11 21:48:00 +07:00
)
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()
2016-11-13 19:50:44 +07:00
// 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)
}
2016-11-23 22:11:31 +07:00
setupLogging(Config.Logconfig.Format, Config.Logconfig.Level)
2016-11-13 19:50:44 +07:00
2016-11-11 21:48:00 +07:00
// Open database
2016-11-28 04:21:46 +07:00
newDB := new(acmedb)
err = newDB.Init(Config.Database.Engine, Config.Database.Connection)
2016-11-11 21:48:00 +07:00
if err != nil {
log.Errorf("Could not open database [%v]", err)
os.Exit(1)
} else {
log.Info("Connected to database")
2016-11-11 21:48:00 +07:00
}
2016-11-28 04:21:46 +07:00
DB = newDB
defer DB.Close()
2016-11-11 21:48:00 +07:00
// Error channel for servers
errChan := make(chan error, 1)
2016-11-28 02:21:38 +07:00
// DNS server
dnsservers := make([]*DNSServer, 0)
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, Config.General.Domain)
dnsservers = append(dnsservers, dnsServerUDP)
dnsServerUDP.ParseRecords(Config)
dnsServerTCP := NewDNSServer(DB, Config.General.Listen, tcpProto, Config.General.Domain)
dnsservers = append(dnsservers, dnsServerTCP)
// 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, Config.General.Domain)
dnsservers = append(dnsservers, dnsServer)
dnsServer.ParseRecords(Config)
go dnsServer.Start(errChan)
}
2016-11-11 21:48:00 +07:00
2016-11-28 03:09:13 +07:00
// HTTP API
go startHTTPAPI(errChan, Config, dnsservers)
2016-11-28 03:09:13 +07:00
// block waiting for error
for {
err = <-errChan
if err != nil {
log.Fatal(err)
}
}
}
func startHTTPAPI(errChan chan error, config DNSConfig, dnsservers []*DNSServer) {
// Setup http logger
logger := log.New()
logwriter := logger.Writer()
defer logwriter.Close()
// Setup logging for different dependencies to log with logrus
// Certmagic
stdlog.SetOutput(logwriter)
// Lego
legolog.Logger = logger
api := httprouter.New()
c := cors.New(cors.Options{
AllowedOrigins: Config.API.CorsOrigins,
2016-11-28 18:09:10 +07:00
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
// TLS specific general settings
cfg := &tls.Config{
MinVersion: tls.VersionTLS12,
}
provider := NewChallengeProvider(dnsservers)
storage := certmagic.FileStorage{Path: Config.API.ACMECacheDir}
// Set up certmagic for getting certificate for acme-dns api
certmagic.DefaultACME.DNS01Solver = &provider
certmagic.DefaultACME.Agreed = true
if Config.API.TLS == "letsencrypt" {
certmagic.DefaultACME.CA = certmagic.LetsEncryptProductionCA
} else {
certmagic.DefaultACME.CA = certmagic.LetsEncryptStagingCA
}
certmagic.DefaultACME.Email = Config.API.NotificationEmail
magicConf := certmagic.NewDefault()
magicConf.Storage = &storage
magicConf.DefaultServerName = Config.General.Domain
magicCache := certmagic.NewCache(certmagic.CacheOptions{
GetConfigForCert: func(cert certmagic.Certificate) (*certmagic.Config, error) {
return magicConf, nil
},
})
magic := certmagic.New(magicCache, *magicConf)
var err error
switch Config.API.TLS {
case "letsencryptstaging":
err = magic.ManageAsync(context.Background(), []string{Config.General.Domain})
if err != nil {
errChan <- err
return
}
cfg.GetCertificate = magic.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.General.Domain}).Info("Listening HTTPS")
err = srv.ListenAndServeTLS("", "")
2016-11-28 18:09:10 +07:00
case "letsencrypt":
err = magic.ManageAsync(context.Background(), []string{Config.General.Domain})
if err != nil {
errChan <- err
return
}
cfg.GetCertificate = magic.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.General.Domain}).Info("Listening HTTPS")
err = srv.ListenAndServeTLS("", "")
2016-11-28 18:09:10 +07:00
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)
2016-11-28 18:09:10 +07:00
default:
log.WithFields(log.Fields{"host": host}).Info("Listening HTTP")
err = http.ListenAndServe(host, c.Handler(api))
}
if err != nil {
errChan <- err
2016-11-28 18:09:10 +07:00
}
}