--- /dev/null
+menu "Configuration"
+ depends on PACKAGE_getdns
+
+config GETDNS_ENABLE_STUB_ONLY
+ bool "GETDNS_ENABLE_STUB_ONLY"
+ help
+ getdns can be configured for stub resolution mode only. (Removes libunbound dependency)
+ default y
+
+config GETDNS_ENABLE_IDN_LIBIDN2
+ bool "GETDNS_ENABLE_IDN_LIBIDN2"
+ help
+ getdns can be configured with some IDN Support. (Requires libidn2 dependency)
+ default n
+
+endmenu
--- /dev/null
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=getdns
+PKG_VERSION:=1.5.2
+PKG_RELEASE:=2
+
+PKG_LICENSE:=BSD-3-Clause
+PKG_LICENSE_FILES:=LICENSE
+PKG_MAINTAINER:=Jonathan Underwood <jonathan.underwood@gmail.com>
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://getdnsapi.net/dist/
+PKG_HASH:=1826a6a221ea9e9301f2c1f5d25f6f5588e841f08b967645bf50c53b970694c0
+
+PKG_FIXUP:=autoreconf
+
+PKG_INSTALL:=1
+
+PKG_CONFIG_DEPENDS:= \
+ CONFIG_GETDNS_ENABLE_STUB_ONLY \
+ CONFIG_GETDNS_ENABLE_IDN_LIBIDN2
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/getdns/Default
+ TITLE:=getdns
+ URL:=https://getdnsapi.net/
+endef
+
+define Package/getdns
+ $(call Package/getdns/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+= (library)
+ DEPENDS+= +libopenssl +!GETDNS_ENABLE_STUB_ONLY:libunbound +GETDNS_ENABLE_IDN_LIBIDN2:libidn2
+ MENU:=1
+endef
+
+define Package/getdns/description
+ This package contains the getdns library (libgetdns).
+ This package also contains the "getdns_query" command line wrapper for getdns exposing the features of this implementation (both in the official API and the additional API functions).
+endef
+
+define Package/getdns/config
+ source "$(SOURCE)/Config.in"
+endef
+
+CONFIGURE_ARGS += \
+ $(if $(CONFIG_GETDNS_ENABLE_STUB_ONLY), --enable-stub-only, ) \
+ --without-libidn \
+ $(if $(CONFIG_GETDNS_ENABLE_IDN_LIBIDN2), , --without-libidn2 ) \
+ --with-ssl="$(STAGING_DIR)/usr" \
+
+# This will make 'configure' think that our libbsd.so is missing the
+# functions inet_pton, inet_ntop, strlcpy and use the builtin. This
+# removes the libbsd dependency
+CONFIGURE_VARS += LIBBSD_LIBS=-lc
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/getdns/
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/getdns/getdns*.h $(1)/usr/include/getdns/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libgetdns*.{a,so*} $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/getdns*.pc $(1)/usr/lib/pkgconfig/
+endef
+
+
+define Package/getdns/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libgetdns.so.* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/getdns_query $(1)/usr/sbin/getdns_query
+endef
+
+$(eval $(call BuildPackage,getdns))
--- /dev/null
+#
+# Copyright (C) 2008-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=yaml
+PKG_VERSION:=0.2.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://pyyaml.org/download/libyaml/
+PKG_HASH:=4a9100ab61047fd9bd395bcef3ce5403365cafd55c1e0d0299cde14958e47be9
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:pyyaml_project:pyyaml
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libyaml
+ SUBMENU:=Languages
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Fast YAML 1.1 parser and emitter library
+ URL:=https://pyyaml.org/wiki/LibYAML
+endef
+
+TARGET_CFLAGS += $(FPIC)
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/yaml.h $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libyaml*.{a,so*} $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/yaml*.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/libyaml/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libyaml*.so* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,libyaml))
--- /dev/null
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=darkstat
+PKG_VERSION:=3.0.719
+PKG_RELEASE:=4
+
+PKG_MAINTAINER:=Jean-Michel Lacroix <lacroix@lepine-lacroix.info>
+
+PKG_LICENSE:=GPL-2.0 BSD-ISC
+PKG_LICENSE_FILES:=COPYING.GPL LICENSE
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://unix4lyfe.org/darkstat
+PKG_HASH:=aeaf909585f7f43dc032a75328fdb62114e58405b06a92a13c0d3653236dedd7
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/darkstat
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=+libpcap +zlib
+ TITLE:=Network bandwidth monitor
+ URL:=http://unix4lyfe.org/darkstat/
+endef
+
+define Package/darkstat/description
+darkstat is a packet sniffer that runs as a background process on a cable/DSL
+router, gathers all sorts of statistics about network usage, and serves them
+over HTTP.
+endef
+
+define Package/darkstat/conffiles
+/etc/config/darkstat
+endef
+
+CONFIGURE_ARGS += \
+ --disable-debug \
+ --with-chroot-dir=/var/empty
+
+CONFIGURE_VARS += \
+ ac_cv_search_setproctitle=no \
+ ac_cv_search_strlcpy=no \
+ ac_cv_search_strlcat=no
+
+define Build/Compile
+ $(HOSTCC) $(PKG_BUILD_DIR)/static/c-ify.c \
+ -o $(PKG_BUILD_DIR)/c-ify
+ $(call Build/Compile/Default)
+endef
+
+define Package/darkstat/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/darkstat $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/darkstat.init $(1)/etc/init.d/darkstat
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) ./files/darkstat.config $(1)/etc/config/darkstat
+endef
+
+$(eval $(call BuildPackage,darkstat))
--- /dev/null
+config darkstat
+ option interface 'lan'
+ option syslog false
+ option verbose false
+ option no_promisc false
+ option no_dns false
+ option no_macs false
+ option no_lastseen false
+ option httpaddr '0.0.0.0'
+# option httpport '667'
+# option network_filter 'not (src net 192.168.1 and dst net 192.168.1)'
+# option network_netmask '192.168.1.0/255.255.255.0'
+ option local_only false
+# option hosts_max '1000'
+# option hosts_keep '500'
+# option ports_max '60'
+# option ports_keep '30'
+# option highest_port '65534'
+# option export_file 'darkstat_export.log'
+# option import_file 'darkstat_export.log'
+# option daylog_file 'darkstat_daylog.log'
--- /dev/null
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2018 Jean-Michel Lacroix
+
+USE_PROCD=1
+
+START=60
+
+APP=darkstat
+RUN_D=/var/empty
+PID_F=$RUN_D/$APP.pid
+CONFIGNAME=darkstat
+USER=nobody
+GROUP=nogroup
+
+CONFIGSTR=""
+FILTERSTR=""
+
+export_bool () {
+ local option="$1"
+ local section="$2"
+ local _keystr="$3"
+ local _loctmp
+ config_get_bool _loctmp "$section" "$option"
+ if [ -n "$_loctmp" ]; then
+ if [ 1 -eq "$_loctmp" ]; then
+ CONFIGSTR="$CONFIGSTR${_keystr} "
+ fi
+ fi
+}
+
+set_config_string(){
+ mkdir -p $RUN_D
+ chown $USER:$GROUP $RUN_D
+ . /lib/functions/network.sh
+ config_load $CONFIGNAME
+ config_foreach build_config_string darkstat
+}
+
+build_config_string() {
+ local cfg="$1"
+ config_get interface $cfg interface
+ network_get_device ifname "$interface"
+ CONFIGSTR=" -i $ifname "
+ export_bool syslog $cfg "--syslog"
+ export_bool verbose $cfg "--verbose"
+ # We need the --no-daemon parameter as with PROCD the process has to run in the background
+ CONFIGSTR="$CONFIGSTR--no-daemon "
+ export_bool no_promisc $cfg "--no-promisc"
+ export_bool no_dns $cfg "--no-dns"
+ export_bool no_macs $cfg "--no-macs"
+ export_bool no_lastseen $cfg "--no-lastseen"
+ config_get httpaddr $cfg httpaddr
+ CONFIGSTR="$CONFIGSTR${httpaddr:+-b "$httpaddr"} "
+ config_get httpport $cfg httpport
+ CONFIGSTR="$CONFIGSTR${httpport:+-p "$httpport"} "
+ config_get network_netmask $cfg network_netmask
+ CONFIGSTR="$CONFIGSTR${network_netmask:+-l "$network_netmask"} "
+ export_bool local_only $cfg "--local-only"
+ config_get hosts_max $cfg hosts_max
+ CONFIGSTR="$CONFIGSTR${hosts_max:+--hosts-max "$hosts_max"} "
+ config_get hosts_keep $cfg hosts_keep
+ CONFIGSTR="$CONFIGSTR${ports_keep:+--ports-keep "$ports_keep"} "
+ config_get highest_port $cfg highest_port
+ CONFIGSTR="$CONFIGSTR${highest_port:+--highest-port "$highest_port"} "
+ config_get export_file $cfg export_file
+ CONFIGSTR="$CONFIGSTR${export_file:+--export "$export_file"} "
+ config_get import_file $cfg import_file
+ CONFIGSTR="$CONFIGSTR${import_file:+--import "$import_file"} "
+ config_get daylog_file $cfg daylog_file
+ CONFIGSTR="$CONFIGSTR${daylog_file:+--daylog "$daylog_file"} "
+ CONFIGSTR="$CONFIGSTR--chroot $RUN_D --pidfile $PID_F"
+ # Now that we have the configuration string (CONFIGSTR), let us get the filter (FILTERSTR)
+ config_get network_filter $cfg network_filter
+ FILTERSTR="${network_filter:+$network_filter}"
+}
+
+service_triggers() {
+ procd_add_reload_trigger $CONFIGNAME
+}
+
+start_service() {
+ set_config_string
+ procd_open_instance
+ procd_set_param command /usr/sbin/$APP
+ procd_append_param command $CONFIGSTR
+ # Let us check if we have a filter string and apply it if we do
+ if [ "$FILTERSTR" != "" ]; then
+ procd_append_param command "-f" "$FILTERSTR"
+ fi
+ procd_close_instance
+}
+
+stop_service() {
+ rm -f $PID_F
+}
+
+reload_service() {
+ stop
+ start
+}
--- /dev/null
+--- a/dns.c
++++ b/dns.c
+@@ -347,9 +347,6 @@ dns_main(void)
+
+ reply.addr = ip;
+ flags = NI_NAMEREQD;
+-# ifdef NI_IDN
+- flags |= NI_IDN;
+-# endif
+ switch (ip.family) {
+ case IPv4:
+ sin.sin_family = AF_INET;
--- /dev/null
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=stubby
+PKG_VERSION:=0.2.6
+PKG_RELEASE:=1
+
+PKG_LICENSE:=BSD-3-Clause
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINTAINER:=Jonathan Underwood <jonathan.underwood@gmail.com>
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/getdnsapi/$(PKG_NAME)
+PKG_SOURCE_VERSION:=v$(PKG_VERSION)
+PKG_MIRROR_HASH:=af896c471ac67b31c2263d11fcdfcdb32a213621c2f8789f4b0a4ceca4437108
+
+PKG_FIXUP:=autoreconf
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/stubby/Default
+ TITLE:=stubby
+ URL:=https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Daemon+-+Stubby
+endef
+
+define Package/stubby
+ $(call Package/stubby/Default)
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=IP Addresses and Names
+ TITLE+= - (daemon that uses getdns)
+ USERID:=stubby=410:stubby=410
+ DEPENDS:= +libyaml +getdns +ca-certificates
+endef
+
+define Package/stubby/description
+ This package contains the Stubby daemon (which utilizes the getdns library).
+
+ See https://github.com/openwrt/packages/blob/master/net/stubby/files/README.md for more details.
+endef
+
+define Package/stubby/conffiles
+/etc/stubby/stubby.yml
+endef
+
+define Package/stubby/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/stubby $(1)/usr/sbin/stubby
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/stubby.init $(1)/etc/init.d/stubby
+ $(INSTALL_DIR) $(1)/etc/stubby
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/stubby/stubby.yml $(1)/etc/stubby/stubby.yml.default
+ $(INSTALL_DATA) ./files/stubby.yml $(1)/etc/stubby/stubby.yml
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/stubby.conf $(1)/etc/config/stubby
+endef
+
+
+define Package/stubby/conffiles
+ /etc/stubby/stubby.yml
+ /etc/config/stubby
+endef
+
+$(eval $(call BuildPackage,stubby))
--- /dev/null
+
+# Stubby for OpenWRT
+
+## Stubby Description
+
+[Stubby](https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Daemon+-+Stubby) is
+an application that acts as a local DNS Privacy stub resolver (using
+DNS-over-TLS). Stubby encrypts DNS queries sent from a client machine to a DNS
+Privacy resolver increasing end user privacy.
+
+Stubby is useful on an OpenWRT device, because it can sit between the usual DNS
+resolver (dnsmasq by default) and the upstream DNS resolver and be used to
+ensure that DNS traffic is encrypted between the OpenWRT device and the
+resolver.
+
+Stubby is developed by the [getdns](http://getdnsapi.net/) project.
+
+For more background and FAQ see the [About
+Stubby](https://dnsprivacy.org/wiki/display/DP/About+Stubby) page.
+
+
+## Installation
+
+Installation of this package can be achieved at the command line using `opkg
+install stubby`, or via the LUCI Web Interface. Installing the stubby package
+will also install the required dependency packages, including the
+`ca-certificates` package.
+
+## Configuration
+
+The default configuration of the package has been chosen to ensure that stubby
+should work after installation.
+
+By default, configuration of stubby is integrated with the OpenWRT UCI system
+using the file `/etc/config/stubby`. The configuration options available are
+also documented in that file. If for some reason you wish to configure stubby
+using the `/etc/stubby/stubby.yml` file, then you simply need to set `option
+manual '1'` in `/etc/config/stubby` and all other settings in
+`/etc/config/stubby` will be ignored.
+
+### Stubby port and addresses
+
+The default configuration ensures that stubby listens on port 5453 on the
+loopback interfaces for IPv4 and IPv6. As such, by default, stubby will respond
+only to lookups from the OpenWRT device itself.
+
+By setting the listening ports to non-standard values, this allows users to keep
+the main name server daemon in place (dnsmasq/unbound/etc.) and have that name
+server forward to stubby.
+
+### Upstream resolvers
+
+The default package configuration uses the CloudFlare resolvers, configured for
+both IPv4 and IPv6.
+
+CloudFlare have not published SPKI pinsets, and even though they are available,
+they have made no commitment to maintaining them. Using the currently known SPKI
+pinsets for CloudFlare brings the risk that in the future they may be changed by
+CloudFlare, and DNS would stop working. The default configuration has those SPKI
+entries commented out for this reason.
+
+[CloudFlare's privacy
+statement](https://developers.cloudflare.com/1.1.1.1/commitment-to-privacy/)
+details how they treat data from DNS requests.
+
+More resolvers are available in the [upstream stubby example
+configuration](https://github.com/getdnsapi/stubby/blob/develop/stubby.yml.example)
+and the [DNS Privacy
+list](https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Test+Servers).
+
+## Integration of stubby with dnsmasq
+
+The recommended way to use stubby on an OpenWRT device is to integrate it with a
+caching resolver. The default caching resolver in OpenWRT is dnsmasq.
+
+### Set dnsmasq to send DNS requests to stubby
+
+Since dnsmasq responds to LAN DNS requests on port 53 of the OpenWRT device by
+default, all that is required is to have dnsmasq forward those requests to
+stubby which is listening on port 5453 of the OpenWRT device. To achieve this,
+we need to set the `server` option in the dnsmasq configuration in the
+`/etc/config/dhcp` file to `'127.0.0.1#5453'`. We also need to tell dnsmasq not
+to use resolvers found in `/etc/resolv.conf` by setting the dnsmasq option
+`noresolv` to `1` in the same file. This can be achieved by editing the
+`/etc/config/dhcp` file directly or executing the following commands at the
+command line:
+
+ uci add_list dhcp.@dnsmasq[-1].server='127.0.0.1#5453'
+ uci set dhcp.@dnsmasq[-1].noresolv=1
+ uci commit && reload_config
+
+The same outcome can be achieved in the LUCI web interface as follows:
+
+1. Select the Network->DHCP and DNS menu entry.
+2. In the "General Settings" tab, enter the address `127.0.0.1#5453` as the only
+ entry in the "DNS Forwardings" dialogue.
+3. In the "Resolv and Host files" tab tick the "Ignore resolve file" checkbox.
+
+### Disable sending DNS requests to ISP provided DNS servers
+
+The configuration changes in the previous section ensure that DNS queries are
+sent over TLS encrypted connections *once dnsmasq and stubby are started*. When
+the OpenWRT device is first brought up, there is a possibility that DNS queries
+can go to ISP provided DNS servers ahead of dnsmasq and stubby being active. In
+order to mitigate this leakage, it's necessary to ensure that upstream resolvers
+aren't available, and the only DNS resolver used by the system is
+dnsmasq+stubby.
+
+This requires setting the option `peerdns` to `0` and the option `dns` to the
+loopback address for both the `wan` and `wan6` interfaces in the
+`/etc/config/network` file. This can be achieved by editing the
+`/etc/config/network` file directly, or by executing the following commands:
+
+ uci set network.wan.peerdns='0'
+ uci set network.wan.dns='127.0.0.1'
+ uci set network.wan6.peerdns='0'
+ uci set network.wan6.dns='0::1'
+ uci commit && reload_config
+
+The same outcome can also be achieved using the LUCI web interface as follows:
+
+1. Select the Network->Interfaces menu entry.
+2. Click on Edit for the WAN interfaces.
+3. Choose the Advanced Settings tab.
+4. Unselect the "Use DNS servers advertised by peer" checkbox
+5. Enter `127.0.0.1` in the "Use custom DNS servers" dialogue box.
+6. Repeat the above steps for the WAN6 interface, but use the address `0::1`
+ instead of `127.0.0.1`.
+
+### Enabling DNSSEC
+
+The configuration described above ensures that DNS queries are executed over TLS
+encrypted links. However, the responses themselves are not validated; DNSSEC
+provides the ability to validate returned DNS responses, and mitigate against
+DNS poisoning risks.
+
+With the combination of stubby+dnsmasq there are two possible ways to enable
+DNSSEC:
+
+1. Configure stubby to perform DNSSEC validation, and configure dnsmasq to proxy
+ the DNSSEC data to clients.
+2. Configure stubby not to perform DNSSEC validation and configure dnsmasq to
+ require DNSSEC validation.
+
+Either option achieves the same outcome, and there appears to be little reason
+for choosing one over the other other than that the second option is easier to
+configure in the LUCI web interface. Both options are detailed below, and both
+require that the `dnsmasq` package on the OpenWRT device is replaced with the
+`dnsmasq-full` package. That can be achieved by running the following command:
+
+ opkg install dnsmasq-full --download-only && opkg remove dnsmasq && opkg install dnsmasq-full --cache . && rm *.ipk
+
+#### DNSSEC by stubby
+
+Configuring stubby to perform DNSSEC validation requires setting the stubby
+configuration option `dnssec_return_status` to `'1'` in `/etc/config/stubby`,
+which can be done by editing the file directly or by executing the commands:
+
+ uci set stubby.global.dnssec_return_status=1
+ uci commit && reload_config
+
+With stubby performing DNSSEC validation, dnsmasq needs to be configured to
+proxy the DNSSEC data to clients. This requires setting the option `proxydnssec`
+to 1 in the dnsmasq configuration in `/etc/config/dhcp`. That can be achieved by
+the following commands:
+
+ uci set dhcp.@dnsmasq[-1].proxydnssec=1
+ uci commit && reload_config
+
+#### DNSSEC by dnsmasq
+
+Configuring dnsmasq to perform DNSSEC validation requires setting the dnsmasq
+option `dnssec` to `1` in the `/etc/config/dhcp` file. In addition, it is
+advisable to also set the dnsmasq option `dnsseccheckunsigned` to `1`. this can
+be achieved by editing the file `/etc/config/dhcp` or by executing the following
+commands:
+
+ uci set dhcp.@dnsmasq[-1].dnssec=1
+ uci set dhcp.@dnsmasq[-1].dnsseccheckunsigned=1
+ uci commit && reload_config
+
+The same options can be set in the LUCI web interface as follows:
+
+1. Select the "Network->DHCP and DNS" menu entry.
+2. Select the "Advanced Settings" tab.
+3. Ensure both the "DNSSEC" and "DNSSEC check unsigned" check boxes are ticked.
+
+#### Validating DNSSEC operation
+
+Having configured DNSSEC validation using one of the two approaches above, it's
+important to check it's actually working. The following command can be used:
+
+ dig dnssectest.sidn.nl +dnssec +multi @192.168.1.1
+
+This command should return output like the following:
+
+ ; <<>> DiG 9.11.4-P1-RedHat-9.11.4-5.P1.fc28 <<>> dnssectest.sidn.nl +dnssec +multi @192.168.1.1
+ ;; global options: +cmd
+ ;; Got answer:
+ ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26579
+ ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
+
+ ;; OPT PSEUDOSECTION:
+ ; EDNS: version: 0, flags: do; udp: 512
+ ;; QUESTION SECTION:
+ ;dnssectest.sidn.nl. IN A
+
+ ;; ANSWER SECTION:
+ dnssectest.sidn.nl. 14399 IN A 213.136.9.12
+ dnssectest.sidn.nl. 14399 IN RRSIG A 8 3 14400 (
+ 20181104071058 20181005071058 42033 sidn.nl.
+ YAQl3tef36M9EQUOmCneHKCCkxox3csLpfUOql5i/6ND
+ zPrQFsNr3g32HPoxOsi+hD2BE5+bEsnARayDSVLyx0qU
+ 6Hpi2rzQ0zGNZZkCJhCsdp3wnM1BWlMgPrCD0iIsJDok
+ +DH5zu+yYufVUdSLQrMqA3MZDFUIqDUqSZuYDF4= )
+
+ ;; Query time: 77 msec
+ ;; SERVER: 192.168.1.1#53(192.168.1.1)
+ ;; WHEN: Sat Oct 06 20:36:25 BST 2018
+ ;; MSG SIZE rcvd: 230
+
+The key thing to note is the `flags: qr rd ra ad` part - the `ad` flag signifies
+that DNSSEC validation is working. If that flag is absent DNSSEC validation is
+not working.
+
+## Appendix: stubby configuration options
+
+This section details the options available for use in the `/etc/config/stubby`
+file. The `global` configuration section specifies the configuration parameters
+for the stubby daemon. One or more `resolver` sections are used to configure
+upstream resolvers for the stubby daemon to use.
+
+### `global` section options
+
+#### `option manual`
+
+Specify whether to use this file to configure the stubby service. If this is set
+to `'1'` stubby will be configured using the file `/etc/stubby/stubby.yml`. If this
+is set to `'0'`, configuration options will be taken from this file, and the service
+will be managed through UCI.
+
+#### `option trigger`
+
+This specifies an interface to trigger stubby start up on; stubby startup will
+be triggered by a procd signal associated with this interface being ready. If
+this interface is restarted, stubby will also be restarted.
+
+This option can also be set to `'timed'`, in which case a time, specified by the
+option `triggerdelay`, will be waited before starting stubby.
+
+
+#### `option triggerdelay`
+
+If the `trigger` option specifies an interface, this option sets the time that
+is waited after the procd signal is received before starting stubby.
+
+If `trigger` is set to `'timed'` then this is the delay before starting stubby.
+This option is specified in seconds and defaults to the value `'2'`.
+
+#### `list dns_transport`
+
+The `dns_transport` list specifies the allowed transports. Allowed values are:
+`GETDNS_TRANSPORT_UDP`, `GETDNS_TRANSPORT_TCP` and `GETDNS_TRANSPORT_TLS`. The
+transports are tried in the order listed.
+
+#### `option tls_authentication`
+
+This option specifies whether TLS authentication is mandatory. A value of `'1'`
+mandates TLS authentication, and is the default.
+
+If this is set to `'0'`, and `GETDNS_TRANSPORT_TCP` or `GETDNS_TRANSPORT_UDP`
+appears in the `dns_transport` list, stubby is allowed to fall back to non-TLS
+authenticated lookups. You probably don't want this though.
+
+#### `option tls_query_padding_blocksize`
+
+This option specifies the block size to pad DNS queries to. You shouldn't need
+to set this to anything but `'128'` (the default), as recommended by
+https://tools.ietf.org/html/draft-ietf-dprive-padding-policy-03
+
+#### `option tls_connection_retries`
+
+This option specifies the number of connection failures stubby permits before
+Stubby backs-off from using an individual upstream resolver. You shouldn't need
+to change this from the default value of `'2'`.
+
+#### `option tls_backoff_time`
+
+This option specifies the maximum time in seconds Stubby will back-off from
+using an individual upstream after failures. You shouldn't need to change this
+from the default value of `'3600'`.
+
+#### `option timeout`
+
+This option specifies the timeout on getting a response to an individual
+request. This is specified in milliseconds. You shouldn't need to change this
+from the default value of ` '5000'`.
+
+#### `option dnssec_return_status`
+
+This option specifies whether stubby should require DNSSEC validation. Specify
+to `'1'` to turn on validation, and `'0'` to turn it off. By default it is off.
+
+#### `option appdata_dir`
+
+This option specifies the location for storing stubby runtime data. In
+particular, if DNSSEC is turned on, stubby will store its automatically
+retrieved trust anchor data here. The default value is `'/var/lib/stubby'`.
+
+#### `option trust_anchors_backoff_time`
+
+When Zero configuration DNSSEC failed, because of network unavailability or
+failure to write to the appdata directory, stubby will backoff trying to refetch
+the DNSSEC trust-anchor for a specified amount of time expressed in milliseconds
+(which defaults to two and a half seconds).
+
+#### `option dnssec_trust_anchors`
+
+This option sets the location of the file containing the trust anchor data used
+for DNSSEC validation. If this is not specified, stubby will automatically
+retrieve a trust anchor at startup. It's unlikely you'll want to manage the
+trust anchor data manually, so in most cases this is not needed. By default,
+this is unset.
+
+#### `option edns_client_subnet_private`
+
+This option specifies whether to enforce ECS client privacy. The default is
+`'1'`. Set to `'0'` to disable client privacy.
+
+For more details see Section 7.1.2 [here](https://tools.ietf.org/html/rfc7871).
+
+#### `option idle_timeout`
+
+This option specifies the time (in milliseconds) to hold TLS connections open to
+avoid the overhead of opening a new connection for every query. You should not
+normally need to change this from the default value (currently `'10000'`).
+
+See [here](https://tools.ietf.org/html/rfc7828) for more details.
+
+#### `option round_robin_upstreams`
+
+This option specifies how stubby will use the upstream DNS resolvers. Set to
+`'1'` (the default) to instruct stubby to distribute queries across all
+available name servers - this will use multiple simultaneous connections which
+can give better performance in most (but not all) cases. Set to `'0'` to treat
+the upstream resolvers as an ordered list and use a single upstream resolver
+until it becomes unavailable, then use the next one.
+
+#### `list listen_address`
+
+This list sets the addresses and ports for the stubby daemon to listen for
+requests on. the default configuration configures stubby to listen on port 5453
+on the loopback interface for both IPv4 and IPv6.
+
+#### `option log_level`
+
+If set, this option specifies the level of logging from the stubby
+daemon. By default, this option is not set.
+
+The possible levels are:
+
+ '0': EMERG - System is unusable
+ '1': ALERT - Action must be taken immediately
+ '2': CRIT - Critical conditions
+ '3': ERROR - Error conditions
+ '4': WARN - Warning conditions
+ '5': NOTICE - Normal, but significant, condition
+ '6': INFO - Informational message
+ '7': DEBUG - Debug-level message
+
+#### `option command_line_arguments`
+
+This option specifies additional command line arguments for
+stubby daemon. By default, this is an empty string.
+
+#### `option tls_cipher_list`
+
+If set, this specifies the acceptable ciphers for DNS over TLS. With OpenSSL
+1.1.1 this list is for TLS1.2 and older only. Ciphers for TLS1.3 should be set
+with the `tls_ciphersuites` option. This option can also be given per upstream
+resolver. By default, this option is not set.
+
+#### `option tls_ciphersuites`
+
+If set, this specifies the acceptable cipher for DNS over TLS1.3. OpenSSL
+version 1.1.1 or greater is required for this option. This option can also be
+given per upstream resolver. By default, this option is not set.
+
+#### `option tls_min_version`
+
+If set, this specifies the minimum acceptable TLS version. Works with OpenSSL
+1.1.1 or greater only. This option can also be given per upstream resolver. By
+default, this option is not set.
+
+#### `option tls_max_version`
+
+If set, this specifies the maximum acceptable TLS version. Works with OpenSSL
+1.1.1 or greater only. This option can also be given per upstream resolver. By
+default, this option is not set.
+
+
+### `resolver` section options
+
+#### `option address`
+
+This option specifies the resolver IP address, and can either be an IPv4 or an
+IPv6 address.
+
+#### `option tls_auth_name`
+
+This option specifies the upstream domain name used for TLS authentication with
+the supplied server certificate
+
+#### `option tls_port`
+
+This option specifies the TLS port for the upstream resolver. If not specified,
+this defaults to 853.
+
+#### `option tls_cipher_list`
+
+If set, this specifies the acceptable ciphers for DNS over TLS. With OpenSSL
+1.1.1 this list is for TLS1.2 and older only. Ciphers for TLS1.3 should be set
+with the `tls_ciphersuites` option. By default, this option is not set. If set,
+this overrides the global value.
+
+#### `option tls_ciphersuites`
+
+If set, this specifies the acceptable cipher for DNS over TLS1.3. OpenSSL
+version 1.1.1 or greater is required for this option. By default, this option is
+not set. If set, this overrides the global value.
+
+#### `option tls_min_version`
+
+If set, this specifies the minimum acceptable TLS version. Works with OpenSSL
+1.1.1 or greater only. By default, this option is not set. If set, this
+overrides the global value.
+
+#### `option tls_max_version`
+
+If set, this specifies the maximum acceptable TLS version. Works with OpenSSL
+1.1.1 or greater only. By default, this options is not set. If set, this
+overrides the global value.
+
+#### `list spki`
+
+This list specifies the SPKI pinset which is verified against the keys in the
+server cerrtificate. The value takes the form `'<digest type>/value>'`, where
+the `digest type` is the hashing algorithm used, and the value is the Base64
+encoded hash of the public key. At present, only `sha256` is
+supported for the digest type.
+
+This should ONLY be used if the upstream resolver has committed to maintaining
+the pinset. CloudFlare have made no such commitment, and so we do not specify
+the SPKI values in the default configuration, even though they are available.
--- /dev/null
+config stubby 'global'
+ option manual '0'
+ option trigger 'wan'
+ # option triggerdelay '2'
+ list dns_transport 'GETDNS_TRANSPORT_TLS'
+ option tls_authentication '1'
+ option tls_query_padding_blocksize '128'
+ # option tls_connection_retries '2'
+ # option tls_backoff_time '3600'
+ # option timeout '5000'
+ # option dnssec_return_status '0'
+ option appdata_dir '/var/lib/stubby'
+ # option trust_anchors_backoff_time 2500
+ # option dnssec_trust_anchors '/var/lib/stubby/getdns-root.key'
+ option edns_client_subnet_private '1'
+ option idle_timeout '10000'
+ option round_robin_upstreams '1'
+ list listen_address '127.0.0.1@5453'
+ list listen_address '0::1@5453'
+ # option log_level '7'
+ # option command_line_arguments ''
+ # option tls_cipher_list 'EECDH+AESGCM:EECDH+CHACHA20'
+ # option tls_ciphersuites 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256'
+ # option tls_min_version '1.2'
+ # option tls_max_version '1.3'
+
+# Upstream resolvers are specified using 'resolver' sections.
+config resolver
+ option address '2606:4700:4700::1111'
+ option tls_auth_name 'cloudflare-dns.com'
+ # option tls_port 853
+ # list spki 'sha256/yioEpqeR4WtDwE9YxNVnCEkTxIjx6EEIwFSQW+lJsbc='
+ # option tls_cipher_list 'EECDH+AESGCM:EECDH+CHACHA20'
+ # option tls_ciphersuites 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256'
+ # option tls_min_version '1.2'
+ # option tls_max_version '1.3'
+
+config resolver
+ option address '2606:4700:4700::1001'
+ option tls_auth_name 'cloudflare-dns.com'
+ # option tls_port 853
+ # list spki 'sha256/yioEpqeR4WtDwE9YxNVnCEkTxIjx6EEIwFSQW+lJsbc='
+ # option tls_cipher_list 'EECDH+AESGCM:EECDH+CHACHA20'
+ # option tls_ciphersuites 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256'
+ # option tls_min_version '1.2'
+ # option tls_max_version '1.3'
+
+config resolver
+ option address '1.1.1.1'
+ option tls_auth_name 'cloudflare-dns.com'
+ # option tls_port 853
+ # list spki 'sha256/yioEpqeR4WtDwE9YxNVnCEkTxIjx6EEIwFSQW+lJsbc='
+ # option tls_cipher_list 'EECDH+AESGCM:EECDH+CHACHA20'
+ # option tls_ciphersuites 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256'
+ # option tls_min_version '1.2'
+ # option tls_max_version '1.3'
+
+config resolver
+ option address '1.0.0.1'
+ option tls_auth_name 'cloudflare-dns.com'
+ # option tls_port 853
+ # list spki 'sha256/yioEpqeR4WtDwE9YxNVnCEkTxIjx6EEIwFSQW+lJsbc='
+ # option tls_cipher_list 'EECDH+AESGCM:EECDH+CHACHA20'
+ # option tls_ciphersuites 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256'
+ # option tls_min_version '1.2'
+ # option tls_max_version '1.3'
--- /dev/null
+#!/bin/sh /etc/rc.common
+
+USE_PROCD=1
+
+START=30
+STOP=51
+
+stubby="/usr/sbin/stubby"
+stubby_init="/etc/init.d/stubby"
+stubby_config_dir="/var/etc/stubby"
+stubby_config="$stubby_config_dir/stubby.yml"
+stubby_pid_file="/var/run/stubby.pid"
+stubby_manual_config="/etc/stubby/stubby.yml"
+
+boot()
+{
+ stubby_boot=1
+ rc_procd start_service
+}
+
+generate_config()
+{
+ local config_file="$1"
+ local round_robin
+ local tls_authentication
+ local tls_query_padding_blocksize
+ local edns_client_subnet_private
+ local idle_timeout
+ local appdata_dir
+ local trust_anchors_backoff_time
+ local tls_connection_retries
+ local tls_backoff_time
+ local timeout
+ local dnssec_return_status
+ local dnssec_trust_anchors
+ local listen_addresses_section=0
+ local dns_transport_list_section=0
+ local upstream_recursive_servers_section=0
+ local command_line_arguments
+ local log_level
+ local tls_cipher_list
+ local tls_ciphersuites
+ local tls_min_version
+ local tls_max_version
+
+ # Generate configuration. See: https://github.com/getdnsapi/stubby/blob/develop/stubby.yml.example
+ echo "# Autogenerated configuration from uci data" > "$config_file"
+ echo "resolution_type: GETDNS_RESOLUTION_STUB" >> "$config_file"
+
+ config_get round_robin "global" round_robin_upstreams "1"
+ echo "round_robin_upstreams: $round_robin" >> "$config_file"
+
+ config_get appdata_dir "global" appdata_dir "/var/lib/stubby"
+ echo "appdata_dir: \"$appdata_dir\"" >> "$config_file"
+
+ config_get trust_anchors_backoff_time "global" trust_anchors_backoff_time "2500"
+ echo "trust_anchors_backoff_time: $trust_anchors_backoff_time" >> "$config_file"
+
+ config_get tls_connection_retries "global" tls_connection_retries ""
+ if [ -n "$tls_connection_retries" ]; then
+ echo "tls_connection_retries: $tls_connection_retries" >> "$config_file"
+ fi
+
+ config_get tls_backoff_time "global" tls_backoff_time ""
+ if [ -n "$tls_backoff_time" ]; then
+ echo "tls_backoff_time: $tls_backoff_time" >> "$config_file"
+ fi
+
+ config_get timeout "global" timeout ""
+ if [ -n "$timeout" ]; then
+ echo "timeout: $timeout" >> "$config_file"
+ fi
+
+ config_get_bool tls_authentication "global" tls_authentication "1"
+ if [ "$tls_authentication" = "1" ]; then
+ echo "tls_authentication: GETDNS_AUTHENTICATION_REQUIRED" >> "$config_file"
+ else
+ echo "tls_authentication: GETDNS_AUTHENTICATION_NONE" >> "$config_file"
+ fi
+
+ config_get_bool dnssec_return_status "global" dnssec_return_status "0"
+ if [ "$dnssec_return_status" = "1" ]; then
+ echo "dnssec_return_status: GETDNS_EXTENSION_TRUE" >> "$config_file"
+ fi
+
+ config_get dnssec_trust_anchors "global" dnssec_trust_anchors ""
+ if [ -n "$dnssec_trust_anchors" ]; then
+ echo "dnssec_trust_anchors: \"$dnssec_trust_anchors\"" >> "$config_file"
+ fi
+
+ config_get tls_query_padding_blocksize "global" tls_query_padding_blocksize "128"
+ echo "tls_query_padding_blocksize: $tls_query_padding_blocksize" >> "$config_file"
+
+ config_get_bool edns_client_subnet_private "global" edns_client_subnet_private "1"
+ echo "edns_client_subnet_private: $edns_client_subnet_private" >> "$config_file"
+
+ config_get idle_timeout "global" idle_timeout "10000"
+ echo "idle_timeout: $idle_timeout" >> "$config_file"
+
+ config_get tls_cipher_list "global" tls_cipher_list ""
+ if [ -n "$tls_cipher_list" ]; then
+ echo "tls_cipher_list: \"$tls_cipher_list\"" >> "$config_file"
+ fi
+
+ config_get tls_ciphersuites "global" tls_ciphersuites ""
+ if [ -n "$tls_ciphersuites" ]; then
+ echo "tls_ciphersuites: \"$tls_ciphersuites\"" >> "$config_file"
+ fi
+
+ config_get tls_min_version "global" tls_min_version ""
+ if [ -n "$tls_min_version" ]; then
+ echo "tls_min_version: GETDNS_TLS${tls_min_version/\./_}" >> "$config_file"
+ fi
+
+ config_get tls_max_version "global" tls_max_version ""
+ if [ -n "$tls_max_version" ]; then
+ echo "tls_max_version: GETDNS_TLS${tls_max_version/\./_}" >> "$config_file"
+ fi
+
+ handle_listen_address_value()
+ {
+ local value="$1"
+
+ if [ "$listen_addresses_section" = 0 ]; then
+ echo "listen_addresses:" >> "$config_file"
+ listen_addresses_section=1
+ fi
+ echo " - $value" >> "$config_file"
+ }
+ config_list_foreach "global" listen_address handle_listen_address_value
+
+ handle_dns_transport_list_value()
+ {
+ local value="$1"
+
+ if [ "$dns_transport_list_section" = 0 ]; then
+ echo "dns_transport_list:" >> "$config_file"
+ dns_transport_list_section=1
+ fi
+ echo " - $value" >> "$config_file"
+ }
+ config_list_foreach "global" dns_transport handle_dns_transport_list_value
+
+ handle_resolver()
+ {
+ local config=$1
+ local address
+ local tls_auth_name
+ local tls_port
+ local tls_pubkey_pinset_section=0
+ local tls_cipher_list
+ local tls_ciphersuites
+ local tls_min_version
+ local tls_max_version
+
+ if [ "$upstream_recursive_servers_section" = 0 ]; then
+ echo "upstream_recursive_servers:" >> "$config_file"
+ upstream_recursive_servers_section=1
+ fi
+ config_get address "$config" address
+ echo " - address_data: $address" >> "$config_file"
+
+ config_get tls_auth_name "$config" tls_auth_name
+ echo " tls_auth_name: \"$tls_auth_name\"" >> "$config_file"
+
+ config_get tls_auth_port "$config" tls_port ""
+ if [ -n "$tls_port" ]; then
+ echo " tls_port: $tls_port" >> "$config_file"
+ fi
+
+ config_get tls_cipher_list "$config" tls_cipher_list ""
+ if [ -n "$tls_cipher_list" ]; then
+ echo " tls_cipher_list: \"$tls_cipher_list\"" >> "$config_file"
+ fi
+
+ config_get tls_ciphersuites "$config" tls_ciphersuites ""
+ if [ -n "$tls_ciphersuites" ]; then
+ echo " tls_ciphersuites: \"$tls_ciphersuites\"" >> "$config_file"
+ fi
+
+ config_get tls_min_version "$config" tls_min_version ""
+ if [ -n "$tls_min_version" ]; then
+ echo " tls_min_version: GETDNS_TLS${tls_min_version/\./_}" >> "$config_file"
+ fi
+
+ config_get tls_max_version "$config" tls_max_version ""
+ if [ -n "$tls_max_version" ]; then
+ echo " tls_max_version: GETDNS_TLS${tls_max_version/\./_}" >> "$config_file"
+ fi
+
+ handle_resolver_spki()
+ {
+ local val="$1"
+ local digest="${val%%/*}"
+ local value="${val#*/}"
+
+ if [ "$tls_pubkey_pinset_section" = 0 ]; then
+ echo " tls_pubkey_pinset:" >> "$config_file"
+ tls_pubkey_pinset_section=1
+ fi
+ echo " - digest: \"$digest\"" >> "$config_file"
+ echo " value: $value" >> "$config_file"
+ }
+ config_list_foreach "$config" spki handle_resolver_spki
+ }
+
+ config_foreach handle_resolver resolver
+}
+
+start_service() {
+ local config_file_tmp
+ local manual
+ local log_level
+ local command_line_arguments
+
+ mkdir -p "$stubby_config_dir"
+
+ config_load "stubby"
+
+ config_get_bool manual "global" manual "0"
+
+ if [ "$manual" = "1" ]; then
+ cp "$stubby_manual_config" "$stubby_config"
+ else
+ config_file_tmp="$stubby_config.$$"
+ generate_config "$config_file_tmp"
+ mv "$config_file_tmp" "$stubby_config"
+ fi
+
+ config_get command_line_arguments "global" command_line_arguments ""
+
+ config_get log_level "global" log_level ""
+
+ if [ "$("$stubby_init" enabled; printf "%u" $?)" -eq 0 ]; then
+ if [ -n "$stubby_boot" ]; then
+ local trigger
+ trigger="$(uci_get stubby global trigger)"
+ if [ "$trigger" != "timed" ]; then
+ return 0
+ fi
+ fi
+ procd_open_instance "stubby"
+ procd_set_param command "$stubby" -C "$stubby_config"
+ if [ -n "$log_level" ]; then
+ procd_append_param command -v "$log_level"
+ fi
+ if [ -n "$command_line_arguments" ]; then
+ procd_append_param command "$command_line_arguments"
+ fi
+ procd_set_param respawn
+ procd_set_param file "$stubby_config"
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_set_param pidfile "$stubby_pid_file"
+ procd_set_param user stubby
+ procd_close_instance
+ fi
+}
+
+service_triggers()
+{
+ local trigger
+ local delay
+
+ trigger="$(uci_get stubby global trigger)"
+ delay="$(uci_get stubby global triggerdelay "2")"
+
+ if [ "$trigger" != "none" ] && [ "$trigger" != "timed" ]; then
+ PROCD_RELOAD_DELAY=$((${delay:-2} * 1000))
+ procd_add_interface_trigger "interface.*.up" "$trigger" "$stubby_init" start
+ fi
+ procd_add_reload_trigger "stubby"
+}
--- /dev/null
+# Note: by default on OpenWRT stubby configuration is handled via
+# the UCI system and the file /etc/config/stubby. If you want to
+# use this file to configure stubby, then set "option manual '1'"
+# in /etc/config/stubby.
+resolution_type: GETDNS_RESOLUTION_STUB
+round_robin_upstreams: 1
+appdata_dir: "/var/lib/stubby"
+tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
+tls_query_padding_blocksize: 128
+edns_client_subnet_private: 1
+idle_timeout: 10000
+listen_addresses:
+ - 127.0.0.1@5453
+ - 0::1@5453
+dns_transport_list:
+ - GETDNS_TRANSPORT_TLS
+upstream_recursive_servers:
+ - address_data: 2606:4700:4700::1111
+ tls_auth_name: "cloudflare-dns.com"
+ - address_data: 2606:4700:4700::1001
+ tls_auth_name: "cloudflare-dns.com"
+ - address_data: 1.1.1.1
+ tls_auth_name: "cloudflare-dns.com"
+ - address_data: 1.0.0.1
+ tls_auth_name: "cloudflare-dns.com"