diff --git a/net/unbound/Makefile b/net/unbound/Makefile index 7dcd2a608..a7171e59d 100644 --- a/net/unbound/Makefile +++ b/net/unbound/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=unbound PKG_VERSION:=1.6.2 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_LICENSE:=BSD-3-Clause PKG_LICENSE_FILES:=LICENSE diff --git a/net/unbound/files/README.md b/net/unbound/files/README.md index d8bdf958f..db0f5974f 100644 --- a/net/unbound/files/README.md +++ b/net/unbound/files/README.md @@ -73,7 +73,7 @@ config dhcp 'lan' ``` ### Unbound and odhcpd -You may ask can Unbound replace dnsmasq? You can have DHCP-DNS records with Unbound and odhcpd only. The UCI scripts will allow Unbound to act like dnsmasq. When odhcpd configures each DHCP lease, it will call a script. The script provided with Unbound will read the lease file for DHCP-DNS records. You **must install** `unbound-control`, because the lease records are added and removed without starting, stopping, flushing cache, or re-writing conf files. (_restart overhead can be excessive with even a few mobile devices._) +You may ask, "can Unbound replace dnsmasq?" You can have DHCP-DNS records with Unbound and odhcpd only. The UCI scripts will allow Unbound to act like dnsmasq. When odhcpd configures each DHCP lease, it will call a script. The script provided with Unbound will read the lease file for DHCP-DNS records. You **must install** `unbound-control`, because the lease records are added and removed without starting, stopping, flushing cache, or re-writing conf files. (_restart overhead can be excessive with even a few mobile devices._) Don't forget to disable or uninstall dnsmasq when you don't intend to use it. Strange results may occur. If you want to use default dnsmasq+odhcpd and add Unbound on top, then use the dnsmasq-serial or dnsmasq-parallel methods above. @@ -106,8 +106,7 @@ config dhcp 'lan' option leasetime '12h' option ra 'server' option ra_management '1' - # issue your ULA and avoid default [fe80::] - list dns 'fdxx:xxxx:xxxx::1' + # odhcpd should issue ULA [fd00::/8] by default ... config odhcpd 'odhcpd' @@ -146,6 +145,14 @@ The former will be added to the end of the `server:` clause. The later will be a config unbound Currently only one instance is supported. + option add_extra_dns '0' + Level. Execute traditional DNS overrides found in `/etc/config/dhcp`. + Optional so you may use other Unbound conf or redirect to NSD instance. + 0 - Ignore `/etc/config/dhcp` + 1 - Use only 'domain' clause (host records) + 2 - Use 'domain', 'mxhost', and 'srvhost' clauses + 3 - Use all of 'domain', 'mxhost', 'srvhost', and 'cname' clauses + option add_local_fqdn '0' Level. This puts your routers host name in the LAN (local) DNS. Each level is more detailed and comprehensive. @@ -271,9 +278,15 @@ 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_insecure - List. Domains or pointers that you wish to skip DNSSEC. Your DHCP - domains and pointers in dnsmasq will get this automatically. + list domain_insecure 'www.example.com' + Domain. Domains that you wish to skip DNSSEC. Your DHCP + domains and pointers will get this automatically. + + list trigger '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. ``` diff --git a/net/unbound/files/odhcpd.sh b/net/unbound/files/odhcpd.sh index 22a470b4c..c93d280a0 100644 --- a/net/unbound/files/odhcpd.sh +++ b/net/unbound/files/odhcpd.sh @@ -45,7 +45,7 @@ odhcpd_zonedata() { 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 dhcp_origin=$( uci get dhcp.@odhcpd[0].leasefile ) + local dhcp_origin=$( uci_get dhcp.@odhcpd[0].leasefile ) config_load unbound config_foreach odhcpd_settings unbound diff --git a/net/unbound/files/unbound.init b/net/unbound/files/unbound.init index 1edf9ef80..5027b79b5 100755 --- a/net/unbound/files/unbound.init +++ b/net/unbound/files/unbound.init @@ -47,7 +47,7 @@ start_service() { stop_service() { unbound_stop - + # Wait! on restart Unbound may take time writing closure stats to syslog pidof $PROG && sleep 1 } @@ -55,9 +55,20 @@ stop_service() { ############################################################################## service_triggers() { - # use soft reload to prevent continuous stop-start and cache flush + local trigger + local triggers=$( uci_get unbound.@unbound[0].trigger ) + + PROCD_RELOAD_DELAY=2000 procd_add_reload_trigger "unbound" - procd_add_raw_trigger "interface.*.up" 2000 /etc/init.d/unbound reload + + if [ -n "$triggers" ] ; then + for trigger in $triggers ; do + # due to some netifd/procd interactions with IP6, limit interfaces + procd_add_reload_interface_trigger "$trigger" + done + else + procd_add_raw_trigger "interface.*.up" 2000 /etc/init.d/unbound reload + fi } ############################################################################## diff --git a/net/unbound/files/unbound.sh b/net/unbound/files/unbound.sh index 4daefda4d..197a06d97 100644 --- a/net/unbound/files/unbound.sh +++ b/net/unbound/files/unbound.sh @@ -14,9 +14,12 @@ # ############################################################################## # -# This builds the basic UCI components currently supported for Unbound. It is -# intentionally NOT comprehensive and bundles a lot of options. The UCI is to -# be a simpler presentation of the total Unbound conf set. +# Unbound is a full featured recursive server with many options. The UCI +# provided tries to simplify and bundle options. This should make Unbound +# easier to deploy. Even light duty routers may resolve recursively instead of +# depending on a stub with the ISP. The UCI also attempts to replicate dnsmasq +# features as used in base LEDE/OpenWrt. If there is a desire for more +# detailed tuning, then manual conf file overrides are also made available. # ############################################################################## @@ -36,6 +39,7 @@ UNBOUND_B_QRY_MINST=0 UNBOUND_D_DOMAIN_TYPE=static UNBOUND_D_DHCP_LINK=none +UNBOUND_D_EXTRA_DNS=0 UNBOUND_D_LAN_FQDN=0 UNBOUND_D_PROTOCOL=mixed UNBOUND_D_RESOURCE=small @@ -57,6 +61,11 @@ UNBOUND_TXT_HOSTNAME=thisrouter ############################################################################## +# keep track of local-domain: assignments during inserted resource records +UNBOUND_LIST_DOMAINS="" + +############################################################################## + UNBOUND_LIBDIR=/usr/lib/unbound UNBOUND_VARDIR=/var/lib/unbound @@ -69,7 +78,7 @@ UNBOUND_CONFFILE=$UNBOUND_VARDIR/unbound.conf UNBOUND_KEYFILE=$UNBOUND_VARDIR/root.key UNBOUND_HINTFILE=$UNBOUND_VARDIR/root.hints -UNBOUND_TIMEFILE=$UNBOUND_VARDIR/unbound.time +UNBOUND_TIMEFILE=$UNBOUND_VARDIR/hotplug.time ############################################################################## @@ -124,8 +133,8 @@ create_interface_dns() { ifdashname="${ifname//./-}" ipcommand="ip -o address show $ifname" - addresses="$($ipcommand | awk '/inet/{sub(/\/.*/,"",$4); print $4}')" - ulaprefix="$(uci_get network @globals[0] ula_prefix)" + addresses=$( $ipcommand | awk '/inet/{sub(/\/.*/,"",$4); print $4}' ) + ulaprefix=$( uci_get network.@globals[0].ula_prefix ) host_fqdn="$UNBOUND_TXT_HOSTNAME.$UNBOUND_TXT_DOMAIN" if_fqdn="$ifdashname.$host_fqdn" @@ -223,6 +232,135 @@ create_interface_dns() { ############################################################################## +create_local_zone() { + local target="$1" + local partial domain found + + + if [ -n "$UNBOUND_LIST_DOMAINS" ] ; then + for domain in $UNBOUND_LIST_DOMAINS ; do + case $target in + *"${domain}") + found=1 + break + ;; + + [A-Za-z0-9]*.[A-Za-z0-9]*) + found=0 + ;; + + *) # no dots + found=1 + break + ;; + esac + done + else + found=0 + fi + + + 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 }' ) + UNBOUND_LIST_DOMAINS="$UNBOUND_LIST_DOMAINS $partial" + echo " local-zone: $partial. transparent" >> $UNBOUND_CONFFILE + fi +} + +############################################################################## + +create_host_record() { + local cfg="$1" + local ip name + + # 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.*) + echo " # note link address $ip for host $name" + ;; + + [1-9a-f]*:*[0-9a-f]) + echo " local-data: \"$name. 120 IN AAAA $ip\"" + echo " local-data-ptr: \"$ip 120 $name\"" + ;; + + [1-9]*.*[0-9]) + echo " local-data: \"$name. 120 IN A $ip\"" + echo " local-data-ptr: \"$ip 120 $name\"" + ;; + esac + } >> $UNBOUND_CONFFILE + fi +} + +############################################################################## + +create_mx_record() { + local cfg="$1" + local domain relay pref + + # 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" + echo " local-data: \"$domain. 120 IN MX $pref $relay.\"" \ + >> $UNBOUND_CONFFILE + fi +} + +############################################################################## + +create_srv_record() { + local cfg="$1" + local srv target port class weight + + # 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" + echo " local-data: \"$srv. 120 IN SRV $class $weight $port $target.\"" \ + >> $UNBOUND_CONFFILE + fi +} + +############################################################################## + +create_cname_record() { + local cfg="$1" + local cname target + + # 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" + echo " local-data: \"$cname. 120 IN CNAME $target.\"" >> $UNBOUND_CONFFILE + fi +} + +############################################################################## + create_access_control() { local cfg="$1" local subnets subnets4 subnets6 @@ -257,8 +395,8 @@ create_domain_insecure() { unbound_mkdir() { local resolvsym=0 - local dhcp_origin=$( uci get dhcp.@odhcpd[0].leasefile ) - local dhcp_dir=$( dirname "$dhcp_origin" ) + local dhcp_origin=$( uci_get dhcp.@odhcpd[0].leasefile ) + local dhcp_dir=$( dirname $dhcp_origin ) local filestuff @@ -780,11 +918,35 @@ unbound_hostname() { ############################################################################## +unbound_records() { + if [ "$UNBOUND_D_EXTRA_DNS" -gt 0 ] ; then + # Parasite from the uci.dhcp.domain clauses + config_load dhcp + config_foreach create_host_record domain + fi + + + if [ "$UNBOUND_D_EXTRA_DNS" -gt 1 ] ; then + config_foreach create_srv_record srvhost + config_foreach create_mx_record mxhost + fi + + + if [ "$UNBOUND_D_EXTRA_DNS" -gt 2 ] ; then + config_foreach create_cname_record cname + fi + + + echo >> $UNBOUND_CONFFILE +} + +############################################################################## + unbound_uci() { local cfg="$1" local dnsmasqpath hostnm - hostnm="$(uci_get system.@system[0].hostname | awk '{print tolower($0)}')" + hostnm=$( uci_get system.@system[0].hostname | awk '{print tolower($0)}' ) UNBOUND_TXT_HOSTNAME=${hostnm:-thisrouter} config_get_bool UNBOUND_B_SLAAC6_MAC "$cfg" dhcp4_slaac6 0 @@ -808,6 +970,7 @@ unbound_uci() { config_get UNBOUND_D_DOMAIN_TYPE "$cfg" domain_type static config_get UNBOUND_D_DHCP_LINK "$cfg" dhcp_link none + config_get UNBOUND_D_EXTRA_DNS "$cfg" add_extra_dns 0 config_get UNBOUND_D_LAN_FQDN "$cfg" add_local_fqdn 0 config_get UNBOUND_D_PROTOCOL "$cfg" protocol mixed config_get UNBOUND_D_RECURSION "$cfg" recursion passive @@ -817,6 +980,7 @@ unbound_uci() { config_get UNBOUND_TTL_MIN "$cfg" ttl_min 120 config_get UNBOUND_TXT_DOMAIN "$cfg" domain lan + UNBOUND_LIST_DOMAINS="nowhere $UNBOUND_TXT_DOMAIN" if [ "$UNBOUND_D_DHCP_LINK" = "none" ] ; then config_get_bool UNBOUND_B_DNSMASQ "$cfg" dnsmasq_link_dns 0 @@ -824,8 +988,8 @@ unbound_uci() { if [ "$UNBOUND_B_DNSMASQ" -gt 0 ] ; then UNBOUND_D_DHCP_LINK=dnsmasq - - + + if [ ! -f "$UNBOUND_TIMEFILE" ] ; then logger -t unbound -s "Please use 'dhcp_link' selector instead" fi @@ -898,6 +1062,7 @@ unbound_start() { dnsmasq_link else unbound_hostname + unbound_records fi unbound_control diff --git a/net/unbound/files/unbound.uci b/net/unbound/files/unbound.uci index 9e58ac799..45022f408 100644 --- a/net/unbound/files/unbound.uci +++ b/net/unbound/files/unbound.uci @@ -1,4 +1,5 @@ config unbound + option add_extra_dns '0' option add_local_fqdn '1' option add_wan_fqdn '0' option dhcp_link 'none' @@ -24,5 +25,7 @@ config unbound option unbound_control '0' option validator '0' option validator_ntp '1' - #list domain_insecure '' + list trigger 'lan' + list trigger 'wan' + #list domain_insecure 'www.example.com'