orchid/test/fakeDnsProv.go

108 lines
2.4 KiB
Go

package test
import (
"fmt"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/challenge/dns01"
"github.com/miekg/dns"
"log"
"strings"
)
type fakeDnsProv struct {
Addr string
mTxt map[string]string
srv *dns.Server
mSoa map[string][2]string
}
func MakeFakeDnsProv(addr string) interface {
challenge.Provider
GetDnsAddrs() []string
Start()
Shutdown()
AddRecursiveSOA(fqdn string)
} {
return &fakeDnsProv{
Addr: addr,
mTxt: make(map[string]string),
mSoa: make(map[string][2]string),
}
}
func (f *fakeDnsProv) AddRecursiveSOA(fqdn string) {
n := fqdn
for {
f.mSoa[n] = [2]string{"ns." + n, "webmaster." + n}
// find next subdomain separator and trim the fqdn
ni := strings.IndexByte(n, '.')
if ni <= 0 {
break
}
n = n[ni+1:]
}
}
func (f *fakeDnsProv) Present(domain, _, keyAuth string) error {
info := dns01.GetChallengeInfo(domain, keyAuth)
f.mTxt[info.EffectiveFQDN] = info.Value
log.Printf("fakeDnsProv.Present(%s TXT %s)\n", info.EffectiveFQDN, info.Value)
return nil
}
func (f *fakeDnsProv) CleanUp(domain, _, keyAuth string) error {
info := dns01.GetChallengeInfo(domain, keyAuth)
delete(f.mTxt, info.EffectiveFQDN)
log.Printf("fakeDnsProv.CleanUp(%s TXT %s)\n", info.EffectiveFQDN, info.Value)
return nil
}
func (f *fakeDnsProv) GetDnsAddrs() []string { return []string{f.Addr} }
func (f *fakeDnsProv) parseQuery(m *dns.Msg) {
for _, q := range m.Question {
switch q.Qtype {
case dns.TypeTXT:
log.Printf("Looking up %s TXT record\n", q.Name)
txt := f.mTxt[q.Name]
if txt != "" {
rr, err := dns.NewRR(fmt.Sprintf("%s 32600 IN TXT \"%s\"", q.Name, txt))
if err == nil {
m.Answer = append(m.Answer, rr)
}
}
default:
log.Printf("Looking up %d for %s\n", q.Qtype, q.Name)
}
}
}
func (f *fakeDnsProv) handleDnsRequest(w dns.ResponseWriter, r *dns.Msg) {
m := new(dns.Msg)
m.SetReply(r)
m.Compress = false
switch r.Opcode {
case dns.OpcodeQuery:
f.parseQuery(m)
}
_ = w.WriteMsg(m)
}
func (f *fakeDnsProv) Start() {
// attach request handler func
dns.HandleFunc(".", f.handleDnsRequest)
// start server
f.srv = &dns.Server{Addr: f.Addr, Net: "udp"}
log.Printf("Starting fake dns service at %s\n", f.srv.Addr)
err := f.srv.ListenAndServe()
if err != nil {
log.Fatalf("Failed to start server: %s\n ", err.Error())
}
}
func (f *fakeDnsProv) Shutdown() {
_ = f.srv.Shutdown()
}