2018-07-03 13:44:04 +03:00
package integration
import (
"fmt"
"net"
"os"
"github.com/miekg/dns"
2020-09-16 16:46:04 +03:00
"github.com/traefik/traefik/v2/pkg/log"
2018-07-03 13:44:04 +03:00
)
2021-11-25 13:10:06 +03:00
type handler struct {
traefikIP string
}
2018-07-03 13:44:04 +03:00
// ServeDNS a fake DNS server
// Simplified version of the Challenge Test Server from Boulder
// https://github.com/letsencrypt/boulder/blob/a6597b9f120207eff192c3e4107a7e49972a0250/test/challtestsrv/dnsone.go#L40
func ( s * handler ) ServeDNS ( w dns . ResponseWriter , r * dns . Msg ) {
2019-09-13 20:28:04 +03:00
logger := log . WithoutContext ( )
2018-07-03 13:44:04 +03:00
m := new ( dns . Msg )
m . SetReply ( r )
m . Compress = false
for _ , q := range r . Question {
2019-09-13 20:28:04 +03:00
logger . Infof ( "Query -- [%s] %s" , q . Name , dns . TypeToString [ q . Qtype ] )
2018-07-03 13:44:04 +03:00
switch q . Qtype {
case dns . TypeA :
record := new ( dns . A )
record . Hdr = dns . RR_Header {
Name : q . Name ,
Rrtype : dns . TypeA ,
Class : dns . ClassINET ,
Ttl : 0 ,
}
2021-11-25 13:10:06 +03:00
record . A = net . ParseIP ( s . traefikIP )
2018-07-03 13:44:04 +03:00
m . Answer = append ( m . Answer , record )
case dns . TypeCAA :
addCAARecord := true
var value string
switch q . Name {
case "bad-caa-reserved.com." :
value = "sad-hacker-ca.invalid"
case "good-caa-reserved.com." :
value = "happy-hacker-ca.invalid"
case "accounturi.good-caa-reserved.com." :
uri := os . Getenv ( "ACCOUNT_URI" )
value = fmt . Sprintf ( "happy-hacker-ca.invalid; accounturi=%s" , uri )
case "recheck.good-caa-reserved.com." :
// Allow issuance when we're running in the past
// (under FAKECLOCK), otherwise deny issuance.
if os . Getenv ( "FAKECLOCK" ) != "" {
value = "happy-hacker-ca.invalid"
} else {
value = "sad-hacker-ca.invalid"
}
case "dns-01-only.good-caa-reserved.com." :
value = "happy-hacker-ca.invalid; validationmethods=dns-01"
case "http-01-only.good-caa-reserved.com." :
value = "happy-hacker-ca.invalid; validationmethods=http-01"
case "dns-01-or-http-01.good-caa-reserved.com." :
value = "happy-hacker-ca.invalid; validationmethods=dns-01,http-01"
default :
addCAARecord = false
}
if addCAARecord {
record := new ( dns . CAA )
record . Hdr = dns . RR_Header {
Name : q . Name ,
Rrtype : dns . TypeCAA ,
Class : dns . ClassINET ,
Ttl : 0 ,
}
record . Tag = "issue"
record . Value = value
m . Answer = append ( m . Answer , record )
}
}
}
auth := new ( dns . SOA )
auth . Hdr = dns . RR_Header { Name : "boulder.invalid." , Rrtype : dns . TypeSOA , Class : dns . ClassINET , Ttl : 0 }
auth . Ns = "ns.boulder.invalid."
auth . Mbox = "master.boulder.invalid."
auth . Serial = 1
auth . Refresh = 1
auth . Retry = 1
auth . Expire = 1
auth . Minttl = 1
m . Ns = append ( m . Ns , auth )
2018-08-06 21:00:03 +03:00
if err := w . WriteMsg ( m ) ; err != nil {
2019-09-13 20:28:04 +03:00
logger . Fatalf ( "Failed to write message %v" , err )
2018-08-06 21:00:03 +03:00
}
2018-07-03 13:44:04 +03:00
}
2021-11-25 13:10:06 +03:00
func startFakeDNSServer ( traefikIP string ) * dns . Server {
2018-07-03 13:44:04 +03:00
srv := & dns . Server {
Addr : ":5053" ,
Net : "udp" ,
2021-11-25 13:10:06 +03:00
Handler : & handler { traefikIP } ,
2018-07-03 13:44:04 +03:00
}
go func ( ) {
2019-09-13 20:28:04 +03:00
log . WithoutContext ( ) . Infof ( "Start a fake DNS server." )
2018-07-03 13:44:04 +03:00
if err := srv . ListenAndServe ( ) ; err != nil {
2019-09-13 20:28:04 +03:00
log . WithoutContext ( ) . Fatalf ( "Failed to set udp listener %v" , err )
2018-07-03 13:44:04 +03:00
}
} ( )
return srv
}