Merge branch 'pr361'
This commit is contained in:
commit
59cd5a13da
2 files changed
+81
-13
No files matched your search
+15
-8
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
LOCAL_DOMAIN = "weave.local."
|
LOCAL_DOMAIN = "weave.local."
|
||||||
|
UDPBufSize = 4096 // bigger than the default 512
|
||||||
)
|
)
|
||||||
|
|
||||||
func checkFatal(e error) {
|
func checkFatal(e error) {
|
||||||
@@ -50,8 +51,8 @@ func queryHandler(lookups []Lookup) dns.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func rdnsHandler(lookups []Lookup) dns.HandlerFunc {
|
func rdnsHandler(config *dns.ClientConfig, lookups []Lookup) dns.HandlerFunc {
|
||||||
fallback := notUsHandler()
|
fallback := notUsHandler(config)
|
||||||
return func(w dns.ResponseWriter, r *dns.Msg) {
|
return func(w dns.ResponseWriter, r *dns.Msg) {
|
||||||
q := r.Question[0]
|
q := r.Question[0]
|
||||||
Debug.Printf("Reverse query: %+v", q)
|
Debug.Printf("Reverse query: %+v", q)
|
||||||
@@ -74,14 +75,14 @@ func rdnsHandler(lookups []Lookup) dns.HandlerFunc {
|
|||||||
/* When we receive a request for a name outside of our '.weave.local.'
|
/* When we receive a request for a name outside of our '.weave.local.'
|
||||||
domain, ask the configured DNS server as a fallback.
|
domain, ask the configured DNS server as a fallback.
|
||||||
*/
|
*/
|
||||||
func notUsHandler() dns.HandlerFunc {
|
func notUsHandler(config *dns.ClientConfig) dns.HandlerFunc {
|
||||||
config, err := dns.ClientConfigFromFile("/etc/resolv.conf")
|
dnsClient := new(dns.Client)
|
||||||
checkFatal(err)
|
dnsClient.UDPSize = UDPBufSize
|
||||||
return func(w dns.ResponseWriter, r *dns.Msg) {
|
return func(w dns.ResponseWriter, r *dns.Msg) {
|
||||||
q := r.Question[0]
|
q := r.Question[0]
|
||||||
Debug.Printf("[dns msgid %d] Fallback query: %+v", r.MsgHdr.Id, q)
|
Debug.Printf("[dns msgid %d] Fallback query: %+v", r.MsgHdr.Id, q)
|
||||||
for _, server := range config.Servers {
|
for _, server := range config.Servers {
|
||||||
reply, err := dns.Exchange(r, fmt.Sprintf("%s:%s", server, config.Port))
|
reply, _, err := dnsClient.Exchange(r, fmt.Sprintf("%s:%s", server, config.Port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Debug.Printf("[dns msgid %d] Network error trying %s (%s)",
|
Debug.Printf("[dns msgid %d] Network error trying %s (%s)",
|
||||||
r.MsgHdr.Id, server, err)
|
r.MsgHdr.Id, server, err)
|
||||||
@@ -104,6 +105,12 @@ func notUsHandler() dns.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func StartServer(zone Zone, iface *net.Interface, dnsPort int, wait int) error {
|
func StartServer(zone Zone, iface *net.Interface, dnsPort int, wait int) error {
|
||||||
|
config, err := dns.ClientConfigFromFile("/etc/resolv.conf")
|
||||||
|
checkFatal(err)
|
||||||
|
return startServerWithConfig(config, zone, iface, dnsPort, wait)
|
||||||
|
}
|
||||||
|
|
||||||
|
func startServerWithConfig(config *dns.ClientConfig, zone Zone, iface *net.Interface, dnsPort int, wait int) error {
|
||||||
mdnsClient, err := NewMDNSClient()
|
mdnsClient, err := NewMDNSClient()
|
||||||
checkFatal(err)
|
checkFatal(err)
|
||||||
|
|
||||||
@@ -117,8 +124,8 @@ func StartServer(zone Zone, iface *net.Interface, dnsPort int, wait int) error {
|
|||||||
|
|
||||||
LocalServeMux := dns.NewServeMux()
|
LocalServeMux := dns.NewServeMux()
|
||||||
LocalServeMux.HandleFunc(LOCAL_DOMAIN, queryHandler([]Lookup{zone, mdnsClient}))
|
LocalServeMux.HandleFunc(LOCAL_DOMAIN, queryHandler([]Lookup{zone, mdnsClient}))
|
||||||
LocalServeMux.HandleFunc(RDNS_DOMAIN, rdnsHandler([]Lookup{zone, mdnsClient}))
|
LocalServeMux.HandleFunc(RDNS_DOMAIN, rdnsHandler(config, []Lookup{zone, mdnsClient}))
|
||||||
LocalServeMux.HandleFunc(".", notUsHandler())
|
LocalServeMux.HandleFunc(".", notUsHandler(config))
|
||||||
|
|
||||||
mdnsServer, err := NewMDNSServer(zone)
|
mdnsServer, err := NewMDNSServer(zone)
|
||||||
checkFatal(err)
|
checkFatal(err)
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
testRDNSsuccess = "1.2.0.10.in-addr.arpa."
|
||||||
|
testRDNSfail = "4.3.2.1.in-addr.arpa."
|
||||||
|
testRDNSnonlocal = "8.8.8.8.in-addr.arpa."
|
||||||
|
)
|
||||||
|
|
||||||
func TestDNSServer(t *testing.T) {
|
func TestDNSServer(t *testing.T) {
|
||||||
const (
|
const (
|
||||||
port = 17625
|
port = 17625
|
||||||
@@ -17,8 +23,6 @@ func TestDNSServer(t *testing.T) {
|
|||||||
failTestName = "test2.weave.local."
|
failTestName = "test2.weave.local."
|
||||||
nonLocalName = "weave.works."
|
nonLocalName = "weave.works."
|
||||||
testAddr1 = "10.0.2.1"
|
testAddr1 = "10.0.2.1"
|
||||||
testRDNSsuccess = "1.2.0.10.in-addr.arpa."
|
|
||||||
testRDNSfail = "4.3.2.1.in-addr.arpa."
|
|
||||||
)
|
)
|
||||||
dnsAddr := fmt.Sprintf("localhost:%d", port)
|
dnsAddr := fmt.Sprintf("localhost:%d", port)
|
||||||
testCIDR1 := testAddr1 + "/24"
|
testCIDR1 := testAddr1 + "/24"
|
||||||
@@ -28,10 +32,20 @@ func TestDNSServer(t *testing.T) {
|
|||||||
ip, _, _ := net.ParseCIDR(testCIDR1)
|
ip, _, _ := net.ParseCIDR(testCIDR1)
|
||||||
zone.AddRecord(containerID, successTestName, ip)
|
zone.AddRecord(containerID, successTestName, ip)
|
||||||
|
|
||||||
go StartServer(zone, nil, port, 0)
|
// Run another DNS server for fallback
|
||||||
|
s, fallbackAddr, err := RunLocalUDPServer("127.0.0.1:0")
|
||||||
|
wt.AssertNoErr(t, err)
|
||||||
|
defer s.Shutdown()
|
||||||
|
|
||||||
|
_, fallbackPort, err := net.SplitHostPort(fallbackAddr)
|
||||||
|
wt.AssertNoErr(t, err)
|
||||||
|
|
||||||
|
config := &dns.ClientConfig{Servers: []string{"127.0.0.1"}, Port: fallbackPort}
|
||||||
|
go startServerWithConfig(config, zone, nil, port, 0)
|
||||||
time.Sleep(100 * time.Millisecond) // Allow sever goroutine to start
|
time.Sleep(100 * time.Millisecond) // Allow sever goroutine to start
|
||||||
|
|
||||||
c := new(dns.Client)
|
c := new(dns.Client)
|
||||||
|
c.UDPSize = UDPBufSize
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.SetQuestion(successTestName, dns.TypeA)
|
m.SetQuestion(successTestName, dns.TypeA)
|
||||||
m.RecursionDesired = true
|
m.RecursionDesired = true
|
||||||
@@ -69,7 +83,7 @@ func TestDNSServer(t *testing.T) {
|
|||||||
wt.AssertEqualInt(t, len(r.Answer), 0, "Number of answers")
|
wt.AssertEqualInt(t, len(r.Answer), 0, "Number of answers")
|
||||||
|
|
||||||
// This non-local query for an MX record should succeed by being
|
// This non-local query for an MX record should succeed by being
|
||||||
// passed on to the configured (/etc/resolv.conf) DNS server.
|
// passed on to the fallback server
|
||||||
m.SetQuestion(nonLocalName, dns.TypeMX)
|
m.SetQuestion(nonLocalName, dns.TypeMX)
|
||||||
r, _, err = c.Exchange(m, dnsAddr)
|
r, _, err = c.Exchange(m, dnsAddr)
|
||||||
wt.AssertNoErr(t, err)
|
wt.AssertNoErr(t, err)
|
||||||
@@ -77,8 +91,16 @@ func TestDNSServer(t *testing.T) {
|
|||||||
if !(len(r.Answer) > 0) {
|
if !(len(r.Answer) > 0) {
|
||||||
t.Fatal("Number of answers > 0")
|
t.Fatal("Number of answers > 0")
|
||||||
}
|
}
|
||||||
|
// Now ask a query that we expect to return a lot of data.
|
||||||
|
m.SetQuestion(nonLocalName, dns.TypeANY)
|
||||||
|
r, _, err = c.Exchange(m, dnsAddr)
|
||||||
|
wt.AssertNoErr(t, err)
|
||||||
|
wt.AssertStatus(t, r.Rcode, dns.RcodeSuccess, "DNS response code")
|
||||||
|
if !(len(r.Extra) > 5) {
|
||||||
|
t.Fatal("Number of answers > 5")
|
||||||
|
}
|
||||||
|
|
||||||
m.SetQuestion("8.8.8.8.in-addr.arpa.", dns.TypePTR)
|
m.SetQuestion(testRDNSnonlocal, dns.TypePTR)
|
||||||
r, _, err = c.Exchange(m, dnsAddr)
|
r, _, err = c.Exchange(m, dnsAddr)
|
||||||
wt.AssertNoErr(t, err)
|
wt.AssertNoErr(t, err)
|
||||||
wt.AssertStatus(t, r.Rcode, dns.RcodeSuccess, "DNS success response code")
|
wt.AssertStatus(t, r.Rcode, dns.RcodeSuccess, "DNS success response code")
|
||||||
@@ -89,3 +111,42 @@ func TestDNSServer(t *testing.T) {
|
|||||||
// Not testing MDNS functionality of server here (yet), since it
|
// Not testing MDNS functionality of server here (yet), since it
|
||||||
// needs two servers, each listening on its own address
|
// needs two servers, each listening on its own address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fallbackHandler(w dns.ResponseWriter, req *dns.Msg) {
|
||||||
|
m := new(dns.Msg)
|
||||||
|
m.SetReply(req)
|
||||||
|
if len(req.Question) == 1 {
|
||||||
|
q := req.Question[0]
|
||||||
|
if q.Name == "weave.works." && q.Qtype == dns.TypeMX {
|
||||||
|
m.Answer = make([]dns.RR, 1)
|
||||||
|
m.Answer[0] = &dns.MX{Hdr: dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: 0}, Mx: "mail.weave.works."}
|
||||||
|
} else if q.Name == "weave.works." && q.Qtype == dns.TypeANY {
|
||||||
|
const N = 10
|
||||||
|
m.Extra = make([]dns.RR, N)
|
||||||
|
for i, _ := range m.Extra {
|
||||||
|
m.Extra[i] = &dns.TXT{Hdr: dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0}, Txt: []string{"Lots and lots and lots and lots and lots and lots and lots and lots and lots of data"}}
|
||||||
|
}
|
||||||
|
} else if q.Name == testRDNSnonlocal && q.Qtype == dns.TypePTR {
|
||||||
|
m.Answer = make([]dns.RR, 1)
|
||||||
|
m.Answer[0] = &dns.PTR{Hdr: dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: 0}, Ptr: "ns1.google.com."}
|
||||||
|
} else if q.Name == testRDNSfail && q.Qtype == dns.TypePTR {
|
||||||
|
m.Rcode = dns.RcodeNameError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.WriteMsg(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunLocalUDPServer(laddr string) (*dns.Server, string, error) {
|
||||||
|
pc, err := net.ListenPacket("udp", laddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
server := &dns.Server{PacketConn: pc, Handler: dns.HandlerFunc(fallbackHandler)}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
server.ActivateAndServe()
|
||||||
|
pc.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return server, pc.LocalAddr().String(), nil
|
||||||
|
}
|
||||||
Reference in new issue
Block a user