Browse Source

unbound: improve local zone evaluation in UCI

When UCI local zone is private and static, Unbound covered private
addresses with defaults. Optional delegated global IP6 prefix
protection lacked a static zone, but it was prevented from appearing
in global DNS responses. Domain names router-as-TLD, "lan." and
"local." were static, but they lacked default SOA or NS such as
Unbound had assinged to private addresses. Clean up these local
zones UCI evaluation and block global DNS inclusion.

Signed-off-by: Eric Luehrsen <ericluehrsen@hotmail.com>
lilik-openwrt-22.03
Eric Luehrsen 7 years ago
parent
commit
a7fd69233d
5 changed files with 189 additions and 77 deletions
  1. +1
    -1
      net/unbound/Makefile
  2. +9
    -6
      net/unbound/files/README.md
  3. +22
    -0
      net/unbound/files/iptools.sh
  4. +3
    -1
      net/unbound/files/odhcpd.sh
  5. +154
    -69
      net/unbound/files/unbound.sh

+ 1
- 1
net/unbound/Makefile View File

@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=unbound PKG_NAME:=unbound
PKG_VERSION:=1.7.2 PKG_VERSION:=1.7.2
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_LICENSE:=BSD-3-Clause PKG_LICENSE:=BSD-3-Clause
PKG_LICENSE_FILES:=LICENSE PKG_LICENSE_FILES:=LICENSE


+ 9
- 6
net/unbound/files/README.md View File

@ -139,7 +139,7 @@ config unbound
### Hybrid Manual/UCI ### 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. 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 ## Complete List of UCI Options
**/etc/config/unbound**: **/etc/config/unbound**:
@ -196,8 +196,11 @@ config unbound
option domain_type 'static' option domain_type 'static'
Unbound local-zone: <domain> <type>. This allows you to lock Unbound local-zone: <domain> <type>. 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' option edns_size '1280'
Bytes. Extended DNS is necessary for DNSSEC. However, it can run 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. configuration. Make changes to /etc/unbound/unbound.conf.
option prefetch_root '0' 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' option protocol 'mixed'
Unbound can limit its protocol used for recursive queries. Unbound can limit its protocol used for recursive queries.


+ 22
- 0
net/unbound/files/iptools.sh View File

@ -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
}
##############################################################################

+ 3
- 1
net/unbound/files/odhcpd.sh View File

@ -43,7 +43,9 @@ odhcpd_zonedata() {
local dhcp_origin=$( uci_get dhcp.@odhcpd[0].leasefile ) 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 # Capture the lease file which could be changing often
sort $dhcp_origin > $dhcp_ls_new sort $dhcp_origin > $dhcp_ls_new


+ 154
- 69
net/unbound/files/unbound.sh View File

@ -63,12 +63,18 @@ UNBOUND_TXT_HOSTNAME=thisrouter
UNBOUND_LIST_FORWARD="" UNBOUND_LIST_FORWARD=""
UNBOUND_LIST_INSECURE="" 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_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() { create_interface_dns() {
local cfg="$1" local cfg="$1"
local ipcommand logint ignore ifname ifdashname local ipcommand logint ignore ifname ifdashname
local name names address addresses 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). # Create local-data: references for this hosts interfaces (router).
config_get logint "$cfg" interface config_get logint "$cfg" interface
@ -124,45 +109,60 @@ create_interface_dns() {
if_fqdn="$ifdashname.$host_fqdn" 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 else
mode="$UNBOUND_D_LAN_FQDN"
mode=1
fi 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" mode_ptr="$host_fqdn"
names="$host_fqdn $UNBOUND_TXT_HOSTNAME" names="$host_fqdn $UNBOUND_TXT_HOSTNAME"
else
;;
4)
mode_ptr="$if_fqdn" mode_ptr="$if_fqdn"
names="$if_fqdn $host_fqdn $UNBOUND_TXT_HOSTNAME" 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 for address in $addresses ; do
case $address in case $address in
@ -385,21 +385,37 @@ bundle_domain_insecure() {
############################################################################## ##############################################################################
bundle_private_interface() { bundle_private_interface() {
local ipcommand ifsubnet ifsubnets ifname
local ipcommand ifsubnet ifsubnets ifname validip4
network_get_device ifname $1 network_get_device ifname $1
if [ -n "$ifname" ] ; then 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 if [ -n "$ifsubnets" ] ; then
for ifsubnet in $ifsubnets ; do for ifsubnet in $ifsubnets ; do
case $ifsubnet in 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 # 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 esac
done done
fi fi
@ -411,6 +427,7 @@ bundle_private_interface() {
unbound_mkdir() { unbound_mkdir() {
local filestuff local filestuff
if [ "$UNBOUND_D_DHCP_LINK" = "odhcpd" ] ; then if [ "$UNBOUND_D_DHCP_LINK" = "odhcpd" ] ; then
local dhcp_origin=$( uci_get dhcp.@odhcpd[0].leasefile ) local dhcp_origin=$( uci_get dhcp.@odhcpd[0].leasefile )
local dhcp_dir=$( dirname $dhcp_origin ) local dhcp_dir=$( dirname $dhcp_origin )
@ -422,6 +439,7 @@ unbound_mkdir() {
fi fi
fi fi
if [ -f $UNBOUND_KEYFILE ] ; then if [ -f $UNBOUND_KEYFILE ] ; then
filestuff=$( cat $UNBOUND_KEYFILE ) filestuff=$( cat $UNBOUND_KEYFILE )
@ -469,7 +487,11 @@ unbound_mkdir() {
fi 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 # Ensure access and prepare to jail
@ -809,6 +831,7 @@ unbound_conf() {
logger -t unbound -s "default memory configuration" logger -t unbound -s "default memory configuration"
fi fi
# Assembly of module-config: options is tricky; order matters # Assembly of module-config: options is tricky; order matters
modulestring="iterator" modulestring="iterator"
@ -941,8 +964,8 @@ unbound_conf() {
fi 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 # Remove global DNS responses with your local network IP6 GLA
echo " private-address: $ifsubnet" >> $UNBOUND_CONFFILE echo " private-address: $ifsubnet" >> $UNBOUND_CONFFILE
done done
@ -1019,6 +1042,7 @@ unbound_adblock() {
# TODO: Unbound 1.6.0 added "tags" and "views"; lets work with adblock team # TODO: Unbound 1.6.0 added "tags" and "views"; lets work with adblock team
local adb_enabled adb_file local adb_enabled adb_file
if [ ! -x /usr/bin/adblock.sh -o ! -x /etc/init.d/adblock ] ; then if [ ! -x /usr/bin/adblock.sh -o ! -x /etc/init.d/adblock ] ; then
adb_enabled=0 adb_enabled=0
else else
@ -1040,31 +1064,90 @@ unbound_adblock() {
############################################################################## ##############################################################################
unbound_hostname() { unbound_hostname() {
local ifsubnet ifarpa
if [ -n "$UNBOUND_TXT_DOMAIN" ] ; then 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 " domain-insecure: $UNBOUND_TXT_HOSTNAME"
echo " private-domain: $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 echo
} >> $UNBOUND_CONFFILE } >> $UNBOUND_CONFFILE
case "$UNBOUND_D_DOMAIN_TYPE" in case "$UNBOUND_D_DOMAIN_TYPE" in
deny|inform_deny|refuse|static) 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 " domain-insecure: local"
echo " private-domain: 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 echo
} >> $UNBOUND_CONFFILE } >> $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 esac
@ -1227,6 +1310,7 @@ unbound_resolv_setup() {
return return
fi fi
if [ -x /etc/init.d/dnsmasq ] && /etc/init.d/dnsmasq enabled \ if [ -x /etc/init.d/dnsmasq ] && /etc/init.d/dnsmasq enabled \
&& nslookup localhost 127.0.0.1#53 >/dev/null 2>&1 ; then && 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 # unbound is configured for port 53, but dnsmasq is enabled and a resolver
@ -1237,6 +1321,7 @@ unbound_resolv_setup() {
return return
fi fi
# unbound is designated to listen on 127.0.0.1#53, # unbound is designated to listen on 127.0.0.1#53,
# set resolver file to local. # set resolver file to local.
rm -f /tmp/resolv.conf rm -f /tmp/resolv.conf


Loading…
Cancel
Save