You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1200 lines
32 KiB

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