implemented lego HTTP endpoint
This commit is contained in:
parent
c7bac27a53
commit
fe7c207065
@ -33,3 +33,9 @@ blacklist:
|
||||
format: host
|
||||
- url: https://blocklistproject.github.io/Lists/alt-version/ads-nl.txt
|
||||
format: line
|
||||
|
||||
lego:
|
||||
enable: true
|
||||
address: :8080
|
||||
username: lego
|
||||
secret: "133742069ab"
|
20
coolDns.go
20
coolDns.go
@ -31,6 +31,7 @@ type config struct {
|
||||
Address string `yaml:"address"`
|
||||
Blacklist []configBlacklist `yaml:"blacklist"`
|
||||
TLS configTLS `yaml:"tls"`
|
||||
Lego configLego `yaml:"lego"`
|
||||
}
|
||||
|
||||
type configForward struct {
|
||||
@ -168,7 +169,7 @@ func createACLList(config []configACL) (map[string]*net.IPNet, error) {
|
||||
}
|
||||
|
||||
// createServer creates a new serve mux. Adds all the logic to handle the request
|
||||
func createServer(zones zoneMap, config config, aclList map[string]*net.IPNet, blacklist map[string]bool) *dns.ServeMux {
|
||||
func createServer(zones zoneMap, config config, aclList map[string]*net.IPNet, blacklist map[string]bool, acmeList *legoMap) *dns.ServeMux {
|
||||
srv := dns.NewServeMux()
|
||||
c := new(dns.Client)
|
||||
|
||||
@ -184,6 +185,11 @@ func createServer(zones zoneMap, config config, aclList map[string]*net.IPNet, b
|
||||
return
|
||||
}
|
||||
|
||||
// Check if it is a ACME DNS-01 challange
|
||||
if handleACMERequest(w, r, acmeList) {
|
||||
return
|
||||
}
|
||||
|
||||
// find out what view to handle the request
|
||||
zoneIndex := -1
|
||||
|
||||
@ -215,6 +221,11 @@ func createServer(zones zoneMap, config config, aclList map[string]*net.IPNet, b
|
||||
return
|
||||
}
|
||||
|
||||
// Check if it is a ACME DNS-01 challange
|
||||
if handleACMERequest(w, r, acmeList) {
|
||||
return
|
||||
}
|
||||
|
||||
// Check ACL rules
|
||||
if !checkACL(config.Forward.ACL, aclList, ip) {
|
||||
rcodeRequest(w, r, dns.RcodeRefused)
|
||||
@ -389,7 +400,12 @@ func main() {
|
||||
|
||||
blacklist := loadBlacklist(config.Blacklist)
|
||||
|
||||
server := createServer(zones, *config, aclList, blacklist)
|
||||
var acmeMap *legoMap
|
||||
if config.Lego.Enable {
|
||||
acmeMap = startLEGOWebSever(config.Lego)
|
||||
}
|
||||
|
||||
server := createServer(zones, *config, aclList, blacklist, acmeMap)
|
||||
|
||||
listenAndServer(server, config.Address)
|
||||
|
||||
|
118
lego.go
Normal file
118
lego.go
Normal file
@ -0,0 +1,118 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// See https://go-acme.github.io/lego/dns/httpreq/
|
||||
|
||||
type configLego struct {
|
||||
Enable bool `yaml:"enable"`
|
||||
Address string `yaml:"address"`
|
||||
Username string `yaml:"username"`
|
||||
Secret string `yaml:"secret"`
|
||||
}
|
||||
|
||||
type legoPresent struct {
|
||||
Fqdn string `json:"fqdn"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type legoMap map[string]string
|
||||
|
||||
func startLEGOWebSever(config configLego) *legoMap {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
acmeMap := make(legoMap)
|
||||
|
||||
mux.HandleFunc("/present", func(rw http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if !checkBasicAuth(r, config) {
|
||||
rw.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
var presentData legoPresent
|
||||
err := json.NewDecoder(r.Body).Decode(&presentData)
|
||||
defer r.Body.Close()
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Failed to parse request for ACME: %s", err.Error())
|
||||
}
|
||||
|
||||
acmeMap[presentData.Fqdn] = presentData.Value
|
||||
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/cleanup", func(rw http.ResponseWriter, r *http.Request) {
|
||||
if !checkBasicAuth(r, config) {
|
||||
rw.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
for k := range acmeMap {
|
||||
delete(acmeMap, k)
|
||||
}
|
||||
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
go func() {
|
||||
if err := http.ListenAndServe(config.Address, mux); err != nil {
|
||||
log.Fatalf("Failed to start Webserver for LEGO: %s\n", err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
log.Printf("Startet webserver on %s", config.Address)
|
||||
|
||||
return &acmeMap
|
||||
}
|
||||
|
||||
func checkBasicAuth(r *http.Request, config configLego) bool {
|
||||
if config.Username != "" && config.Secret != "" {
|
||||
u, p, ok := r.BasicAuth()
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if u == config.Username && p == config.Secret {
|
||||
return true
|
||||
}
|
||||
|
||||
log.Printf("Failed lego authentication")
|
||||
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func handleACMERequest(w dns.ResponseWriter, r *dns.Msg, acmeMap *legoMap) bool {
|
||||
if len(r.Question) == 1 {
|
||||
if r.Question[0].Qtype == dns.TypeTXT && r.Question[0].Qclass == dns.ClassINET {
|
||||
if value, ok := (*acmeMap)[r.Question[0].Name]; ok {
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(r)
|
||||
|
||||
m.Answer = append(m.Answer, &dns.TXT{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: r.Question[0].Name,
|
||||
Rrtype: dns.TypeTXT,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 0,
|
||||
},
|
||||
Txt: []string{value},
|
||||
})
|
||||
|
||||
w.WriteMsg(m)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
Loading…
Reference in New Issue
Block a user