DNS flag day 2020, software should reflect the minimum EDNS 1232 bytes. Added iface_wan and iface_lan to control internal DNS assignemnts and to control what is local service ACL. Interface wild cards are not explicitly set so that they can be customized in extended conf. Signed-off-by: Eric Luehrsen <ericluehrsen@gmail.com>
318 lines
8.4 KiB
Bash
318 lines
8.4 KiB
Bash
#!/bin/sh
|
|
##############################################################################
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License version 2 as
|
|
# published by the Free Software Foundation.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# Copyright (C) 2016 Eric Luehrsen
|
|
#
|
|
##############################################################################
|
|
#
|
|
# This crosses over to the dnsmasq UCI file "dhcp" and parses it for fields
|
|
# that will allow Unbound to request local host DNS of dnsmasq. We need to look
|
|
# at the interfaces in "dhcp" and get their subnets. The Unbound conf syntax
|
|
# makes this a little difficult. First in "server:" we need to create private
|
|
# zones for the domain and PTR records. Then we need to create numerous
|
|
# "forward:" clauses to forward those zones to dnsmasq.
|
|
#
|
|
##############################################################################
|
|
|
|
# while useful (sh)ellcheck is pedantic and noisy
|
|
# shellcheck disable=1091,2002,2004,2034,2039,2086,2094,2140,2154,2155
|
|
|
|
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" ] && [ -n "$ip" ] ; then
|
|
create_local_zone "$name"
|
|
|
|
|
|
case $ip in
|
|
fe[89ab][0-9a-f]:*|169.254.*)
|
|
debug_ip="$ip@$name"
|
|
;;
|
|
|
|
[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" ] && [ -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" ] && [ -n "$target" ] && [ -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" ] && [ -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
|
|
|
|
# dnsmasq domain and interface assignment settings will control config
|
|
config_get fwd_domain "$cfg" domain
|
|
config_get fwd_port "$cfg" port
|
|
config_get wan_fqdn "$cfg" add_wan_fqdn
|
|
|
|
|
|
if [ -n "$wan_fqdn" ] ; then
|
|
DM_D_WAN_FQDN=$wan_fqdn
|
|
fi
|
|
|
|
|
|
if [ -n "$fwd_domain" ] && [ -n "$fwd_port" ] \
|
|
&& [ ! ${fwd_port:-53} -eq 53 ] ; then
|
|
# dnsmasq localhost listening ports (possible multiple instances)
|
|
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 ifarpa ifsubnet
|
|
|
|
|
|
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 "$UB_LIST_NETW_WAN" ] && [ $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_inactive() {
|
|
local record
|
|
|
|
|
|
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" ] && [ -n "$DM_LIST_FWD_ZONES" ] ; then
|
|
if [ $UB_B_DNS_ASSIST -lt 1 ] ; 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
|
|
|
|
else
|
|
echo > $UB_SRVMASQ_CONF
|
|
fi
|
|
|
|
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
|
|
} >> $UB_EXTMASQ_CONF
|
|
done
|
|
fi
|
|
}
|
|
|
|
##############################################################################
|
|
|
|
dnsmasq_link() {
|
|
if [ "$UB_D_DHCP_LINK" = "dnsmasq" ] ; then
|
|
dnsmasq_active
|
|
|
|
else
|
|
dnsmasq_inactive
|
|
fi
|
|
}
|
|
|
|
##############################################################################
|
|
|