diff --git a/nameserver/dns.go b/nameserver/dns.go index f2cd8fe7..db128203 100644 --- a/nameserver/dns.go +++ b/nameserver/dns.go @@ -90,7 +90,7 @@ type DNSServer struct { ns *Nameserver domain string ttl uint32 - address string + address string // listen address and port, e.g. 1.2.3.4:53 servers []*dns.Server upstream Upstream @@ -99,6 +99,10 @@ type DNSServer struct { } func NewDNSServer(ns *Nameserver, domain, address string, upstream Upstream, ttl uint32, clientTimeout time.Duration) (*DNSServer, error) { + if _, _, err := net.SplitHostPort(address); err != nil { + return nil, fmt.Errorf("invalid DNS listen address %q: %v", address, err) + } + s := &DNSServer{ ns: ns, domain: dns.Fqdn(domain), diff --git a/nameserver/http.go b/nameserver/http.go index ac421c0e..d7b91dea 100644 --- a/nameserver/http.go +++ b/nameserver/http.go @@ -3,6 +3,7 @@ package nameserver import ( "encoding/json" "fmt" + "net" "net/http" "github.com/gorilla/mux" @@ -84,3 +85,13 @@ func (n *Nameserver) HandleHTTP(router *mux.Router, dockerCli *docker.Client) { } }) } + +func (d *DNSServer) HandleHTTP(router *mux.Router) { + router.Methods("GET").Path("/dns-address-port").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, d.address) + }) + router.Methods("GET").Path("/dns-address").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + host, _, _ := net.SplitHostPort(d.address) // address is validated in NewDNSServer() + fmt.Fprint(w, host) + }) +} diff --git a/prog/weaver/main.go b/prog/weaver/main.go index 811fc5d9..315a979c 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -55,10 +55,7 @@ type dnsConfig struct { // return the address part of the DNS listen address, without ":53" on the end func (c dnsConfig) addressOnly() string { - addr, _, err := net.SplitHostPort(c.ListenAddress) - if err != nil { - Log.Fatalf("Error when parsing DNS listen address %q: %s", c.ListenAddress, err) - } + addr, _, _ := net.SplitHostPort(c.ListenAddress) return addr } @@ -474,6 +471,7 @@ func main() { } if ns != nil { ns.HandleHTTP(muxRouter, dockerCli) + dnsserver.HandleHTTP(muxRouter) } router.HandleHTTP(muxRouter) HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver, proxy, plugin, &waitReady) diff --git a/site/tasks/weavedns/weavedns.md b/site/tasks/weavedns/weavedns.md index 867bdb21..6b685349 100644 --- a/site/tasks/weavedns/weavedns.md +++ b/site/tasks/weavedns/weavedns.md @@ -39,6 +39,10 @@ the same time, the hostname takes precedence. In this circumstance, if the hostname is not in the weaveDNS domain, the container is *not* registered, but it will still use weaveDNS for resolution. +By default, weaveDNS will listen on port 53 on the address of the +Docker bridge. To make it listen on a different address or port use +`weave launch --dns-listen-address
:` + To disable an application container's use of weaveDNS, add the `--without-dns` option to `weave launch`. To disable weaveDNS itself, launch weave with the `--no-dns` option. diff --git a/test/225_dns_subdomain_test.sh b/test/225_dns_subdomain_test.sh index a40f13a4..59a1cd46 100755 --- a/test/225_dns_subdomain_test.sh +++ b/test/225_dns_subdomain_test.sh @@ -13,9 +13,9 @@ start_suite "Resolve names in custom domain with subdomains" weave_on $HOST1 launch --log-level=debug --dns-domain $DOMAIN. -start_container_with_dns $HOST1 $C1/24 --name=c1 -h foo.$SUBDOMAIN1 -start_container_with_dns $HOST1 $C2/24 --name=c2 -h foo.$SUBDOMAIN2 -start_container_with_dns $HOST1 $C3/24 --name=c3 -h tre.$SUBDOMAIN1 --dns-search=$SUBDOMAIN2 +proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C1/24 --name=c1 -h foo.$SUBDOMAIN1 +proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C2/24 --name=c2 -h foo.$SUBDOMAIN2 +proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C3/24 --name=c3 -h tre.$SUBDOMAIN1 --dns-search=$SUBDOMAIN2 assert_dns_record $HOST1 c1 foo.$SUBDOMAIN2 $C2 assert_dns_a_record $HOST1 c3 foo $C2 foo.$SUBDOMAIN2 diff --git a/test/230_dns_unqualified_test.sh b/test/230_dns_unqualified_test.sh index 1c5e9291..802b9916 100755 --- a/test/230_dns_unqualified_test.sh +++ b/test/230_dns_unqualified_test.sh @@ -13,9 +13,9 @@ start_suite "Resolve unqualified names" weave_on $HOST1 launch -start_container $HOST1 $C1/24 --name=c1 -h $NAME -start_container_with_dns $HOST1 $C2/24 --name=c2 -h seetwo.$DOMAIN -start_container_with_dns $HOST1 $C3/24 --name=c3 --dns-search=$DOMAIN +proxy_start_container $HOST1 -e WEAVE_CIDR=$C1/24 --name=c1 -h $NAME +proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C2/24 --name=c2 -h seetwo.$DOMAIN +proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C3/24 --name=c3 --dns-search=$DOMAIN container=$(start_container_with_dns $HOST1 $C4/24) assert_dns_a_record $HOST1 c2 seeone $C1 $NAME diff --git a/test/280_with_or_without_dns_test.sh b/test/280_with_or_without_dns_test.sh index 7ba86452..f71b9271 100755 --- a/test/280_with_or_without_dns_test.sh +++ b/test/280_with_or_without_dns_test.sh @@ -7,14 +7,15 @@ TARGET=seetwo.weave.local TARGET_IP=10.2.0.78 STATIC=static.name STATIC_IP=10.9.9.9 +ATTACH_ARGS="--rewrite-hosts --add-host=$STATIC:$STATIC_IP" check_dns() { chk=$1 shift - container=$(docker_on $HOST1 run $(dns_args $HOST1 "$@") -dt $DNS_IMAGE /bin/sh) - weave_on $HOST1 attach $IP/24 "$@" --rewrite-hosts --add-host=$STATIC:$STATIC_IP $container + container=$(start_container_with_dns $HOST1 "$@" $IP/24) $chk $HOST1 $container $TARGET + # --add-host adds to /etc/hosts so should work even when DNS is off. assert_dns_record $HOST1 $container $STATIC $STATIC_IP rm_containers $HOST1 $container } @@ -22,10 +23,18 @@ check_dns() { start_suite "With or without DNS test" # Assert behaviour without weaveDNS running -weave_on $HOST1 launch +weave_on $HOST1 launch --no-dns start_container $HOST1 $TARGET_IP/24 --name c2 -h $TARGET +check_dns assert_no_dns_record --without-dns +check_dns assert_no_dns_record + +weave_on $HOST1 stop + +# Assert behaviour with weaveDNS +weave_on $HOST1 launch + check_dns assert_no_dns_record --without-dns check_dns assert_dns_record diff --git a/test/config.sh b/test/config.sh index 29958867..f0df952b 100644 --- a/test/config.sh +++ b/test/config.sh @@ -189,7 +189,7 @@ start_container_image() { fi is_cidr "$1" && { cidr=$1; shift; } container=$(docker_on $host run $weave_dns_args $name_args "$@" -dt $image /bin/sh) - if ! weave_on $host attach $cidr $container >/dev/null ; then + if ! weave_on $host attach $cidr $ATTACH_ARGS $container >/dev/null ; then docker_on $host rm -f $container return 1 fi diff --git a/weave b/weave index a8e6fb06..c86aa722 100755 --- a/weave +++ b/weave @@ -43,6 +43,7 @@ weave launch [--password ] [--trusted-subnets ,...] [--host ] [--name ] [--nickname ] [--no-restart] [--resume] [--no-discovery] [--no-dns] + [--dns-listen-address
:] [--ipalloc-init ] [--ipalloc-range [--ipalloc-default-subnet ]] [--plugin=false] [--proxy=false] @@ -775,52 +776,9 @@ dns_args() { DNS_DOMAIN=${DNS_DOMAIN:-$(call_weave GET /domain 2>/dev/null)} || retval=$? [ "$retval" -eq 4 ] && return 0 DNS_DOMAIN=${DNS_DOMAIN:-weave.local.} + DNS_ADDRESS=${DNS_ADDRESS:-$(call_weave GET /dns-address 2>/dev/null)} - NAME_ARG="" - HOSTNAME_SPECIFIED= - DNS_SEARCH_SPECIFIED= - WITHOUT_DNS= - while [ $# -gt 0 ] ; do - case "$1" in - --without-dns) - WITHOUT_DNS=1 - ;; - --name) - NAME_ARG="$2" - shift - ;; - --name=*) - NAME_ARG="${1#*=}" - ;; - -h|--hostname|--hostname=*) - HOSTNAME_SPECIFIED=1 - ;; - --dns-search|--dns-search=*) - DNS_SEARCH_SPECIFIED=1 - ;; - esac - shift - done - [ -n "$WITHOUT_DNS" ] && return 0 - - [ -n "$DOCKER_BRIDGE_IP" ] || DOCKER_BRIDGE_IP=$(util_op bridge-ip $DOCKER_BRIDGE) - DNS_ARGS="--dns=$DOCKER_BRIDGE_IP" - if [ -n "$NAME_ARG" -a -z "$HOSTNAME_SPECIFIED" ] ; then - HOSTNAME="$NAME_ARG.${DNS_DOMAIN%.}" - if [ ${#HOSTNAME} -gt 64 ] ; then - echo "Container name too long to be used as hostname" >&2 - else - DNS_ARGS="$DNS_ARGS --hostname=$HOSTNAME" - HOSTNAME_SPECIFIED=1 - fi - fi - if [ -z "$DNS_SEARCH_SPECIFIED" ] ; then - if [ -z "$HOSTNAME_SPECIFIED" ] ; then - DNS_ARGS="$DNS_ARGS --dns-search=$DNS_DOMAIN" - else - DNS_ARGS="$DNS_ARGS --dns-search=." - fi - fi + DNS_ARGS="--dns=$DNS_ADDRESS --dns-search=$DNS_DOMAIN" } # Iff the container in $1 has an FQDN, invoke $2 as a command passing @@ -1489,8 +1447,8 @@ case "$COMMAND" in ;; dns-lookup) [ $# -eq 1 ] || usage - DOCKER_BRIDGE_IP=$(util_op bridge-ip $DOCKER_BRIDGE) - dig @$DOCKER_BRIDGE_IP +short $1 + DNS_ADDRESS=${DNS_ADDRESS:-$(call_weave GET /dns-address-port 2>/dev/null)} + dig @${DNS_ADDRESS%:*} -p ${DNS_ADDRESS#*:} +short $1 ;; expose) WITHOUT_MASQUERADE=