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=