Open jinrenjie opened 1 month ago
I think the problem might be here:
func (d *DNSServer) answer(q dns.Question) ([]dns.RR, int, bool, error) {
var rcode int
var err error
var txtRRs []dns.RR
var authoritative = d.isAuthoritative(q)
if !d.isOwnChallenge(q.Name) && !d.answeringForDomain(q.Name) {
rcode = dns.RcodeNameError
}
r, _ := d.getRecord(q)
+ for _, rr := range r {
+ if rr.Header().Rrtype == dns.TypeCNAME && len(r) == 1 {
+ q = dns.Question{
+ Name: rr.(*dns.CNAME).Target,
+ Qtype: q.Qtype,
+ Qclass: q.Qclass,
+ }
+ }
+ }
if q.Qtype == dns.TypeTXT {
if d.isOwnChallenge(q.Name) {
txtRRs, err = d.answerOwnChallenge(q)
} else {
txtRRs, err = d.answerTXT(q)
}
if err == nil {
r = append(r, txtRRs...)
}
}
if len(r) > 0 {
// Make sure that we return NOERROR if there were dynamic records for the domain
rcode = dns.RcodeSuccess
}
log.WithFields(log.Fields{"qtype": dns.TypeToString[q.Qtype], "domain": q.Name, "rcode": dns.RcodeToString[rcode]}).Debug("Answering question for domain")
return r, rcode, authoritative, nil
}
When there is only one CNAME record obtained from DNS, use the value of the CNAME record as the parameter of d.answerTXT()
to obtain the TXT record in the database.
Once I did this, Smallstep CA Server was able to verify and issue certificates just fine!
I don't know if this is a common practice, But I can traverse and query the TXT records on the CNAME in the cloud service provider's DNS like this:
dig TXT _acme-challenge.betterde.com @223.5.5.5
; <<>> DiG 9.10.6 <<>> TXT _acme-challenge.betterde.com @223.5.5.5
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59316
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1408
;; QUESTION SECTION:
;_acme-challenge.betterde.com. IN TXT
;; ANSWER SECTION:
_acme-challenge.betterde.com. 600 IN CNAME 1ef56a0d-5f76-4aae-93ca-d3209823a217.betterde.com.
1ef56a0d-5f76-4aae-93ca-d3209823a217.betterde.com. 600 IN TXT "L6gnTrq24MA66xjFQ0jvAFhtia83cxu2zJBtPdMB6UH"
;; Query time: 200 msec
;; SERVER: 223.5.5.5#53(223.5.5.5)
;; WHEN: Tue Jul 16 03:13:24 CST 2024
;; MSG SIZE rcvd: 164
@jinrenjie are you able to provide some more specific instructions on that fix?
I have the exact same issue and assumed it was something I'd configured incorrectly. Is there a workaround in the DNS config?
Are you saying we can't have any other CNAMEs at all on the DNS for it to work?
@TRPB I think the problem is that when we query the DNS for the TXT record, it doesn't process the CNAME record that exists on the DNS and then query the corresponding TXT record according to the CNAME record!
Later, I did not use this project as the DNS Challenge service provider, but wrote my own project github.com/betterde/cdns, but my project is limited to intranet development or test environment, not for production environment!
Architecture
These services all run in containers and can communicate with each other.
acme-dns.cfg
is configured as follows:Get acme-dns account fulldomain TXT records:
This seems to be all working fine!
Get the NS record of
ingress.test
:Get the TXT record of
_acme-challenge.ingress.test
:There seems to be a problem here. In theory, both the CNAME and TXT records should be queried at the same time, but no TXT record appears. As a result, the Smallstep CA I use cannot verify the DNS challenge and cannot issue a certificate!
This problem has troubled me for a long time and I have not found a solution. I look forward to your answer, which will be of great help to me. Thank you!