4daefda4d1138c49f6b12742e22fd8ecf32be036
[librecmc/package-feed.git] / net / unbound / files / unbound.sh
1 #!/bin/sh
2 ##############################################################################
3 #
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License version 2 as
6 # published by the Free Software Foundation.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # Copyright (C) 2016 Eric Luehrsen
14 #
15 ##############################################################################
16 #
17 # This builds the basic UCI components currently supported for Unbound. It is
18 # intentionally NOT comprehensive and bundles a lot of options. The UCI is to
19 # be a simpler presentation of the total Unbound conf set.
20 #
21 ##############################################################################
22
23 UNBOUND_B_CONTROL=0
24 UNBOUND_B_SLAAC6_MAC=0
25 UNBOUND_B_DNSSEC=0
26 UNBOUND_B_DNS64=0
27 UNBOUND_B_GATE_NAME=0
28 UNBOUND_B_HIDE_BIND=1
29 UNBOUND_B_LOCL_BLCK=0
30 UNBOUND_B_LOCL_SERV=1
31 UNBOUND_B_MAN_CONF=0
32 UNBOUND_B_NTP_BOOT=1
33 UNBOUND_B_PRIV_BLCK=1
34 UNBOUND_B_QUERY_MIN=0
35 UNBOUND_B_QRY_MINST=0
36
37 UNBOUND_D_DOMAIN_TYPE=static
38 UNBOUND_D_DHCP_LINK=none
39 UNBOUND_D_LAN_FQDN=0
40 UNBOUND_D_PROTOCOL=mixed
41 UNBOUND_D_RESOURCE=small
42 UNBOUND_D_RECURSION=passive
43 UNBOUND_D_WAN_FQDN=0
44
45 UNBOUND_IP_DNS64="64:ff9b::/96"
46
47 UNBOUND_N_EDNS_SIZE=1280
48 UNBOUND_N_FWD_PORTS=""
49 UNBOUND_N_RX_PORT=53
50 UNBOUND_N_ROOT_AGE=9
51
52 UNBOUND_TTL_MIN=120
53
54 UNBOUND_TXT_DOMAIN=lan
55 UNBOUND_TXT_FWD_ZONE=""
56 UNBOUND_TXT_HOSTNAME=thisrouter
57
58 ##############################################################################
59
60 UNBOUND_LIBDIR=/usr/lib/unbound
61 UNBOUND_VARDIR=/var/lib/unbound
62
63 UNBOUND_PIDFILE=/var/run/unbound.pid
64
65 UNBOUND_SRV_CONF=$UNBOUND_VARDIR/unbound_srv.conf
66 UNBOUND_EXT_CONF=$UNBOUND_VARDIR/unbound_ext.conf
67 UNBOUND_DHCP_CONF=$UNBOUND_VARDIR/unbound_dhcp.conf
68 UNBOUND_CONFFILE=$UNBOUND_VARDIR/unbound.conf
69
70 UNBOUND_KEYFILE=$UNBOUND_VARDIR/root.key
71 UNBOUND_HINTFILE=$UNBOUND_VARDIR/root.hints
72 UNBOUND_TIMEFILE=$UNBOUND_VARDIR/unbound.time
73
74 ##############################################################################
75
76 UNBOUND_ANCHOR=/usr/sbin/unbound-anchor
77 UNBOUND_CONTROL=/usr/sbin/unbound-control
78 UNBOUND_CONTROL_CFG="$UNBOUND_CONTROL -c $UNBOUND_CONFFILE"
79
80 ##############################################################################
81
82 . /lib/functions.sh
83 . /lib/functions/network.sh
84
85 . $UNBOUND_LIBDIR/dnsmasq.sh
86 . $UNBOUND_LIBDIR/iptools.sh
87 . $UNBOUND_LIBDIR/rootzone.sh
88
89 ##############################################################################
90
91 copy_dash_update() {
92   # TODO: remove this function and use builtins when this issues is resovled.
93   # Due to OpenWrt/LEDE divergence "cp -u" isn't yet universally available.
94   local filetime keeptime
95
96
97   if [ -f $UNBOUND_KEYFILE.keep ] ; then
98     # root.key.keep is reused if newest
99     filetime=$( date -r $UNBOUND_KEYFILE +%s )
100     keeptime=$( date -r $UNBOUND_KEYFILE.keep +%s )
101
102
103     if [ $keeptime -gt $filetime ] ; then
104       cp $UNBOUND_KEYFILE.keep $UNBOUND_KEYFILE
105     fi
106
107
108     rm -f $UNBOUND_KEYFILE.keep
109   fi
110 }
111
112 ##############################################################################
113
114 create_interface_dns() {
115   local cfg="$1"
116   local ipcommand logint ignore ifname ifdashname
117   local name names address addresses
118   local ulaprefix if_fqdn host_fqdn mode mode_ptr
119
120   # Create local-data: references for this hosts interfaces (router).
121   config_get logint "$cfg" interface
122   config_get_bool ignore "$cfg" ignore 0
123   network_get_device ifname "$cfg"
124
125   ifdashname="${ifname//./-}"
126   ipcommand="ip -o address show $ifname"
127   addresses="$($ipcommand | awk '/inet/{sub(/\/.*/,"",$4); print $4}')"
128   ulaprefix="$(uci_get network @globals[0] ula_prefix)"
129   host_fqdn="$UNBOUND_TXT_HOSTNAME.$UNBOUND_TXT_DOMAIN"
130   if_fqdn="$ifdashname.$host_fqdn"
131
132
133   if [ -z "${ulaprefix%%:/*}" ] ; then
134     # Nonsense so this option isn't globbed below
135     ulaprefix="fdno:such:addr::/48"
136   fi
137
138
139   if [ "$ignore" -gt 0 ] ; then
140     mode="$UNBOUND_D_WAN_FQDN"
141   else
142     mode="$UNBOUND_D_LAN_FQDN"
143   fi
144
145
146   case "$mode" in
147   3)
148     mode_ptr="$host_fqdn"
149     names="$host_fqdn  $UNBOUND_TXT_HOSTNAME"
150     ;;
151
152   4)
153     if [ -z "$ifdashname" ] ; then
154       # race conditions at init can rarely cause a blank device return
155       # the record format is invalid and Unbound won't load the conf file
156       mode_ptr="$host_fqdn"
157       names="$host_fqdn  $UNBOUND_TXT_HOSTNAME"
158     else
159       mode_ptr="$if_fqdn"
160       names="$if_fqdn  $host_fqdn  $UNBOUND_TXT_HOSTNAME"
161     fi
162     ;;
163
164   *)
165     mode_ptr="$UNBOUND_TXT_HOSTNAME"
166     names="$UNBOUND_TXT_HOSTNAME"
167     ;;
168   esac
169
170
171   if [ "$mode" -gt 1 ] ; then
172     {
173       for address in $addresses ; do
174         case $address in
175         fe80:*|169.254.*)
176           echo "  # note link address $address"
177           ;;
178
179         [1-9a-f]*:*[0-9a-f])
180           # GA and ULA IP6 for HOST IN AAA records (ip command is robust)
181           for name in $names ; do
182             echo "  local-data: \"$name. 120 IN AAAA $address\""
183           done
184           echo "  local-data-ptr: \"$address 120 $mode_ptr\""
185           ;;
186
187         [1-9]*.*[0-9])
188           # Old fashioned HOST IN A records
189           for name in $names ; do
190             echo "  local-data: \"$name. 120 IN A $address\""
191           done
192           echo "  local-data-ptr: \"$address 120 $mode_ptr\""
193           ;;
194         esac
195       done
196       echo
197     } >> $UNBOUND_CONFFILE
198
199   elif [ "$mode" -gt 0 ] ; then
200     {
201       for address in $addresses ; do
202         case $address in
203         fe80:*|169.254.*)
204           echo "  # note link address $address"
205           ;;
206
207         "${ulaprefix%%:/*}"*)
208           # Only this networks ULA and only hostname
209           echo "  local-data: \"$UNBOUND_TXT_HOSTNAME. 120 IN AAAA $address\""
210           echo "  local-data-ptr: \"$address 120 $UNBOUND_TXT_HOSTNAME\""
211           ;;
212
213         [1-9]*.*[0-9])
214           echo "  local-data: \"$UNBOUND_TXT_HOSTNAME. 120 IN A $address\""
215           echo "  local-data-ptr: \"$address 120 $UNBOUND_TXT_HOSTNAME\""
216           ;;
217         esac
218       done
219       echo
220     } >> $UNBOUND_CONFFILE
221   fi
222 }
223
224 ##############################################################################
225
226 create_access_control() {
227   local cfg="$1"
228   local subnets subnets4 subnets6
229   local validip4 validip6
230
231   network_get_subnets  subnets4 "$cfg"
232   network_get_subnets6 subnets6 "$cfg"
233   subnets="$subnets4 $subnets6"
234
235
236   if [ -n "$subnets" ] ; then
237     for subnet in $subnets ; do
238       validip4=$( valid_subnet4 $subnet )
239       validip6=$( valid_subnet6 $subnet )
240
241
242       if [ "$validip4" = "ok" -o "$validip6" = "ok" ] ; then
243         # For each "network" UCI add "access-control:" white list for queries
244         echo "  access-control: $subnet allow" >> $UNBOUND_CONFFILE
245       fi
246     done
247   fi
248 }
249
250 ##############################################################################
251
252 create_domain_insecure() {
253   echo "  domain-insecure: \"$1\"" >> $UNBOUND_CONFFILE
254 }
255
256 ##############################################################################
257
258 unbound_mkdir() {
259   local resolvsym=0
260   local dhcp_origin=$( uci get dhcp.@odhcpd[0].leasefile )
261   local dhcp_dir=$( dirname "$dhcp_origin" )
262   local filestuff
263
264
265   if [ ! -x /usr/sbin/dnsmasq -o ! -x /etc/init.d/dnsmasq ] ; then
266     resolvsym=1
267   else
268     /etc/init.d/dnsmasq enabled || resolvsym=1
269   fi
270
271
272   if [ "$resolvsym" -gt 0 ] ; then
273     rm -f /tmp/resolv.conf
274
275
276     {
277       # Set resolver file to local but not if /etc/init.d/dnsmasq will do it.
278       echo "nameserver 127.0.0.1"
279       echo "nameserver ::1"
280       echo "search $UNBOUND_TXT_DOMAIN"
281     } > /tmp/resolv.conf
282   fi
283
284
285   if [ "$UNBOUND_D_DHCP_LINK" = "odhcpd" -a ! -d "$dhcp_dir" ] ; then
286     # make sure odhcpd has a directory to write (not done itself, yet)
287     mkdir -p "$dhcp_dir"
288   fi
289
290
291   if [ -f $UNBOUND_KEYFILE ] ; then
292     filestuff=$( cat $UNBOUND_KEYFILE )
293
294
295     case "$filestuff" in
296       *"state=2 [  VALID  ]"*)
297         # Lets not lose RFC 5011 tracking if we don't have to
298         cp -p $UNBOUND_KEYFILE $UNBOUND_KEYFILE.keep
299         ;;
300     esac
301   fi
302
303
304   # Blind copy /etc/ to /var/lib/
305   mkdir -p $UNBOUND_VARDIR
306   rm -f $UNBOUND_VARDIR/dhcp_*
307   touch $UNBOUND_CONFFILE
308   touch $UNBOUND_SRV_CONF
309   touch $UNBOUND_EXT_CONF
310   cp -p /etc/unbound/* $UNBOUND_VARDIR/
311
312
313   if [ ! -f $UNBOUND_HINTFILE ] ; then
314     if [ -f /usr/share/dns/root.hints ] ; then
315       # Debian-like package dns-root-data
316       cp -p /usr/share/dns/root.hints $UNBOUND_HINTFILE
317
318     elif [ ! -f "$UNBOUND_TIMEFILE" ] ; then
319       logger -t unbound -s "iterator will use built-in root hints"
320     fi
321   fi
322
323
324   if [ ! -f $UNBOUND_KEYFILE ] ; then
325     if [ -f /usr/share/dns/root.key ] ; then
326       # Debian-like package dns-root-data
327       cp -p /usr/share/dns/root.key $UNBOUND_KEYFILE
328
329     elif [ -x $UNBOUND_ANCHOR ] ; then
330       $UNBOUND_ANCHOR -a $UNBOUND_KEYFILE
331
332     elif [ ! -f "$UNBOUND_TIMEFILE" ] ; then
333       logger -t unbound -s "validator will use built-in trust anchor"
334     fi
335   fi
336
337
338   copy_dash_update
339
340
341   # Ensure access and prepare to jail
342   chown -R unbound:unbound $UNBOUND_VARDIR
343   chmod 775 $UNBOUND_VARDIR
344   chmod 664 $UNBOUND_VARDIR/*
345 }
346
347 ##############################################################################
348
349 unbound_control() {
350   if [ "$UNBOUND_B_CONTROL" -gt 0 ] ; then
351     {
352       # Enable remote control tool, but only at local host for security
353       # You can hand write fancier encrypted access with /etc/..._ext.conf
354       echo "remote-control:"
355       echo "  control-enable: yes"
356       echo "  control-use-cert: no"
357       echo "  control-interface: 127.0.0.1"
358       echo "  control-interface: ::1"
359       echo
360     } >> $UNBOUND_CONFFILE
361   fi
362
363
364   {
365     # Amend your own extended clauses here like forward zones or disable
366     # above (local, no encryption) and amend your own remote encrypted control
367     echo
368     echo "include: $UNBOUND_EXT_CONF" >> $UNBOUND_CONFFILE
369     echo
370   } >> $UNBOUND_CONFFILE
371 }
372
373 ##############################################################################
374
375 unbound_conf() {
376   local cfg="$1"
377   local rt_mem rt_conn modulestring
378
379
380   {
381     # Make fresh conf file
382     echo "# $UNBOUND_CONFFILE generated by UCI $( date )"
383     echo
384   } > $UNBOUND_CONFFILE
385
386
387   {
388     # No threading
389     echo "server:"
390     echo "  username: unbound"
391     echo "  num-threads: 1"
392     echo "  msg-cache-slabs: 1"
393     echo "  rrset-cache-slabs: 1"
394     echo "  infra-cache-slabs: 1"
395     echo "  key-cache-slabs: 1"
396     echo
397   } >> $UNBOUND_CONFFILE
398
399
400   {
401     # Logging
402     echo "  verbosity: 1"
403     echo "  statistics-interval: 0"
404     echo "  statistics-cumulative: no"
405     echo "  extended-statistics: no"
406     echo
407   } >> $UNBOUND_CONFFILE
408
409
410   {
411     # Interfaces (access contol "option local_service")
412     echo "  interface: 0.0.0.0"
413     echo "  interface: ::0"
414     echo "  outgoing-interface: 0.0.0.0"
415     echo "  outgoing-interface: ::0"
416     echo
417   } >> $UNBOUND_CONFFILE
418
419
420   case "$UNBOUND_D_PROTOCOL" in
421     ip4_only)
422       {
423         echo "  do-ip4: yes"
424         echo "  do-ip6: no"
425       } >> $UNBOUND_CONFFILE
426       ;;
427
428     ip6_only)
429       {
430         echo "  do-ip4: no"
431         echo "  do-ip6: yes"
432       } >> $UNBOUND_CONFFILE
433       ;;
434
435     ip6_prefer)
436       {
437         echo "  do-ip4: yes"
438         echo "  do-ip6: yes"
439         echo "  prefer-ip6: yes"
440       } >> $UNBOUND_CONFFILE
441       ;;
442
443     *)
444       {
445         echo "  do-ip4: yes"
446         echo "  do-ip6: yes"
447       } >> $UNBOUND_CONFFILE
448       ;;
449   esac
450
451
452   {
453     # protocol level tuning
454     echo "  edns-buffer-size: $UNBOUND_N_EDNS_SIZE"
455     echo "  msg-buffer-size: 8192"
456     echo "  port: $UNBOUND_N_RX_PORT"
457     echo "  outgoing-port-permit: 10240-65535"
458     echo
459   } >> $UNBOUND_CONFFILE
460
461
462   {
463     # Other harding and options for an embedded router
464     echo "  harden-short-bufsize: yes"
465     echo "  harden-large-queries: yes"
466     echo "  harden-glue: yes"
467     echo "  harden-below-nxdomain: no"
468     echo "  harden-referral-path: no"
469     echo "  use-caps-for-id: no"
470     echo
471   } >> $UNBOUND_CONFFILE
472
473
474   {
475     # Default Files
476     echo "  use-syslog: yes"
477     echo "  chroot: \"$UNBOUND_VARDIR\""
478     echo "  directory: \"$UNBOUND_VARDIR\""
479     echo "  pidfile: \"$UNBOUND_PIDFILE\""
480   } >> $UNBOUND_CONFFILE
481
482
483   if [ -f "$UNBOUND_HINTFILE" ] ; then
484     # Optional hints if found
485     echo "  root-hints: \"$UNBOUND_HINTFILE\"" >> $UNBOUND_CONFFILE
486   fi
487
488
489   if [ "$UNBOUND_B_DNSSEC" -gt 0 -a -f "$UNBOUND_KEYFILE" ] ; then
490     {
491       echo "  auto-trust-anchor-file: \"$UNBOUND_KEYFILE\""
492       echo
493     } >> $UNBOUND_CONFFILE
494
495   else
496     echo >> $UNBOUND_CONFFILE
497   fi
498
499
500   case "$UNBOUND_D_RESOURCE" in
501     # Tiny - Unbound's recommended cheap hardware config
502     tiny)   rt_mem=1  ; rt_conn=1 ;;
503     # Small - Half RRCACHE and open ports
504     small)  rt_mem=8  ; rt_conn=5 ;;
505     # Medium - Nearly default but with some added balancintg
506     medium) rt_mem=16 ; rt_conn=10 ;;
507     # Large - Double medium
508     large)  rt_mem=32 ; rt_conn=10 ;;
509     # Whatever unbound does
510     *) rt_mem=0 ; rt_conn=0 ;;
511   esac
512
513
514   if [ "$rt_mem" -gt 0 ] ; then
515     {
516       # Set memory sizing parameters
517       echo "  outgoing-range: $(($rt_conn*64))"
518       echo "  num-queries-per-thread: $(($rt_conn*32))"
519       echo "  outgoing-num-tcp: $(($rt_conn))"
520       echo "  incoming-num-tcp: $(($rt_conn))"
521       echo "  rrset-cache-size: $(($rt_mem*256))k"
522       echo "  msg-cache-size: $(($rt_mem*128))k"
523       echo "  key-cache-size: $(($rt_mem*128))k"
524       echo "  neg-cache-size: $(($rt_mem*64))k"
525       echo "  infra-cache-numhosts: $(($rt_mem*256))"
526       echo
527     } >> $UNBOUND_CONFFILE
528
529   elif [ ! -f "$UNBOUND_TIMEFILE" ] ; then
530     logger -t unbound -s "default memory resource consumption"
531   fi
532
533   # Assembly of module-config: options is tricky; order matters
534   modulestring="iterator"
535
536
537   if [ "$UNBOUND_B_DNSSEC" -gt 0 ] ; then
538     if [ ! -f "$UNBOUND_TIMEFILE" -a "$UNBOUND_B_NTP_BOOT" -gt 0 ] ; then
539       # DNSSEC chicken and egg with getting NTP time
540       echo "  val-override-date: -1" >> $UNBOUND_CONFFILE
541     fi
542
543
544     {
545       echo "  harden-dnssec-stripped: yes"
546       echo "  val-clean-additional: yes"
547       echo "  ignore-cd-flag: yes"
548     } >> $UNBOUND_CONFFILE
549
550
551     modulestring="validator $modulestring"
552   fi
553
554
555   if [ "$UNBOUND_B_DNS64" -gt 0 ] ; then
556     echo "  dns64-prefix: $UNBOUND_IP_DNS64" >> $UNBOUND_CONFFILE
557
558     modulestring="dns64 $modulestring"
559   fi
560
561
562   {
563     # Print final module string
564     echo "  module-config: \"$modulestring\""
565     echo
566   }  >> $UNBOUND_CONFFILE
567
568
569   if [ "$UNBOUND_B_QRY_MINST" -gt 0 -a "$UNBOUND_B_QUERY_MIN" -gt 0 ] ; then
570     {
571       # Some query privacy but "strict" will break some name servers
572       echo "  qname-minimisation: yes"
573       echo "  qname-minimisation-strict: yes"
574     } >> $UNBOUND_CONFFILE
575
576   elif [ "$UNBOUND_B_QUERY_MIN" -gt 0 ] ; then
577     # Minor improvement on query privacy
578     echo "  qname-minimisation: yes" >> $UNBOUND_CONFFILE
579
580   else
581     echo "  qname-minimisation: no" >> $UNBOUND_CONFFILE
582   fi
583
584
585   case "$UNBOUND_D_RECURSION" in
586     passive)
587       {
588         echo "  prefetch: no"
589         echo "  prefetch-key: no"
590         echo "  target-fetch-policy: \"0 0 0 0 0\""
591         echo
592       } >> $UNBOUND_CONFFILE
593       ;;
594
595     aggressive)
596       {
597         echo "  prefetch: yes"
598         echo "  prefetch-key: yes"
599         echo "  target-fetch-policy: \"3 2 1 0 0\""
600         echo
601       } >> $UNBOUND_CONFFILE
602       ;;
603
604     *)
605       if [ ! -f "$UNBOUND_TIMEFILE" ] ; then
606         logger -t unbound -s "default recursion configuration"
607       fi
608       ;;
609   esac
610
611
612   {
613     # Reload records more than 10 hours old
614     # DNSSEC 5 minute bogus cool down before retry
615     # Adaptive infrastructure info kept for 15 minutes
616     echo "  cache-min-ttl: $UNBOUND_TTL_MIN"
617     echo "  cache-max-ttl: 36000"
618     echo "  val-bogus-ttl: 300"
619     echo "  infra-host-ttl: 900"
620     echo
621   } >> $UNBOUND_CONFFILE
622
623
624   if [ "$UNBOUND_B_HIDE_BIND" -gt 0 ] ; then
625     {
626       # Block server id and version DNS TXT records
627       echo "  hide-identity: yes"
628       echo "  hide-version: yes"
629       echo
630     } >> $UNBOUND_CONFFILE
631   fi
632
633
634   if [ "$UNBOUND_B_PRIV_BLCK" -gt 0 ] ; then
635     {
636       # Remove _upstream_ or global reponses with private addresses.
637       # Unbounds own "local zone" and "forward zone" may still use these.
638       # RFC1918, RFC3927, RFC4291, RFC6598, RFC6890
639       echo "  private-address: 10.0.0.0/8"
640       echo "  private-address: 100.64.0.0/10"
641       echo "  private-address: 169.254.0.0/16"
642       echo "  private-address: 172.16.0.0/12"
643       echo "  private-address: 192.168.0.0/16"
644       echo "  private-address: fc00::/8"
645       echo "  private-address: fd00::/8"
646       echo "  private-address: fe80::/10"
647     } >> $UNBOUND_CONFFILE
648   fi
649
650
651   if [ "$UNBOUND_B_LOCL_BLCK" -gt 0 ] ; then
652     {
653       # Remove DNS reponses from upstream with loopback IP
654       # Black hole DNS method for ad blocking, so consider...
655       echo "  private-address: 127.0.0.0/8"
656       echo "  private-address: ::1/128"
657       echo
658     } >> $UNBOUND_CONFFILE
659
660   else
661     echo >> $UNBOUND_CONFFILE
662   fi
663
664
665   # Except and accept domains as insecure (DNSSEC); work around broken domains
666   config_list_foreach "$cfg" "domain_insecure" create_domain_insecure
667   echo >> $UNBOUND_CONFFILE
668 }
669
670 ##############################################################################
671
672 unbound_access() {
673   # TODO: Unbound 1.6.0 added "tags" and "views", so we can add tags to
674   # each access-control IP block, and then divert access.
675   # -- "guest" WIFI will not be allowed to see local zone data
676   # -- "child" LAN can black whole a list of domains to http~deadpixel
677
678
679   if [ "$UNBOUND_B_LOCL_SERV" -gt 0 ] ; then
680     # Only respond to queries from which this device has an interface.
681     # Prevent DNS amplification attacks by not responding to the universe.
682     config_load network
683     config_foreach create_access_control interface
684
685
686     {
687       echo "  access-control: 127.0.0.0/8 allow"
688       echo "  access-control: ::1/128 allow"
689       echo "  access-control: fe80::/10 allow"
690       echo
691     } >> $UNBOUND_CONFFILE
692
693   else
694     {
695       echo "  access-control: 0.0.0.0/0 allow"
696       echo "  access-control: ::0/0 allow"
697       echo
698     } >> $UNBOUND_CONFFILE
699   fi
700
701
702   {
703     # Amend your own "server:" stuff here
704     echo "  include: $UNBOUND_SRV_CONF"
705     echo
706   } >> $UNBOUND_CONFFILE
707 }
708
709 ##############################################################################
710
711 unbound_adblock() {
712   # TODO: Unbound 1.6.0 added "tags" and "views"; lets work with adblock team
713   local adb_enabled adb_file
714
715   if [ ! -x /usr/bin/adblock.sh -o ! -x /etc/init.d/adblock ] ; then
716     adb_enabled=0
717   else
718     /etc/init.d/adblock enabled && adb_enabled=1 || adb_enabled=0
719   fi
720
721
722   if [ "$adb_enabled" -gt 0 ] ; then
723     {
724       # Pull in your selected openwrt/pacakges/net/adblock generated lists
725       for adb_file in $UNBOUND_VARDIR/adb_list.* ; do
726         echo "  include: $adb_file"
727       done
728       echo
729     } >> $UNBOUND_CONFFILE
730   fi
731 }
732
733 ##############################################################################
734
735 unbound_hostname() {
736   if [ -n "$UNBOUND_TXT_DOMAIN" ] ; then
737     {
738       # TODO: Unbound 1.6.0 added "tags" and "views" and we could make
739       # domains by interface to prevent DNS from "guest" to "home"
740       echo "  local-zone: $UNBOUND_TXT_DOMAIN. $UNBOUND_D_DOMAIN_TYPE"
741       echo "  domain-insecure: $UNBOUND_TXT_DOMAIN"
742       echo "  private-domain: $UNBOUND_TXT_DOMAIN"
743       echo
744       echo "  local-zone: $UNBOUND_TXT_HOSTNAME. $UNBOUND_D_DOMAIN_TYPE"
745       echo "  domain-insecure: $UNBOUND_TXT_HOSTNAME"
746       echo "  private-domain: $UNBOUND_TXT_HOSTNAME"
747       echo
748     } >> $UNBOUND_CONFFILE
749
750
751     case "$UNBOUND_D_DOMAIN_TYPE" in
752     deny|inform_deny|refuse|static)
753       {
754         # avoid upstream involvement in RFC6762 like responses (link only)
755         echo "  local-zone: local. $UNBOUND_D_DOMAIN_TYPE"
756         echo "  domain-insecure: local"
757         echo "  private-domain: local"
758         echo
759       } >> $UNBOUND_CONFFILE
760       ;;
761     esac
762
763
764     if [ "$UNBOUND_D_LAN_FQDN" -gt 0 -o "$UNBOUND_D_WAN_FQDN" -gt 0 ] ; then
765       config_load dhcp
766       config_foreach create_interface_dns dhcp
767     fi
768
769
770     if [ -f "$UNBOUND_DHCP_CONF" ] ; then
771       {
772         # Seed DHCP records because dhcp scripts trigger externally
773         # Incremental Unbound restarts may drop unbound-control add records
774         echo "  include: $UNBOUND_DHCP_CONF"
775         echo
776       } >> $UNBOUND_CONFFILE
777     fi
778   fi
779 }
780
781 ##############################################################################
782
783 unbound_uci() {
784   local cfg="$1"
785   local dnsmasqpath hostnm
786
787   hostnm="$(uci_get system.@system[0].hostname | awk '{print tolower($0)}')"
788   UNBOUND_TXT_HOSTNAME=${hostnm:-thisrouter}
789
790   config_get_bool UNBOUND_B_SLAAC6_MAC "$cfg" dhcp4_slaac6 0
791   config_get_bool UNBOUND_B_DNS64      "$cfg" dns64 0
792   config_get_bool UNBOUND_B_HIDE_BIND  "$cfg" hide_binddata 1
793   config_get_bool UNBOUND_B_LOCL_SERV  "$cfg" localservice 1
794   config_get_bool UNBOUND_B_MAN_CONF   "$cfg" manual_conf 0
795   config_get_bool UNBOUND_B_QUERY_MIN  "$cfg" query_minimize 0
796   config_get_bool UNBOUND_B_QRY_MINST  "$cfg" query_min_strict 0
797   config_get_bool UNBOUND_B_PRIV_BLCK  "$cfg" rebind_protection 1
798   config_get_bool UNBOUND_B_LOCL_BLCK  "$cfg" rebind_localhost 0
799   config_get_bool UNBOUND_B_CONTROL    "$cfg" unbound_control 0
800   config_get_bool UNBOUND_B_DNSSEC     "$cfg" validator 0
801   config_get_bool UNBOUND_B_NTP_BOOT   "$cfg" validator_ntp 1
802
803   config_get UNBOUND_IP_DNS64    "$cfg" dns64_prefix "64:ff9b::/96"
804
805   config_get UNBOUND_N_EDNS_SIZE "$cfg" edns_size 1280
806   config_get UNBOUND_N_RX_PORT   "$cfg" listen_port 53
807   config_get UNBOUND_N_ROOT_AGE  "$cfg" root_age 9
808
809   config_get UNBOUND_D_DOMAIN_TYPE "$cfg" domain_type static
810   config_get UNBOUND_D_DHCP_LINK   "$cfg" dhcp_link none
811   config_get UNBOUND_D_LAN_FQDN    "$cfg" add_local_fqdn 0
812   config_get UNBOUND_D_PROTOCOL    "$cfg" protocol mixed
813   config_get UNBOUND_D_RECURSION   "$cfg" recursion passive
814   config_get UNBOUND_D_RESOURCE    "$cfg" resource small
815   config_get UNBOUND_D_WAN_FQDN    "$cfg" add_wan_fqdn 0
816
817   config_get UNBOUND_TTL_MIN     "$cfg" ttl_min 120
818   config_get UNBOUND_TXT_DOMAIN  "$cfg" domain lan
819
820
821   if [ "$UNBOUND_D_DHCP_LINK" = "none" ] ; then
822     config_get_bool UNBOUND_B_DNSMASQ   "$cfg" dnsmasq_link_dns 0
823
824
825     if [ "$UNBOUND_B_DNSMASQ" -gt 0 ] ; then
826       UNBOUND_D_DHCP_LINK=dnsmasq
827       
828       
829       if [ ! -f "$UNBOUND_TIMEFILE" ] ; then
830         logger -t unbound -s "Please use 'dhcp_link' selector instead"
831       fi
832     fi
833   fi
834
835
836   if [ "$UNBOUND_D_DHCP_LINK" = "dnsmasq" ] ; then
837     if [ ! -x /usr/sbin/dnsmasq -o ! -x /etc/init.d/dnsmasq ] ; then
838       UNBOUND_D_DHCP_LINK=none
839     else
840       /etc/init.d/dnsmasq enabled || UNBOUND_D_DHCP_LINK=none
841     fi
842
843
844     if [ "$UNBOUND_D_DHCP_LINK" = "none" -a ! -f "$UNBOUND_TIMEFILE" ] ; then
845       logger -t unbound -s "cannot forward to dnsmasq"
846     fi
847   fi
848
849
850   if [ "$UNBOUND_D_DHCP_LINK" = "odhcpd" ] ; then
851     if [ ! -x /usr/sbin/odhcpd -o ! -x /etc/init.d/odhcpd ] ; then
852       UNBOUND_D_DHCP_LINK=none
853     else
854       /etc/init.d/odhcpd enabled || UNBOUND_D_DHCP_LINK=none
855     fi
856
857
858     if [ "$UNBOUND_D_DHCP_LINK" = "none" -a ! -f "$UNBOUND_TIMEFILE" ] ; then
859       logger -t unbound -s "cannot receive records from odhcpd"
860     fi
861   fi
862
863
864   if [ "$UNBOUND_N_EDNS_SIZE" -lt 512 \
865     -o 4096 -lt "$UNBOUND_N_EDNS_SIZE" ] ; then
866     # exceeds range, back to default
867     UNBOUND_N_EDNS_SIZE=1280
868   fi
869
870
871   if [ "$UNBOUND_N_RX_PORT" -lt 1024 \
872     -o 10240 -lt "$UNBOUND_N_RX_PORT" ] ; then
873     # special port or in 5 digits, back to default
874     UNBOUND_N_RX_PORT=53
875   fi
876
877
878   if [ "$UNBOUND_TTL_MIN" -gt 1800 ] ; then
879     # that could have had awful side effects
880     UNBOUND_TTL_MIN=300
881   fi
882 }
883
884 ##############################################################################
885
886 unbound_start() {
887   config_load unbound
888   config_foreach unbound_uci unbound
889   unbound_mkdir
890
891
892   if [ "$UNBOUND_B_MAN_CONF" -eq 0 ] ; then
893     unbound_conf
894     unbound_access
895     unbound_adblock
896
897     if [ "$UNBOUND_D_DHCP_LINK" = "dnsmasq" ] ; then
898       dnsmasq_link
899     else
900       unbound_hostname
901     fi
902
903     unbound_control
904   fi
905 }
906
907 ##############################################################################
908
909 unbound_stop() {
910   local resolvsym=0
911
912   rootzone_update
913
914
915   if [ ! -x /usr/sbin/dnsmasq -o ! -x /etc/init.d/dnsmasq ] ; then
916     resolvsym=1
917   else
918     /etc/init.d/dnsmasq enabled || resolvsym=1
919   fi
920
921
922   if [ "$resolvsym" -gt 0 ] ; then
923     # set resolver file to normal, but don't stomp on dnsmasq
924     rm -f /tmp/resolv.conf
925     ln -s /tmp/resolv.conf.auto /tmp/resolv.conf
926   fi
927 }
928
929 ##############################################################################
930