Skip to content

Commit

Permalink
Merge pull request #15 from atomicbaum1/dns-recursion
Browse files Browse the repository at this point in the history
DNS allow recursion and allow query environment variable support
  • Loading branch information
cytopia authored Jun 10, 2019
2 parents 897a094 + 24a2313 commit c20c0c3
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 6 deletions.
63 changes: 61 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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) <br/>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) <br/>Example: `ALLOW_RECURSION=192.168.1.0/24,127.0.0.1` |
#### DEBUG_ENTRYPOINT

* If set to `0`, only warnings and errors are shown
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
140 changes: 136 additions & 4 deletions data/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
###
Expand Down Expand Up @@ -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 {"
Expand All @@ -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}"
}
Expand Down Expand Up @@ -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
###
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
###
Expand Down

0 comments on commit c20c0c3

Please sign in to comment.