diff --git a/net/unbound/Makefile b/net/unbound/Makefile index a6de8db33..12144aeb9 100644 --- a/net/unbound/Makefile +++ b/net/unbound/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=unbound PKG_VERSION:=1.7.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 4e81162f8..d89704438 100644 --- a/net/unbound/files/README.md +++ b/net/unbound/files/README.md @@ -139,7 +139,7 @@ config unbound ### Hybrid Manual/UCI You like the UCI. Yet, you need to add some difficult to standardize options, or just are not ready to make a UCI request yet. The files `/etc/unbound/unbound_srv.conf` and `/etc/unbound/unbound_ext.conf` will be copied to Unbounds chroot directory and included during auto generation. -The former will be added to the end of the `server:` clause. The later will be added to the end of the file for extended `forward:` 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. +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. ## Complete List of UCI Options **/etc/config/unbound**: @@ -196,8 +196,11 @@ config unbound option domain_type 'static' Unbound local-zone: . This allows you to lock - down or allow forwarding of your domain, your router host name - without suffix, and leakage of RFC6762 "local." + down or allow forwarding of the local zone. Notable types: + static - typical single router setup much like OpenWrt dnsmasq default + refuse - to answer overtly with DNS code REFUSED + deny - to drop queries for the local zone + transparent - to use your manually added forward-zone: or stub-zone: clause option edns_size '1280' Bytes. Extended DNS is necessary for DNSSEC. However, it can run @@ -226,9 +229,9 @@ config unbound configuration. Make changes to /etc/unbound/unbound.conf. option prefetch_root '0' - Boolean. Enable Unbound authority zone clauses for "." (root), "arpa," - "in-addr.arpa," and "ip6.arpa" and obtain complete zone files from public - servers using http or AXFR (gTLD are unfortunately not as public). + 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. diff --git a/net/unbound/files/iptools.sh b/net/unbound/files/iptools.sh index 1725242ec..9985f76d0 100644 --- a/net/unbound/files/iptools.sh +++ b/net/unbound/files/iptools.sh @@ -138,3 +138,25 @@ private_subnet() { ############################################################################## +domain_ptr_any() { + local subnet=$1 + local arpa validip4 validip6 + + validip4=$( valid_subnet4 $subnet ) + validip6=$( valid_subnet6 $subnet ) + + + if [ "$validip4" = "ok" ] ; then + arpa=$( domain_ptr_ip4 "$subnet" ) + elif [ "$validip6" = "ok" ] ; then + arpa=$( domain_ptr_ip6 "$subnet" ) + fi + + + if [ -n "$arpa" ] ; then + echo $arpa + fi +} + +############################################################################## + diff --git a/net/unbound/files/odhcpd.sh b/net/unbound/files/odhcpd.sh index 9c01dc6f6..93efa73ad 100644 --- a/net/unbound/files/odhcpd.sh +++ b/net/unbound/files/odhcpd.sh @@ -43,7 +43,9 @@ odhcpd_zonedata() { local dhcp_origin=$( uci_get dhcp.@odhcpd[0].leasefile ) - if [ "$dhcp_link" = "odhcpd" -a -f "$dhcp_origin" ] ; then + if [ "$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 diff --git a/net/unbound/files/unbound.sh b/net/unbound/files/unbound.sh index 2fda84e86..a22117751 100644 --- a/net/unbound/files/unbound.sh +++ b/net/unbound/files/unbound.sh @@ -63,12 +63,18 @@ UNBOUND_TXT_HOSTNAME=thisrouter UNBOUND_LIST_FORWARD="" UNBOUND_LIST_INSECURE="" -UNBOUND_LIST_PRV_SUBNET="" ############################################################################## -# keep track of local-domain: assignments during inserted resource records +# keep track of assignments during inserted resource records UNBOUND_LIST_DOMAINS="" +UNBOUND_LIST_IFACE="" +UNBOUND_LIST_PRV_IP6GLA="" +UNBOUND_LIST_LAN_NET="" + +# Similar default SOA / NS RR as Unbound uses for private ARPA zones +UNBOUND_XSOA="3600 IN SOA localhost. nobody.invalid. 1 3600 1200 7200 600" +UNBOUND_XNS="3600 IN NS localhost." ############################################################################## @@ -82,34 +88,13 @@ UNBOUND_LIST_DOMAINS="" ############################################################################## -copy_dash_update() { - # TODO: remove this function and use builtins when this issues is resovled. - # Due to OpenWrt/LEDE divergence "cp -u" isn't yet universally available. - local filetime keeptime - - - if [ -f $UNBOUND_KEYFILE.keep ] ; then - # root.key.keep is reused if newest - filetime=$( date -r $UNBOUND_KEYFILE +%s ) - keeptime=$( date -r $UNBOUND_KEYFILE.keep +%s ) - - - if [ $keeptime -gt $filetime ] ; then - cp $UNBOUND_KEYFILE.keep $UNBOUND_KEYFILE - fi - - - rm -f $UNBOUND_KEYFILE.keep - fi -} - -############################################################################## - create_interface_dns() { local cfg="$1" local ipcommand logint ignore ifname ifdashname local name names address addresses - local ulaprefix if_fqdn host_fqdn mode mode_ptr + local ulaprefix if_fqdn host_fqdn + local mode_ptr="$UNBOUND_TXT_HOSTNAME" + local names="$UNBOUND_TXT_HOSTNAME" # Create local-data: references for this hosts interfaces (router). config_get logint "$cfg" interface @@ -124,45 +109,60 @@ create_interface_dns() { if_fqdn="$ifdashname.$host_fqdn" - if [ -z "${ulaprefix%%:/*}" ] ; then - # Nonsense so this option isn't globbed below - ulaprefix="fdno:such:addr::/48" - fi + if [ -z "$ifdashname" ] ; then + # race conditions at init can rarely cause a blank device return + # the record format is invalid and Unbound won't load the conf file + mode=0 + elif [ -n "$UNBOUND_LIST_IFACE" ] ; then + case "$UNBOUND_LIST_IFACE" in + *$ifdashname*) + # repeat such as dual WAN (eth0-1) and WAN6 (eth0-1) + mode=0 + ;; + + *) + mode=1 + ;; + esac - if [ "$ignore" -gt 0 ] ; then - mode="$UNBOUND_D_WAN_FQDN" else - mode="$UNBOUND_D_LAN_FQDN" + mode=1 fi - case "$mode" in - 3) - mode_ptr="$host_fqdn" - names="$host_fqdn $UNBOUND_TXT_HOSTNAME" - ;; + if [ $mode -gt 0 ] ; then + UNBOUND_LIST_IFACE="$UNBOUND_LIST_IFACE $ifdashname" + + + if [ -z "${ulaprefix%%:/*}" ] ; then + # Nonsense so this option isn't globbed below + ulaprefix="fdno:such:addr::/48" + fi + - 4) - if [ -z "$ifdashname" ] ; then - # race conditions at init can rarely cause a blank device return - # the record format is invalid and Unbound won't load the conf file + if [ "$ignore" -gt 0 ] ; then + mode="$UNBOUND_D_WAN_FQDN" + else + mode="$UNBOUND_D_LAN_FQDN" + fi + fi + + + if [ "$mode" -gt 1 ] ; then + case "$mode" in + 3) mode_ptr="$host_fqdn" names="$host_fqdn $UNBOUND_TXT_HOSTNAME" - else + ;; + + 4) mode_ptr="$if_fqdn" names="$if_fqdn $host_fqdn $UNBOUND_TXT_HOSTNAME" - fi - ;; - - *) - mode_ptr="$UNBOUND_TXT_HOSTNAME" - names="$UNBOUND_TXT_HOSTNAME" - ;; - esac + ;; + esac - if [ "$mode" -gt 1 ] ; then { for address in $addresses ; do case $address in @@ -385,21 +385,37 @@ bundle_domain_insecure() { ############################################################################## bundle_private_interface() { - local ipcommand ifsubnet ifsubnets ifname + local ipcommand ifsubnet ifsubnets ifname validip4 network_get_device ifname $1 + if [ -n "$ifname" ] ; then - ipcommand="ip -6 -o address show $ifname" - ifsubnets=$( $ipcommand | awk '/inet6/{ print $4 }' ) + ipcommand="ip -o address show $ifname" + ifsubnets=$( $ipcommand | awk '/inet/{ print $4 }' ) if [ -n "$ifsubnets" ] ; then for ifsubnet in $ifsubnets ; do case $ifsubnet in - [1-9]*:*[0-9a-f]) + [1-9][0-9a-f][0-9a-f][0-9a-f]:*[0-9a-f]) # Special GLA protection for local block; ULA protected as a catagory - UNBOUND_LIST_PRV_SUBNET="$UNBOUND_LIST_PRV_SUBNET $ifsubnet" ;; + UNBOUND_LIST_PRV_IP6GLA="$UNBOUND_LIST_PRV_IP6GLA $ifsubnet" + ;; + + f[dc][0-9a-f][0-9a-f]:*[0-9a-f]) + # Used to configure specific local-zone: data + UNBOUND_LIST_LAN_NET="$UNBOUND_LIST_LAN_NET $ifsubnet" + ;; + + *) + validip4=$( valid_subnet4 $ifsubnet ) + + + if [ "$validip4" = "ok" ] ; then + UNBOUND_LIST_LAN_NET="$UNBOUND_LIST_LAN_NET $ifsubnet" + fi + ;; esac done fi @@ -411,6 +427,7 @@ bundle_private_interface() { unbound_mkdir() { local filestuff + if [ "$UNBOUND_D_DHCP_LINK" = "odhcpd" ] ; then local dhcp_origin=$( uci_get dhcp.@odhcpd[0].leasefile ) local dhcp_dir=$( dirname $dhcp_origin ) @@ -422,6 +439,7 @@ unbound_mkdir() { fi fi + if [ -f $UNBOUND_KEYFILE ] ; then filestuff=$( cat $UNBOUND_KEYFILE ) @@ -469,7 +487,11 @@ unbound_mkdir() { fi - copy_dash_update + if [ -f $UNBOUND_KEYFILE.keep ] ; then + # root.key.keep is reused if newest + cp -u $UNBOUND_KEYFILE.keep $UNBOUND_KEYFILE + rm -f $UNBOUND_KEYFILE.keep + fi # Ensure access and prepare to jail @@ -809,6 +831,7 @@ unbound_conf() { logger -t unbound -s "default memory configuration" fi + # Assembly of module-config: options is tricky; order matters modulestring="iterator" @@ -941,8 +964,8 @@ unbound_conf() { fi - if [ -n "$UNBOUND_LIST_PRV_SUBNET" -a "$UNBOUND_D_PRIV_BLCK" -gt 1 ] ; then - for ifsubnet in $UNBOUND_LIST_PRV_SUBNET ; do + if [ -n "$UNBOUND_LIST_PRV_IP6GLA" -a "$UNBOUND_D_PRIV_BLCK" -gt 1 ] ; then + for ifsubnet in $UNBOUND_LIST_PRV_IP6GLA ; do # Remove global DNS responses with your local network IP6 GLA echo " private-address: $ifsubnet" >> $UNBOUND_CONFFILE done @@ -1019,6 +1042,7 @@ unbound_adblock() { # TODO: Unbound 1.6.0 added "tags" and "views"; lets work with adblock team local adb_enabled adb_file + if [ ! -x /usr/bin/adblock.sh -o ! -x /etc/init.d/adblock ] ; then adb_enabled=0 else @@ -1040,31 +1064,90 @@ unbound_adblock() { ############################################################################## unbound_hostname() { + local ifsubnet ifarpa + + if [ -n "$UNBOUND_TXT_DOMAIN" ] ; then { - # TODO: Unbound 1.6.0 added "tags" and "views" and we could make - # domains by interface to prevent DNS from "guest" to "home" - echo " local-zone: $UNBOUND_TXT_DOMAIN. $UNBOUND_D_DOMAIN_TYPE" - echo " domain-insecure: $UNBOUND_TXT_DOMAIN" - echo " private-domain: $UNBOUND_TXT_DOMAIN" - echo - echo " local-zone: $UNBOUND_TXT_HOSTNAME. $UNBOUND_D_DOMAIN_TYPE" + # Hostname as TLD works, but not transparent through recursion echo " domain-insecure: $UNBOUND_TXT_HOSTNAME" echo " private-domain: $UNBOUND_TXT_HOSTNAME" + echo " local-zone: $UNBOUND_TXT_HOSTNAME. static" + echo " local-data: \"$UNBOUND_TXT_HOSTNAME. $UNBOUND_XSOA\"" + echo " local-data: \"$UNBOUND_TXT_HOSTNAME. $UNBOUND_XNS\"" echo } >> $UNBOUND_CONFFILE case "$UNBOUND_D_DOMAIN_TYPE" in deny|inform_deny|refuse|static) + if [ -n "$UNBOUND_LIST_PRV_IP6GLA" \ + -a "$UNBOUND_D_PRIV_BLCK" -gt 1 ] ; then + for ifsubnet in $UNBOUND_LIST_PRV_IP6GLA ; do + ifarpa=$( domain_ptr_any "$ifsubnet" ) + + + if [ -n "$ifarpa" ] ; then + { + # Do NOT forward queries with your GLA ip6.arpa + echo " domain-insecure: $ifarpa" + echo " local-zone: $ifarpa. $UNBOUND_D_DOMAIN_TYPE" + echo " local-data: \"$ifarpa. $UNBOUND_XSOA\"" + echo " local-data: \"$ifarpa. $UNBOUND_XNS\"" + echo + } >> $UNBOUND_CONFFILE + fi + done + fi + + + if [ -n "$UNBOUND_LIST_LAN_NET" \ + -a "$UNBOUND_D_PRIV_BLCK" -gt 0 ] ; then + for ifsubnet in $UNBOUND_LIST_LAN_NET ; do + ifarpa=$( domain_ptr_any "$ifsubnet" ) + + + if [ -n "$ifarpa" ] ; then + { + # Do NOT forward queries with your ULA ip6.arpa or in-addr.arpa + echo " domain-insecure: $ifarpa" + echo " local-zone: $ifarpa. $UNBOUND_D_DOMAIN_TYPE" + echo " local-data: \"$ifarpa. $UNBOUND_XSOA\"" + echo " local-data: \"$ifarpa. $UNBOUND_XNS\"" + echo + } >> $UNBOUND_CONFFILE + fi + done + fi + + { - # avoid upstream involvement in RFC6762 like responses (link only) - echo " local-zone: local. $UNBOUND_D_DOMAIN_TYPE" + # avoid upstream involvement in RFC6762 echo " domain-insecure: local" echo " private-domain: local" + echo " local-zone: local. $UNBOUND_D_DOMAIN_TYPE" + echo " local-data: \"local. $UNBOUND_XSOA\"" + echo " local-data: \"local. $UNBOUND_XNS\"" + echo " local-data: \"local. 3600 IN TXT RFC6762\"" + echo + # type static means only this router has your domain + # type transparent will permit forward-zone: or stub-zone: clauses + echo " domain-insecure: $UNBOUND_TXT_DOMAIN" + echo " private-domain: $UNBOUND_TXT_DOMAIN" + echo " local-zone: $UNBOUND_TXT_DOMAIN. $UNBOUND_D_DOMAIN_TYPE" + echo " local-data: \"$UNBOUND_TXT_DOMAIN. $UNBOUND_XSOA\"" + echo " local-data: \"$UNBOUND_TXT_DOMAIN. $UNBOUND_XNS\"" echo } >> $UNBOUND_CONFFILE ;; + + *) + # likely transparent domain with fordward-zone: clause to next router + echo " domain-insecure: $UNBOUND_TXT_DOMAIN" + echo " private-domain: $UNBOUND_TXT_DOMAIN" + echo " local-zone: $UNBOUND_TXT_DOMAIN. $UNBOUND_D_DOMAIN_TYPE" + echo + ;; esac @@ -1227,6 +1310,7 @@ unbound_resolv_setup() { return fi + if [ -x /etc/init.d/dnsmasq ] && /etc/init.d/dnsmasq enabled \ && nslookup localhost 127.0.0.1#53 >/dev/null 2>&1 ; then # unbound is configured for port 53, but dnsmasq is enabled and a resolver @@ -1237,6 +1321,7 @@ unbound_resolv_setup() { return fi + # unbound is designated to listen on 127.0.0.1#53, # set resolver file to local. rm -f /tmp/resolv.conf