unbound: add UCI for forward stub and auth zone clauses

With growing interest, DNS over TLS can be setup in Unbounds foward-zone:
clause. A broader UCI solution is added to support forward-, stub-, and
auth- zone clauses in a new 'zone' section. This implentation required
reworking scripts, because they did not scale. 'forward_domain' and
'prefetch_root' options are removed, and superceded by 'zone' section.

Signed-off-by: Eric Luehrsen <ericluehrsen@gmail.com>
This commit is contained in:
Eric Luehrsen 2018-06-28 20:41:37 -04:00
parent 7bbec3b06b
commit 408047628e
12 changed files with 1380 additions and 1095 deletions

View File

@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=unbound
PKG_VERSION:=1.7.3
PKG_RELEASE:=2
PKG_RELEASE:=3
PKG_LICENSE:=BSD-3-Clause
PKG_LICENSE_FILES:=LICENSE
@ -159,7 +159,7 @@ define Package/unbound/install
$(INSTALL_DATA) ./files/iptools.sh $(1)/usr/lib/unbound/iptools.sh
$(INSTALL_BIN) ./files/odhcpd.sh $(1)/usr/lib/unbound/odhcpd.sh
$(INSTALL_DATA) ./files/odhcpd.awk $(1)/usr/lib/unbound/odhcpd.awk
$(INSTALL_DATA) ./files/rootzone.sh $(1)/usr/lib/unbound/rootzone.sh
$(INSTALL_DATA) ./files/stopping.sh $(1)/usr/lib/unbound/stopping.sh
$(INSTALL_DATA) ./files/unbound.sh $(1)/usr/lib/unbound/unbound.sh
endef

View File

@ -6,7 +6,7 @@
## Package Overview
OpenWrt default build uses [dnsmasq](http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html) for DNS forwarding and DHCP. With a forward only resolver, dependence on the upstream recursors may be cause for concern. They are often provided by the ISP, and some users have switched to public DNS providers. Either way may result in problems due to performance, "snoop-vertising", hijacking (MiM), and other causes. Running a recursive resolver or resolver capable of TLS may be a solution.
Unbound may be useful on consumer grade embedded hardware. It is fully DNSSEC and TLS capable. It is _intended_ to be a recursive resolver only. [NLnet Labs NSD](https://www.nlnetlabs.nl/projects/nsd/) is _intended_ for the authoritative task. This is different than [ISC Bind](https://www.isc.org/downloads/bind/) and its inclusive functions. Unbound configuration effort and memory consumption may be easier to control. A consumer could have their own recursive resolver with 8/64 MB router, and remove potential issues from forwarding resolvers outside of their control.
Unbound may be useful on consumer grade embedded hardware. It is fully DNSSEC and TLS capable. It is _intended_ to be a recursive resolver only. NLnet Labs [NSD](https://www.nlnetlabs.nl/projects/nsd/) is _intended_ for the authoritative task. This is different than [ISC Bind](https://www.isc.org/downloads/bind/) and its inclusive functions. Unbound configuration effort and memory consumption may be easier to control. A consumer could have their own recursive resolver with 8/64 MB router, and remove potential issues from forwarding resolvers outside of their control.
This package builds on Unbounds capabilities with OpenWrt UCI. Not every Unbound option is in UCI, but rather, UCI simplifies the combination of related options. Unbounds native options are bundled and balanced within a smaller set of choices. Options include resources, DNSSEC, access control, and some TTL tweaking. The UCI also provides an escape option and works at the raw "unbound.conf" level.
@ -18,21 +18,21 @@ A few tweaks may be needed to enhance the realiability and effectiveness. Ad Blo
**/etc/config/firewall**:
```
config rule
option name 'Block-Public-DNS'
option enabled '1'
option src 'lan'
option dest 'wan'
option dest_port '53 853 5353'
option proto 'tcpudp'
option family 'any'
option target 'REJECT'
option name 'Block-Public-DNS'
option enabled '1'
option src 'lan'
option dest 'wan'
option dest_port '53 853 5353'
option proto 'tcpudp'
option family 'any'
option target 'REJECT'
```
## HOW TO: Integrate with DHCP
Some UCI options and scripts help Unbound to work with DHCP servers to load the local DNS. The examples provided here are serial dnsmasq-unbound, parallel dnsmasq-unbound, and unbound scripted with odhcpd.
### Serial dnsmasq
In this case, dnsmasq is not changed *much* with respect to the default [OpenWrt configuration](https://openwrt.org/docs/guide-user/base-system/dns_configuration). Here dnsmasq is forced to use the local Unbound instance as the lone upstream DNS server, instead of your ISP. This may be the easiest implementation, but performance degradation can occur in high volume networks. dnsmasq and Unbound effectively have the same information in memory, and all transfers are double handled.
In this case, dnsmasq is not changed *much* with respect to the default [OpenWrt](https://openwrt.org/docs/guide-user/base-system/dns_configuration) configuration. Here dnsmasq is forced to use the local Unbound instance as the lone upstream DNS server, instead of your ISP. This may be the easiest implementation, but performance degradation can occur in high volume networks. Unbound and dnsmasq effectively have the same information in memory, and all transfers are double handled.
**/etc/config/unbound**:
```
@ -120,7 +120,6 @@ config dhcp 'lan'
option leasetime '12h'
option ra 'server'
option ra_management '1'
# odhcpd should issue ULA [fd00::/8] by default
...
config odhcpd 'odhcpd'
@ -151,23 +150,40 @@ You like the UCI. Yet, you need to add some difficult to standardize options, or
The file `unbound_srv.conf` will be added into the `server:` clause. The file `unbound_ext.conf` will be added to the end of all configuration. It is for extended `forward-zone:`, `stub-zone:`, `auth-zone:`, and `view:` clauses. You can also disable unbound-control in the UCI which only allows "localhost" connections unencrypted, and then add an encrypted remote `control:` clause.
#### DNS over TLS
Some public servers are now offering DNS over TLS. Unbound supports acting as DNS over TLS forwarding client. You can use the override files to enable this funciton. Unbound will connect TLS without verifying keys unless you include the PEM path and install `ca-bundle` package. No connection or connection without verification will occur unless you use complete syntax with "@" and "#". See `forward-addr: 1.1.1.1@853#cloudflare-dns.com` for example. Unbound makes a new TLS connection for each query. You limit this effect using large resource and aggressive recursion setting (big cache and prefetching). You can also set memory and recursion to default and edit `unbound_srv.conf` to suit your needs. UCI improvements are in progress but not ready in OpenWrt 18.06.
## HOW TO: Cache Zone Files
Unbound has the ability to AXFR a whole zone from an authoritative server to prefetch the zone. This can speed up access to common zones. Some may have special bandwidth concerns for DNSSEC overhead. The following is a generic example. UCI defaults include the [root](https://www.internic.net/domain/) zone, but it is disabled as a ready to go example.
**/etc/unbound/unbound_srv.conf**:
**/etc/config/unbound**:
```
tls-service-pem: /etc/ssl/certs/ca-certificates.crt
config zone
option enabled '1'
option fallback '1'
option url_dir 'https://asset-management.it.example.com/zones/'
option zone_type 'auth_zone'
list server 'ns1.it.example.com'
list server 'ns2.it.example.com'
list zone_name 'example.com'
```
**/etc/unbound/unbound_ext.conf**:
## HOW TO: TLS Over DNS
Unbound has the ability to be client and server in TLS mode. UCI can configure Unbound to be a client forwarding queries in TLS mode for selected domains. (Server is more complex to setup and needs to be done manually). This may be desired for privacy against stealth market tracking in some cases. Some public DNS servers seem to advertise help in this quest.
Unbound will make TLS connections without validation unless you install the 'ca-bundle' package. Do **not** however forget to maintain the certification bundle. The validation chain otherwise will expire and connections will go dead. Unbound makes and breaks TCP connections per connection. To reduce the lag from TLS handshaking it may help to use more cache memory `resource`, increase record exirations `ttl_min`, enable `aggressive` searching, or manually enable prefetch options.
The following is a generic example. If your looking for a better understanding, then some information can be found at [Cloudflare](https://www.cloudflare.com/) DNS [1.1.1.1](https://1.1.1.1/) for one place.
**/etc/config/unbound**:
```
forward-zone:
name: .
forward-addr: 1.1.1.1@853#cloudflare-dns.com
forward-addr: 1.0.0.1@853#cloudflare-dns.com
forward-addr: 2606:4700:4700::1111@853#cloudflare-dns.com
forward-addr: 2606:4700:4700::1001@853#cloudflare-dns.com
forward-tls-upstream: yes
config zone
option enabled '1'
# question: do you want to recurse when TLS fails or not?
option fallback '0'
option tls_index 'dns.example.net'
option tls_upstream '1'
option zone_type 'forward_zone'
list server '192.0.2.53'
list server '2001:db8::53'
list zone_name '.'
```
## Complete List of UCI Options
@ -234,9 +250,6 @@ config unbound
Bytes. Extended DNS is necessary for DNSSEC. However, it can run
into MTU issues. Use this size in bytes to manage drop outs.
option extended_luci '0'
Boolean. Extends a tab hierarchy in LuCI for advanced configuration.
option extended_stats '0'
Boolean. extended statistics are printed from unbound-control.
Keeping track of more statistics takes time.
@ -256,11 +269,6 @@ config unbound
Boolean. Skip all this UCI nonsense. Manually edit the
configuration. Make changes to /etc/unbound/unbound.conf.
option prefetch_root '0'
Boolean. Cache the entire root. Enable Unbound `auth-zone:` clauses for
"." (root), "arpa," "in-addr.arpa," and "ip6.arpa." Obtain complete zone
files from public servers using http or AXFR. (see RFC7706)
option protocol 'mixed'
Unbound can limit its protocol used for recursive queries.
ip4_only - limit issues if you do not have native IPv6
@ -336,23 +344,83 @@ config unbound
embedded devices don't have a real time power off clock. NTP needs
DNS to resolve servers. This works around the chicken-and-egg.
list domain_forward 'mail.my-isp.com'
Domain. Do not recurse, but rather forward the domains to given DNS
servers found in resolve.conf.auto from WAN DHCP client. This may
provide better access to mirror servers in 'your neigborhood.' This
may be useful in keeping local organization lookups on local subnets.
option verbosity '1'
Level. Sets Unbounds logging intensity.
list domain_insecure 'ntp.somewhere.org'
Domain. Domains that you wish to skip DNSSEC. It is one way around NTP
chicken and egg. Your DHCP servered domains are automatically included.
list rebind_interface 'lan'
Interface (logical). Works with 'rebind_protection' options 2 and 3.
list trigger_interface 'lan' 'wan'
Interface (logical). This option is a work around for netifd/procd
interaction with WAN DHCPv6. Minor RA or DHCP changes in IP6 can
cause netifd to execute procd interface reload. Limit Unbound procd
triggers to LAN and WAN (IP4 only) to prevent restart @2-3 minutes.
config zone
Create Unbounds forward-zone:, stub-zone:, or auth-zone: clauses
option enabled 1
Boolean. Enable the zone clause.
option fallback 1
Boolean. Permit normal recursion when the narrowly selected servers
in this zone are unresponsive or return empty responses. Disable, if
there are security concerns (forward only internal to organization).
option port 53
Port. Servers are contact on this port for plain DNS operations.
option resolv_conf 0
Boolean. Use "resolv.conf" as it was filled by the DHCP client. This
can be used to forward zones within your ISP (mail.example.net) or that
have co-located services (streamed-movies.example.com). Recursion may
not yield the most local result, but forwarding may instead.
option tls_index (n/a)
Domain. Name TLS certificates are signed for (dns.example.net). If this
option is ommitted, then Unbound will make the connection but not
validate it.
option tls_port 853
Port. Servers are contact on this port for DNS over TLS operations.
option tls_upstream 0
Boolean. Use TLS to contact the zone server.
option url_dir
String. http or https path, directory part only, to the zone file for
auth_zone type only. Files "${zone_name}.zone" are expect in this path.
option zone_type (n/a)
State. Required field or the clause is effectively disabled. Check
Unbound documentation for clarity (unbound-conf).
auth_zone - prefetch whole zones from authoritative server (ICANN)
forward_zone - forward queries in these domains to the listed servers
stub_zone - force recursion of these domains to the listed servers
list server (n/a)
IP. Every zone must have one server. Stub and forward require IP to
prevent chicken and egg (due to UCI simplicity). Authoritative prefetch
may use a server name.
list zone_name
Domain. Every zone must represent some part of the DNS tree. It can be
all of it "." or you internal organization domain "example.com." Within
each zone clause all zone names will be matched to all servers.
```
## Replaced Options
config unbound / option prefetch_root
List the domains in a zone with type auth_zone and fill in the server
or url fields. Root zones are ready but disabled in default install UCI.
config unbound / list domain_forward
List the domains in a zone with type forward_zone and enable the
resolv_conf option.
config unbound / list rebind_interface
Enable rebind_protection at 2 and all DHCP interfaces are also
protected for IPV6 GLA (parallel to subnets in add_local_fqdn).

View File

@ -14,30 +14,52 @@
#
##############################################################################
UNBOUND_LIBDIR=/usr/lib/unbound
UNBOUND_VARDIR=/var/lib/unbound
# where are we?
UB_LIBDIR=/usr/lib/unbound
UB_VARDIR=/var/lib/unbound
UB_PIDFILE=/var/run/unbound.pid
UNBOUND_PIDFILE=/var/run/unbound.pid
# conf deconstructed
UB_TOTAL_CONF=$UB_VARDIR/unbound.conf
UB_CORE_CONF=$UB_VARDIR/server.conf.tmp
UB_HOST_CONF=$UB_VARDIR/host.conf.tmp
UB_DHCP_CONF=$UB_VARDIR/dhcp.conf
UB_ZONE_CONF=$UB_VARDIR/zone.conf.tmp
UB_CTRL_CONF=$UB_VARDIR/ctrl.conf.tmp
UB_SRVMASQ_CONF=$UB_VARDIR/dnsmasq_srv.conf.tmp
UB_EXTMASQ_CONF=$UB_VARDIR/dnsmasq_ext.conf.tmp
UB_SRV_CONF=$UB_VARDIR/unbound_srv.conf
UB_EXT_CONF=$UB_VARDIR/unbound_ext.conf
UNBOUND_SRV_CONF=$UNBOUND_VARDIR/unbound_srv.conf
UNBOUND_EXT_CONF=$UNBOUND_VARDIR/unbound_ext.conf
UNBOUND_DHCP_CONF=$UNBOUND_VARDIR/unbound_dhcp.conf
UNBOUND_CONFFILE=$UNBOUND_VARDIR/unbound.conf
# TLS keys
UB_TLS_KEY_FILE="TLS server UCI not implemented"
UB_TLS_PEM_FILE="TLS server UCI not implemented"
UB_TLS_FWD_FILE=$UB_VARDIR/ca-certificates.crt
UB_TLS_ETC_FILE=/etc/ssl/certs/ca-certificates.crt
UNBOUND_KEYFILE=$UNBOUND_VARDIR/root.key
UNBOUND_HINTFILE=$UNBOUND_VARDIR/root.hints
UNBOUND_TIMEFILE=$UNBOUND_VARDIR/hotplug.time
# start files
UB_RKEY_FILE=$UB_VARDIR/root.key
UB_RHINT_FILE=$UB_VARDIR/root.hints
UB_TIME_FILE=$UB_VARDIR/hotplug.time
UNBOUND_CTLKEY_FILE=$UNBOUND_VARDIR/unbound_control.key
UNBOUND_CTLPEM_FILE=$UNBOUND_VARDIR/unbound_control.pem
UNBOUND_SRVKEY_FILE=$UNBOUND_VARDIR/unbound_server.key
UNBOUND_SRVPEM_FILE=$UNBOUND_VARDIR/unbound_server.pem
##############################################################################
UNBOUND_ANCHOR=/usr/sbin/unbound-anchor
UNBOUND_CONTROL=/usr/sbin/unbound-control
UNBOUND_CONTROL_CFG="$UNBOUND_CONTROL -c $UNBOUND_CONFFILE"
# control app keys
UB_CTLKEY_FILE=$UB_VARDIR/unbound_control.key
UB_CTLPEM_FILE=$UB_VARDIR/unbound_control.pem
UB_SRVKEY_FILE=$UB_VARDIR/unbound_server.key
UB_SRVPEM_FILE=$UB_VARDIR/unbound_server.pem
# similar default SOA / NS RR as Unbound uses for private ARPA zones
UB_XSER=$(( $( date +%s ) / 60 ))
UB_XSOA="7200 IN SOA localhost. nobody.invalid. $UB_XSER 3600 1200 9600 600"
UB_XNS="7200 IN NS localhost."
UB_XTXT="7200 IN TXT \"comment=local intranet dns zone\""
UB_MTXT="7200 IN TXT \"comment=masked internet dns zone\""
UB_LTXT="7200 IN TXT \"comment=rfc6762 multicast dns zone\""
# helper apps
UB_ANCHOR=/usr/sbin/unbound-anchor
UB_CONTROL=/usr/sbin/unbound-control
UB_CONTROL_CFG="$UB_CONTROL -c $UB_TOTAL_CONF"
##############################################################################

View File

@ -23,6 +23,140 @@
#
##############################################################################
DM_D_WAN_FQDN=0
DM_LIST_KNOWN_ZONES="invalid"
DM_LIST_TRN_ZONES=""
DM_LIST_LOCAL_DATA=""
DM_LIST_LOCAL_PTR=""
DM_LIST_FWD_PORTS=""
DM_LIST_FWD_ZONES=""
##############################################################################
create_local_zone() {
local target="$1"
local partial domain found
case $DM_LIST_TRN_ZONES in
*"${target}"*)
found=1
;;
*)
case $target in
[A-Za-z0-9]*.[A-Za-z0-9]*)
found=0
;;
*) # no dots
found=1
;;
esac
esac
if [ $found -eq 0 ] ; then
# New Zone! Bundle local-zones: by first two name tiers "abcd.tld."
partial=$( echo "$target" | awk -F. '{ j=NF ; i=j-1; print $i"."$j }' )
DM_LIST_TRN_ZONES="$DM_LIST_TRN_ZONES $partial"
DM_LIST_KNOWN_ZONES="$DM_LIST_KNOWN_ZONES $partial"
fi
}
##############################################################################
create_host_record() {
local cfg="$1"
local ip name debug_ip
# basefiles dhcp "domain" clause which means host A, AAAA, and PRT record
config_get ip "$cfg" ip
config_get name "$cfg" name
if [ -n "$name" -a -n "$ip" ] ; then
create_local_zone "$name"
case $ip in
fe80:*|169.254.*)
debug_ip="$ip@$host"
;;
[1-9a-f]*:*[0-9a-f])
DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $name.@@300@@IN@@AAAA@@$ip"
DM_LIST_LOCAL_PTR="$DM_LIST_LOCAL_PTR $ip@@300@@$name"
;;
[1-9]*.*[0-9])
DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $name.@@300@@IN@@A@@$ip"
DM_LIST_LOCAL_PTR="$DM_LIST_LOCAL_PTR $ip@@300@@$name"
;;
esac
fi
}
##############################################################################
create_mx_record() {
local cfg="$1"
local domain relay pref record
# Insert a static MX record
config_get domain "$cfg" domain
config_get relay "$cfg" relay
config_get pref "$cfg" pref 10
if [ -n "$domain" -a -n "$relay" ] ; then
create_local_zone "$domain"
record="$domain.@@300@@IN@@MX@@$pref@@$relay."
DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $record"
fi
}
##############################################################################
create_srv_record() {
local cfg="$1"
local srv target port class weight record
# Insert a static SRV record such as SIP server
config_get srv "$cfg" srv
config_get target "$cfg" target
config_get port "$cfg" port
config_get class "$cfg" class 10
config_get weight "$cfg" weight 10
if [ -n "$srv" -a -n "$target" -a -n "$port" ] ; then
create_local_zone "$srv"
record="$srv.@@300@@IN@@SRV@@$class@@$weight@@$port@@$target."
DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $record"
fi
}
##############################################################################
create_cname_record() {
local cfg="$1"
local cname target record
# Insert static CNAME record
config_get cname "$cfg" cname
config_get target "$cfg" target
if [ -n "$cname" -a -n "$target" ] ; then
create_local_zone "$cname"
record="$cname.@@300@@IN@@CNAME@@$target."
DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $record"
fi
}
##############################################################################
dnsmasq_local_zone() {
local cfg="$1"
local fwd_port fwd_domain wan_fqdn
@ -34,130 +168,127 @@ dnsmasq_local_zone() {
if [ -n "$wan_fqdn" ] ; then
UNBOUND_D_WAN_FQDN=$wan_fqdn
DM_D_WAN_FQDN=$wan_fqdn
fi
if [ -n "$fwd_domain" -a -n "$fwd_port" -a ! "${fwd_port:-53}" -eq 53 ] ; then
# dnsmasq localhost listening ports (possible multiple instances)
UNBOUND_N_FWD_PORTS="$UNBOUND_N_FWD_PORTS $fwd_port"
UNBOUND_TXT_FWD_ZONE="$UNBOUND_TXT_FWD_ZONE $fwd_domain"
{
# This creates DOMAIN local privledges
echo " private-domain: \"$fwd_domain\""
echo " local-zone: \"$fwd_domain.\" transparent"
echo " domain-insecure: \"$fwd_domain\""
echo
} >> $UNBOUND_CONFFILE
DM_LIST_FWD_PORTS="$DM_LIST_FWD_PORTS $fwd_port"
DM_LIST_FWD_ZONES="$DM_LIST_FWD_ZONES $fwd_domain"
fi
}
##############################################################################
dnsmasq_local_arpa() {
local cfg="$1"
local logint dhcpv4 dhcpv6 ignore
local subnets subnets4 subnets6
local forward arpa
local validip4 validip6 privateip
config_get logint "$cfg" interface
config_get dhcpv4 "$cfg" dhcpv4
config_get dhcpv6 "$cfg" dhcpv6
config_get_bool ignore "$cfg" ignore 0
# Find the list of addresses assigned to a logical interface
# Its typical to have a logical gateway split NAME and NAME6
network_get_subnets subnets4 "$logint"
network_get_subnets6 subnets6 "$logint"
subnets="$subnets4 $subnets6"
network_get_subnets subnets4 "${logint}6"
network_get_subnets6 subnets6 "${logint}6"
subnets="$subnets $subnets4 $subnets6"
local ifarpa ifsubnet
if [ -z "$subnets" ] ; then
forward=""
elif [ -z "$UNBOUND_N_FWD_PORTS" ] ; then
forward=""
elif [ "$ignore" -gt 0 ] ; then
if [ "$UNBOUND_D_WAN_FQDN" -gt 0 ] ; then
# Only forward the one gateway host.
forward="host"
else
forward=""
fi
else
# Forward the entire private subnet.
forward="domain"
if [ -n "$UB_LIST_NETW_LAN" ] ; then
for ifsubnet in $UB_LIST_NETW_LAN ; do
ifarpa=$( domain_ptr_any "${ifsubnet#*@}" )
DM_LIST_FWD_ZONES="$DM_LIST_FWD_ZONES $ifarpa"
done
fi
if [ -n "$forward" ] ; then
for subnet in $subnets ; do
validip4=$( valid_subnet4 $subnet )
validip6=$( valid_subnet6 $subnet )
privateip=$( private_subnet $subnet )
if [ "$validip4" = "ok" -a "$dhcpv4" != "disable" ] ; then
if [ "$forward" = "domain" ] ; then
arpa=$( domain_ptr_ip4 "$subnet" )
else
arpa=$( host_ptr_ip4 "$subnet" )
fi
elif [ "$validip6" = "ok" -a "$dhcpv6" != "disable" ] ; then
if [ "$forward" = "domain" ] ; then
arpa=$( domain_ptr_ip6 "$subnet" )
else
arpa=$( host_ptr_ip6 "$subnet" )
fi
else
arpa=""
fi
if [ -n "$arpa" ] ; then
if [ "$privateip" = "ok" ] ; then
{
# This creates ARPA local zone privledges
echo " local-zone: \"$arpa.\" transparent"
echo " domain-insecure: \"$arpa\""
echo
} >> $UNBOUND_CONFFILE
fi
UNBOUND_TXT_FWD_ZONE="$UNBOUND_TXT_FWD_ZONE $arpa"
fi
if [ -n "$UB_LIST_NETW_WAN" -a "$DM_D_WAN_FQDN" -gt 0 ] ; then
for ifsubnet in $UB_LIST_NETW_WAN ; do
ifarpa=$( domain_ptr_any "${ifsubnet#*@}" )
DM_LIST_FWD_ZONES="$DM_LIST_FWD_ZONES $ifarpa"
done
fi
}
##############################################################################
dnsmasq_forward_zone() {
if [ -n "$UNBOUND_N_FWD_PORTS" -a -n "$UNBOUND_TXT_FWD_ZONE" ] ; then
for fwd_domain in $UNBOUND_TXT_FWD_ZONE ; do
{
# This is derived of dnsmasq_local_zone/arpa
# but forward: clauses need to be seperate
echo "forward-zone:"
echo " name: \"$fwd_domain.\""
dnsmasq_inactive() {
local record
for port in $UNBOUND_N_FWD_PORTS ; do
if [ "$UB_D_EXTRA_DNS" -gt 0 ] ; then
# Parasite from the uci.dhcp.domain clauses
DM_LIST_KNOWN_ZONES="$DM_LIST_KNOWN_ZONES $UB_TXT_DOMAIN"
config_load dhcp
config_foreach create_host_record domain
if [ "$UB_D_EXTRA_DNS" -gt 1 ] ; then
config_foreach create_srv_record srvhost
config_foreach create_mx_record mxhost
fi
if [ "$UB_D_EXTRA_DNS" -gt 2 ] ; then
config_foreach create_cname_record cname
fi
{
echo "# $UB_SRVMASQ_CONF generated by UCI $( date -Is )"
if [ -n "$DM_LIST_TRN_ZONES" ] ; then
for record in $DM_LIST_TRN_ZONES ; do
echo " local-zone: $record transparent"
done
echo
fi
if [ -n "$DM_LIST_LOCAL_DATA" ] ; then
for record in $DM_LIST_LOCAL_DATA ; do
echo " local-data: \"${record//@@/ }\""
done
echo
fi
if [ -n "$DM_LIST_LOCAL_PTR" ] ; then
for record in $DM_LIST_LOCAL_PTR ; do
echo " local-data-ptr: \"${record//@@/ }\""
done
echo
fi
} > $UB_SRVMASQ_CONF
fi
}
##############################################################################
dnsmasq_active() {
# Look at dnsmasq settings
config_load dhcp
# Zone for DHCP / SLAAC-PING DOMAIN
config_foreach dnsmasq_local_zone dnsmasq
# Zone for DHCP / SLAAC-PING ARPA
dnsmasq_local_arpa
if [ -n "$DM_LIST_FWD_PORTS" -a -n "$DM_LIST_FWD_ZONES" ] ; then
{
# Forward to dnsmasq on same host for DHCP lease hosts
echo "# $UB_SRVMASQ_CONF generated by UCI $( date -Is )"
echo " do-not-query-localhost: no"
echo
} > $UB_SRVMASQ_CONF
echo "# $UB_EXTMASQ_CONF generated by UCI $( date -Is )" > $UB_EXTMASQ_CONF
for fwd_domain in $DM_LIST_FWD_ZONES ; do
{
# This creates a domain with local privledges
echo " domain-insecure: $fwd_domain"
echo " private-domain: $fwd_domain"
echo " local-zone: $fwd_domain transparent"
echo
} >> $UB_SRVMASQ_CONF
{
# This is derived from dnsmasq local domain and dhcp service subnets
echo "forward-zone:"
echo " name: $fwd_domain"
echo " forward-first: no"
for port in $DM_LIST_FWD_PORTS ; do
echo " forward-addr: 127.0.0.1@$port"
done
echo
} >> $UNBOUND_CONFFILE
} >> $UB_EXTMASQ_CONF
done
fi
}
@ -165,16 +296,12 @@ dnsmasq_forward_zone() {
##############################################################################
dnsmasq_link() {
# Forward to dnsmasq on same host for DHCP lease hosts
echo " do-not-query-localhost: no" >> $UNBOUND_CONFFILE
# Look at dnsmasq settings
config_load dhcp
# Zone for DHCP / SLAAC-PING DOMAIN
config_foreach dnsmasq_local_zone dnsmasq
# Zone for DHCP / SLAAC-PING ARPA
config_foreach dnsmasq_local_arpa dhcp
# Now create ALL seperate forward: clauses
dnsmasq_forward_zone
if [ "$UB_D_DHCP_LINK" = "dnsmasq" ] ; then
dnsmasq_active
else
dnsmasq_inactive
fi
}
##############################################################################

View File

@ -160,3 +160,25 @@ domain_ptr_any() {
##############################################################################
host_ptr_any() {
local subnet=$1
local arpa validip4 validip6
validip4=$( valid_subnet4 $subnet )
validip6=$( valid_subnet6 $subnet )
if [ "$validip4" = "ok" ] ; then
arpa=$( host_ptr_ip4 "$subnet" )
elif [ "$validip6" = "ok" ] ; then
arpa=$( host_ptr_ip6 "$subnet" )
fi
if [ -n "$arpa" ] ; then
echo $arpa
fi
}
##############################################################################

View File

@ -66,15 +66,15 @@
if ( bconf == 1 ) {
x = ( "local-data: \"" fqdn ". 120 IN A " adr "\"" ) ;
y = ( "local-data-ptr: \"" adr " 120 " fqdn "\"" ) ;
x = ( "local-data: \"" fqdn ". 300 IN A " adr "\"" ) ;
y = ( "local-data-ptr: \"" adr " 300 " fqdn "\"" ) ;
print ( x "\n" y "\n" ) > hostfile ;
}
else {
for( i=1; i<=4; i++ ) { qpr = ( ptr[i] "." qpr) ; }
x = ( fqdn ". 120 IN A " adr ) ;
y = ( qpr "in-addr.arpa. 120 IN PTR " fqdn ) ;
x = ( fqdn ". 300 IN A " adr ) ;
y = ( qpr "in-addr.arpa. 300 IN PTR " fqdn ) ;
print ( x "\n" y ) > hostfile ;
}
@ -100,15 +100,15 @@
if ( bconf == 1 ) {
x = ( "local-data: \"" fqdn ". 120 IN AAAA " adr "\"" ) ;
y = ( "local-data-ptr: \"" adr " 120 " fqdn "\"" ) ;
x = ( "local-data: \"" fqdn ". 300 IN AAAA " adr "\"" ) ;
y = ( "local-data-ptr: \"" adr " 300 " fqdn "\"" ) ;
print ( x "\n" y "\n" ) > hostfile ;
}
else {
qpr = ipv6_ptr( adr ) ;
x = ( fqdn ". 120 IN AAAA " adr ) ;
y = ( qpr ". 120 IN PTR " fqdn ) ;
x = ( fqdn ". 300 IN AAAA " adr ) ;
y = ( qpr ". 300 IN PTR " fqdn ) ;
print ( x "\n" y ) > hostfile ;
}
}
@ -123,32 +123,32 @@
else {
if (( cdr == 128 ) && ( hst != "-" )) {
if ( bconf == 1 ) {
x = ( "local-data: \"" fqdn ". 120 IN AAAA " adr "\"" ) ;
y = ( "local-data-ptr: \"" adr " 120 " fqdn "\"" ) ;
x = ( "local-data: \"" fqdn ". 300 IN AAAA " adr "\"" ) ;
y = ( "local-data-ptr: \"" adr " 300 " fqdn "\"" ) ;
print ( x "\n" y "\n" ) > hostfile ;
}
else {
# only for provided hostnames and full /128 assignments
qpr = ipv6_ptr( adr ) ;
x = ( fqdn ". 120 IN AAAA " adr ) ;
y = ( qpr ". 120 IN PTR " fqdn ) ;
x = ( fqdn ". 300 IN AAAA " adr ) ;
y = ( qpr ". 300 IN PTR " fqdn ) ;
print ( x "\n" y ) > hostfile ;
}
}
if (( cdr2 == 128 ) && ( hst != "-" )) {
if ( bconf == 1 ) {
x = ( "local-data: \"" fqdn ". 120 IN AAAA " adr2 "\"" ) ;
y = ( "local-data-ptr: \"" adr2 " 120 " fqdn "\"" ) ;
x = ( "local-data: \"" fqdn ". 300 IN AAAA " adr2 "\"" ) ;
y = ( "local-data-ptr: \"" adr2 " 300 " fqdn "\"" ) ;
print ( x "\n" y "\n" ) > hostfile ;
}
else {
# odhcp puts GA and ULA on the same line (position 9 and 10)
qpr2 = ipv6_ptr( adr2 ) ;
x = ( fqdn ". 120 IN AAAA " adr2 ) ;
y = ( qpr2 ". 120 IN PTR " fqdn ) ;
x = ( fqdn ". 300 IN AAAA " adr2 ) ;
y = ( qpr2 ". 300 IN PTR " fqdn ) ;
print ( x "\n" y ) > hostfile ;
}
}

View File

@ -30,12 +30,12 @@
odhcpd_zonedata() {
local longconf dateconf
local dns_ls_add=$UNBOUND_VARDIR/dhcp_dns.add
local dns_ls_del=$UNBOUND_VARDIR/dhcp_dns.del
local dhcp_ls_new=$UNBOUND_VARDIR/dhcp_lease.new
local dhcp_ls_old=$UNBOUND_VARDIR/dhcp_lease.old
local dhcp_ls_add=$UNBOUND_VARDIR/dhcp_lease.add
local dhcp_ls_del=$UNBOUND_VARDIR/dhcp_lease.del
local dns_ls_add=$UB_VARDIR/dhcp_dns.add
local dns_ls_del=$UB_VARDIR/dhcp_dns.del
local dhcp_ls_new=$UB_VARDIR/dhcp_lease.new
local dhcp_ls_old=$UB_VARDIR/dhcp_lease.old
local dhcp_ls_add=$UB_VARDIR/dhcp_lease.add
local dhcp_ls_del=$UB_VARDIR/dhcp_lease.del
local dhcp_link=$( uci_get unbound.@unbound[0].dhcp_link )
local dhcp4_slaac6=$( uci_get unbound.@unbound[0].dhcp4_slaac6 )
@ -43,18 +43,17 @@ odhcpd_zonedata() {
local dhcp_origin=$( uci_get dhcp.@odhcpd[0].leasefile )
if [ "$dhcp_link" = "odhcpd" \
-a -f "$dhcp_origin" \
-a -n "$dhcp_domain" ] ; then
if [ -f "$UB_TIME_FILE" -a "$dhcp_link" = "odhcpd" \
-a -f "$dhcp_origin" -a -n "$dhcp_domain" ] ; then
# Capture the lease file which could be changing often
sort $dhcp_origin > $dhcp_ls_new
if [ ! -f $UNBOUND_DHCP_CONF -o ! -f $dhcp_ls_old ] ; then
if [ ! -f $UB_DHCP_CONF -o ! -f $dhcp_ls_old ] ; then
longconf=2
else
dateconf=$(( $( date +%s ) - $( date -r $UNBOUND_DHCP_CONF +%s ) ))
dateconf=$(( $( date +%s ) - $( date -r $UB_DHCP_CONF +%s ) ))
if [ $dateconf > 150 ] ; then
@ -68,7 +67,7 @@ odhcpd_zonedata() {
if [ $longconf -gt 0 ] ; then
# Go through the messy business of coding up A, AAAA, and PTR records
# This static conf will be available if Unbound restarts asynchronously
awk -v hostfile=$UNBOUND_DHCP_CONF -v domain=$dhcp_domain \
awk -v hostfile=$UB_DHCP_CONF -v domain=$dhcp_domain \
-v bslaac=$dhcp4_slaac6 -v bisolt=0 -v bconf=1 \
-f /usr/lib/unbound/odhcpd.awk $dhcp_ls_new
fi
@ -95,12 +94,12 @@ odhcpd_zonedata() {
if [ -f "$dns_ls_del" ] ; then
cat $dns_ls_del | $UNBOUND_CONTROL_CFG local_datas_remove
cat $dns_ls_del | $UB_CONTROL_CFG local_datas_remove
fi
if [ -f "$dns_ls_add" ] ; then
cat $dns_ls_add | $UNBOUND_CONTROL_CFG local_datas
cat $dns_ls_add | $UB_CONTROL_CFG local_datas
fi

View File

@ -19,6 +19,10 @@
#
##############################################################################
. /usr/lib/unbound/defaults.sh
##############################################################################
roothints_update() {
# TODO: Might not be implemented. Unbound doesn't natively update hints.
# Unbound philosophy is built in root hints are good for machine life.
@ -29,17 +33,21 @@ roothints_update() {
rootkey_update() {
local basekey_date rootkey_date rootkey_age filestuff
local dnssec=$( uci_get unbound.@unbound[0].validator )
local dnssec_ntp=$( uci_get unbound.@unbound[0].validator_ntp )
local dnssec_age=$( uci_get unbound.@unbound[0].root_age )
# fix empty
[ -z "$dnssec" ] && dnssec=0
[ -z "$dnssec_ntp" ] && dnssec_ntp=1
[ -z "$dnssec_age" ] && dnssec_age=9
if [ "$dnssec_age" -gt 90 -o "$dnssec" -lt 1 ] ; then
# Feature disabled
return 0
elif [ "$dnssec_ntp" -gt 0 -a ! -f "$UNBOUND_TIMEFILE" ] ; then
elif [ "$dnssec_ntp" -gt 0 -a ! -f "$UB_TIME_FILE" ] ; then
# We don't have time yet
return 0
fi
@ -54,16 +62,16 @@ rootkey_update() {
fi
if [ -f "$UNBOUND_KEYFILE" ] ; then
if [ -f "$UB_RKEY_FILE" ] ; then
# Unbound maintains it itself
rootkey_date=$( date -r $UNBOUND_KEYFILE +%s )
rootkey_date=$( date -r $UB_RKEY_FILE +%s )
rootkey_age=$(( (rootkey_date - basekey_date) / 86440 ))
elif [ -x "$UNBOUND_ANCHOR" ] ; then
elif [ -x "$UB_ANCHOR" ] ; then
# No tmpfs key - use unbound-anchor
rootkey_date=$( date -I +%s )
rootkey_age=$(( (rootkey_date - basekey_date) / 86440 ))
$UNBOUND_ANCHOR -a $UNBOUND_KEYFILE
$UB_ANCHOR -a $UB_RKEY_FILE
else
# give up
@ -72,20 +80,20 @@ rootkey_update() {
if [ "$rootkey_age" -gt "$dnssec_age" ] ; then
filestuff=$( cat $UNBOUND_KEYFILE )
filestuff=$( cat $UB_RKEY_FILE )
case "$filestuff" in
*NOERROR*)
# Header comment for drill and dig
logger -t unbound -s "root.key updated after $rootkey_age days"
cp -p $UNBOUND_KEYFILE /etc/unbound/root.key
cp -p $UB_RKEY_FILE /etc/unbound/root.key
;;
*"state=2 [ VALID ]"*)
# Comment inline to key for unbound-anchor
logger -t unbound -s "root.key updated after $rootkey_age days"
cp -p $UNBOUND_KEYFILE /etc/unbound/root.key
cp -p $UB_RKEY_FILE /etc/unbound/root.key
;;
*)
@ -97,7 +105,20 @@ rootkey_update() {
##############################################################################
rootzone_update() {
resolv_teardown() {
case $( cat /tmp/resolv.conf ) in
*"generated by Unbound UCI"*)
# our resolver file, reset to auto resolver file.
rm -f /tmp/resolv.conf
ln -s /tmp/resolv.conf.auto /tmp/resolv.conf
;;
esac
}
##############################################################################
unbound_stop() {
resolv_teardown
roothints_update
rootkey_update
}

View File

@ -17,14 +17,14 @@ PROG=/usr/sbin/unbound
##############################################################################
boot() {
UNBOUND_BOOT=1
UB_BOOT=1
start "$@"
}
##############################################################################
start_service() {
if [ -n "$UNBOUND_BOOT" ] ; then
if [ -n "$UB_BOOT" ] ; then
# Load procd triggers (rc) and use event IFUP to really start
return 0
fi
@ -35,7 +35,7 @@ start_service() {
# standard procd clause
procd_open_instance "unbound"
procd_set_param command $PROG -d -c $UNBOUND_CONFFILE
procd_set_param command $PROG -d -c $UB_TOTAL_CONF
procd_set_param respawn
procd_close_instance
}
@ -44,7 +44,7 @@ start_service() {
stop_service() {
# clean up
. /usr/lib/unbound/unbound.sh
. /usr/lib/unbound/stopping.sh
unbound_stop
# Wait! on restart Unbound may take time writing closure stats to syslog

View File

@ -13,12 +13,12 @@
##############################################################################
# Common file location definitions
. /usr/lib/unbound/unbound.sh
. /usr/lib/unbound/defaults.sh
##############################################################################
if [ "$ACTION" = stratum -a ! -f "$UNBOUND_TIMEFILE" ] ; then
echo "ntpd: $( date )" > $UNBOUND_TIMEFILE
if [ ! -f "$UB_TIME_FILE" -a "$ACTION" = stratum ] ; then
date -Is > $UB_TIME_FILE
/etc/init.d/unbound enabled && /etc/init.d/unbound restart
# Yes, hard RESTART. We need to be absolutely sure to enable DNSSEC.
fi

File diff suppressed because it is too large Load Diff

View File

@ -9,13 +9,11 @@ config unbound
option domain 'lan'
option domain_type 'static'
option edns_size '1280'
option extended_luci '0'
option extended_stats '0'
option hide_binddata '1'
option listen_port '53'
option localservice '1'
option manual_conf '0'
option prefetch_root '0'
option protocol 'default'
option query_minimize '0'
option query_min_strict '0'
@ -28,9 +26,28 @@ config unbound
option unbound_control '0'
option validator '0'
option validator_ntp '1'
option verbosity '1'
list trigger_interface 'lan'
list trigger_interface 'wan'
#list rebind_interface 'lan'
#list domain_insecure 'ntp.example.com'
#list domain_forward 'mail.example.com'
config zone
option enabled '0'
option fallback '1'
option url_dir 'https://www.internic.net/domain/'
option zone_type 'auth_zone'
list server 'lax.xfr.dns.icann.org'
list server 'iad.xfr.dns.icann.org'
list zone_name '.'
list zone_name 'arpa.'
list zone_name 'in-addr.arpa.'
list zone_name 'ip6.arpa.'
config zone
option enabled '0'
option fallback '1'
option resolv_conf '1'
option zone_type 'forward_zone'
list zone_name 'isp-bill.example.com.'
list zone_name 'isp-mail.example.net.'