diff --git a/README.md b/README.md
index 8fe793b..7db8334 100644
--- a/README.md
+++ b/README.md
@@ -34,6 +34,8 @@ Bind caching DNS server based on Debian slim with support for DNS forwarders, in
8. [RETRY_TIME](#retry_time)
9. [EXPIRY_TIME](#expiry_time)
10. [MAX_CACHE_TIME](#max_cache_time)
+ 11. [ALLOW_QUERY](#allow_query)
+ 12. [ALLOW_RECURSION](#allow_recursion)
2. [Default mountpoints](#default-mountpoints)
3. [Default ports](#default-ports)
4. [Examples](#examples)
@@ -44,6 +46,7 @@ Bind caching DNS server based on Debian slim with support for DNS forwarders, in
5. [Wildcard TLD and reverse DNS entry](#wildcard-tld-and-reverse-dns-entry)
6. [Wildcard TLD and DNS resolver](#wildcard-tld-and-dns-resolver)
7. [Wildcard TLD, DNS resolver and extra hosts](#wildcard-tld-dns-resolver-and-extra-hosts)
+ 8. [Extra hosts, DNS resolver, allow query, and allow recursion](#extra-hosts-dns-resolver-allow-query-and-allow-recursion)
5. [Host integration](#host-integration)
6. [Support](#support)
7. [License](#license)
@@ -71,7 +74,8 @@ Bind caching DNS server based on Debian slim with support for DNS forwarders, in
| `RETRY_TIME` | int | `180` | (Time in seconds) See [BIND SOA](http://www.zytrax.com/books/dns/ch8/soa.html) |
| `EXPIRY_TIME` | int | `1209600` | (Time in seconds) See [BIND SOA](http://www.zytrax.com/books/dns/ch8/soa.html) |
| `MAX_CACHE_TIME` | int | `10800` | (Time in seconds) See [BIND SOA](http://www.zytrax.com/books/dns/ch8/soa.html) |
-
+| `ALLOW_QUERY` | string | | Specify a comma separated list of IP addresses with optional CIDR mask to allow queries from a specific IP address or ranges of IP addresses. This allows for control over who is allowed to query the DNS server. If not specified all hosts are allowed to make queries (defaults to `any`). See [BIND QUERIES](http://www.zytrax.com/books/dns/ch7/queries.html)
Example: `ALLOW_QUERY=192.168.1.0/24,127.0.0.1` |
+| `ALLOW_RECURSION` | string | | Specify a comma separated list of IP addresses with optional CIDR mask to allow queries from a specific IP address or ranges of IP addresses. This option allows this DNS server to forward a request to another DNS server when an address cannot be resolved. If not present the allow-query-cache default is assumed. See [BIND QUERIES](http://www.zytrax.com/books/dns/ch7/queries.html)
Example: `ALLOW_RECURSION=192.168.1.0/24,127.0.0.1` |
#### DEBUG_ENTRYPOINT
* If set to `0`, only warnings and errors are shown
@@ -180,7 +184,7 @@ The `DNSSEC_VALIDATE` variable defines the DNSSEC validation. Default is to not
Possible values are:
* `yes` - DNSSEC validation is enabled, but a trust anchor must be manually configured. No validation will actually take place.
-* `no` - DNSSEC validation is disabled, and recursive server will behave in the "old fashioned" way of performing insecure DNS lookups, until you have manually configured at least one trusted key.
+* `no` - DNSSEC validation is disabled, and recursive server will behave in the "old fashioned" way of performing insecure DNS lookups, until you have manually configured at least one trusted key.
* `auto` - DNSSEC validation is enabled, and a default trust anchor (included as part of BIND) for the DNS root zone is used.
#### DNS_FORWARDER
@@ -222,6 +226,39 @@ For more information regarding this setting, see [BIND SOA](http://www.zytrax.co
Specify time in seconds.
For more information regarding this setting, see [BIND SOA](http://www.zytrax.com/books/dns/ch8/soa.html)
+#### ALLOW_QUERY
+
+By default this dockerized BIND does not specify query rules. This exposes the
+allow-query options to specify who is allowed to query for results.
+Note that ACLs are not yet handled.
+
+```bash
+# Structure (comma separated list of IP addresses, IP addresses with CIDR mask, or address match list names "none", "any", "localhost", and "localnets")
+ALLOW_QUERY='192.168.1.0/24,127.0.0.1'
+```
+
+Some examples
+```bash
+ALLOW_QUERY='any'
+ALLOW_QUERY='192.168.1.0/24,127.0.0.1'
+```
+
+#### ALLOW_RECURSION
+
+By default this dockerized BIND does not allow DNS recursion. If BIND cannot resolve an address it
+will act as a DNS client and forward the request to another DNS server. This server is specified in the DNS_FORWARDER list.
+Note that ACLs are not yet handled.
+
+```bash
+# Structure (comma separated list of IP addresses, IP addresses with CIDR mask, or address match list names "none", "any", "localhost", and "localnets")
+ALLOW_RECURSION='192.168.1.0/24,127.0.0.1'
+```
+
+Some examples
+```bash
+ALLOW_RECURSION='any'
+ALLOW_RECURSION='192.168.1.0/24,127.0.0.1'
+```
## Default mount points
@@ -338,6 +375,28 @@ $ docker run -i \
-t cytopia/bind
```
+#### Extra hosts, DNS resolver, allow query, and allow recursion
+
+* Your trusted external DNS servers are `8.8.8.8` and `8.8.4.4` (google DNS servers)
+* Allow queries from:
+ - All 192.168.0.xxx addresses
+ - Localhost aka 127.0.0.1
+* Allow recursion to resolve other queries (such as www.google.com) from:
+ - All 192.168.0.xxx addresses
+ - Localhost aka 127.0.0.1
+* Add an extra hosts with custom DNS:
+ - host1 -> 192.168.0.11
+
+```bash
+$ docker run -i \
+ -p 53:53/tcp \
+ -p 53:53/udp \
+ -e EXTRA_HOSTS='host1=192.168.0.11' \
+ -e DNS_FORWARDER=8.8.8.8,8.8.4.4 \
+ -e ALLOW_QUERY=192.168.0.0/24,127.0.0.1 \
+ -e ALLOW_RECURSION=192.168.0.0/24,127.0.0.1 \
+ -t cytopia/bind
+```
## Host integration
diff --git a/data/docker-entrypoint.sh b/data/docker-entrypoint.sh
index 5f8c89b..4c24942 100755
--- a/data/docker-entrypoint.sh
+++ b/data/docker-entrypoint.sh
@@ -132,6 +132,47 @@ is_ip4() {
return 0
}
+###
+### Check if a value is a valid IPv4 address with CIDR mask
+###
+is_ipv4_with_mask() {
+ local string="${1}"
+
+ # http://blog.markhatton.co.uk/2011/03/15/regular-expressions-for-ip-addresses-cidr-ranges-and-hostnames/
+ if ! echo "${1}" | grep -Eq '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))$'; then
+ return 1
+ fi
+
+ # All tests passed
+ return 0
+}
+
+###
+### Check if a value is a valid IPv4 address or IPv4 address with CIDR mask
+###
+is_ipv4_or_mask() {
+ # Is IPv4 or IPv4 with mask
+ if is_ip4 "${1}" || is_ipv4_with_mask "${1}"; then
+ return 0
+ fi
+
+ # Failure
+ return 1
+}
+
+###
+### Check if a value matches any of four predefined address match list names
+###
+is_address_match_list() {
+ # Matches "any" or "none" or "localhost" or "localnets"
+ if [[ "${1}" == "any" || "${1}" == "none" || "${1}" == "localhost" || "${1}" == "localnets" ]] ; then
+ return 0
+ fi
+
+ # Failure
+ return 1
+}
+
###
### Check if a value is a valid cname
###
@@ -160,10 +201,14 @@ is_cname() {
# @param config_file Where to store this configuration in.
# @param dnssec_validate dnssec-validation setting
# @param forwarders formated (newline separated and trailing semi-colon) string of ip addr
+# @param allow_query formated (newline separated and trailing semi-colon) string of ipv4 addr with optional mask
+# @param allow_recursion formated (newline separated and trailing semi-colon) string of ipv4 addr with optional mask
add_options() {
local config_file="${1}"
local dnssec_validate="${2}"
local forwarders="${3}"
+ local allow_query="${4}"
+ local allow_recursion="${5}"
{
echo "options {"
@@ -176,6 +221,17 @@ add_options() {
printf "${forwarders}"
echo " };"
fi
+ if [ -n "${allow_recursion}" ]; then
+ echo " recursion yes;"
+ echo " allow-recursion {"
+ printf "${allow_recursion}"
+ echo " };"
+ fi
+ if [ -n "${allow_query}" ]; then
+ echo " allow-query {"
+ printf "${allow_query}"
+ echo " };"
+ fi
echo "};"
} > "${config_file}"
}
@@ -571,6 +627,84 @@ fi
+###
+### Allow query
+###
+_allow_query_block=""
+if ! printenv ALLOW_QUERY >/dev/null 2>&1; then
+ log "info" "\$ALLOW_QUERY not set." "${DEBUG_ENTRYPOINT}"
+ log "info" "DNS query rules will not be set" "${DEBUG_ENTRYPOINT}"
+else
+ # Transform into newline separated forwards and loop over:
+ # x.x.x.x\n
+ # y.y.y.y\n
+ while read ip ; do
+ ip="$( echo "${ip}" | xargs )"
+
+ if ! is_ipv4_or_mask "${ip}" && ! is_address_match_list "${ip}"; then
+ log "err" "ALLOW_QUERY error: not a valid IPv4 address with optional mask: ${ip}" "${DEBUG_ENTRYPOINT}"
+ exit 1
+ fi
+
+ if [ -z "${_allow_query_block}" ]; then
+ _allow_query_block=" ${ip};"
+ else
+ _allow_query_block="${_allow_query_block}\n ${ip};"
+ fi
+ done <<< "$(echo "$( printenv ALLOW_QUERY )" | sed 's/,/\n/g' )"
+
+
+ if [ -z "${_allow_query_block}" ]; then
+ log "err" "ALLOW_QUERY error: variable specified, but no IP addresses found." "${DEBUG_ENTRYPOINT}"
+ exit 1
+ fi
+
+ log "info" "Adding custom allow-query options: ${ALLOW_QUERY}" "${DEBUG_ENTRYPOINT}"
+ # Add quotes here
+ _allow_query_block="${_allow_query_block}"
+fi
+
+
+
+###
+### Allow recursion
+###
+_allow_recursion_block=""
+if ! printenv ALLOW_RECURSION >/dev/null 2>&1; then
+ log "info" "\$ALLOW_RECURSION not set." "${DEBUG_ENTRYPOINT}"
+ log "info" "DNS recursion rules will not be set" "${DEBUG_ENTRYPOINT}"
+else
+ # Transform into newline separated forwards and loop over:
+ # x.x.x.x\n
+ # y.y.y.y\n
+ while read ip ; do
+ ip="$( echo "${ip}" | xargs )"
+
+ if ! is_ipv4_or_mask "${ip}" && ! is_address_match_list "${ip}"; then
+ log "err" "ALLOW_RECURSION error: not a valid IPv4 address with optional mask: ${ip}" "${DEBUG_ENTRYPOINT}"
+ exit 1
+ fi
+
+ if [ -z "${_allow_recursion_block}" ]; then
+ _allow_recursion_block=" ${ip};"
+ else
+ _allow_recursion_block="${_allow_recursion_block}\n ${ip};"
+ fi
+ done <<< "$(echo "$( printenv ALLOW_RECURSION )" | sed 's/,/\n/g' )"
+
+
+ if [ -z "${_allow_recursion_block}" ]; then
+ log "err" "ALLOW_RECURSION error: variable specified, but no IP addresses found." "${DEBUG_ENTRYPOINT}"
+ exit 1
+ fi
+
+ log "info" "Adding custom allow-recursion options: ${ALLOW_RECURSION}" "${DEBUG_ENTRYPOINT}"
+ # Add quotes here
+ _allow_recursion_block="${_allow_recursion_block}"
+fi
+
+
+
###
### DNSSEC validation
###
@@ -600,7 +734,7 @@ if ! printenv DNS_FORWARDER >/dev/null 2>&1; then
log "info" "\$DNS_FORWARDER not set." "${DEBUG_ENTRYPOINT}"
log "info" "No custom DNS server will be used as forwarder" "${DEBUG_ENTRYPOINT}"
- add_options "${NAMED_OPT_CONF}" "${DNSSEC_VALIDATE}" ""
+ add_options "${NAMED_OPT_CONF}" "${DNSSEC_VALIDATE}" "" "${_allow_query_block}" "${_allow_recursion_block}"
else
# To be pupulated
@@ -631,11 +765,9 @@ else
fi
log "info" "Adding custom DNS forwarder: ${DNS_FORWARDER}" "${DEBUG_ENTRYPOINT}"
- add_options "${NAMED_OPT_CONF}" "${DNSSEC_VALIDATE}" "${_forwarders_block}"
+ add_options "${NAMED_OPT_CONF}" "${DNSSEC_VALIDATE}" "${_forwarders_block}" "${_allow_query_block}" "${_allow_recursion_block}"
fi
-
-
###
### Start
###