Embedding DNSCrypt2 into a custom build

To all custom firmware builders, here is a recipe to automatically bundle the latest DNSCrypt into your build if you wish to do so. A mandatory disclaimer:

  • I have only tested it with the image builder, but building from sources also allows for adding custom files.
  • The script below is for ARM 32 bit (Netgear R7800 in my case), so if you are building for a different platform the script can be adapted by searching for arm and replacing it with your architecture.
  • The approach is based on this.
  • This setup is working with adblock just fine.
  1. Run the following script (it is Linux based and might need to be adapted to another OS) to prepare the DNSCrypt bundle
Prepare DNSCrypt
mkdir files files/usr files/usr/sbin files/etc files/etc/config files/etc/init.d

DNSCRYPT_VERSION=`curl -s https://github.com/jedisct1/dnscrypt-proxy/releases/latest | awk -v FS="(/dnscrypt-proxy/releases/tag/|\">redirected)" '{print $2}'`
wget https://github.com/jedisct1/dnscrypt-proxy/releases/download/${DNSCRYPT_VERSION}/dnscrypt-proxy-linux_arm-${DNSCRYPT_VERSION}.tar.gz
tar zxvf dnscrypt-proxy-linux_arm-${DNSCRYPT_VERSION}.tar.gz

cp linux-arm/dnscrypt-proxy files/usr/sbin
chmod +x files/usr/sbin/dnscrypt-proxy

cp linux-arm/example-dnscrypt-proxy.toml files/etc/config/dnscrypt-proxy.toml
sed -i "s/^listen_addresses = .*/listen_addresses = ['127.0.0.77:5300']/" files/etc/config/dnscrypt-proxy.toml
sed -i "s/.*#.*blacklist_file = 'blacklist.txt'$/  blacklist_file = '\/etc\/config\/dnscrypt-blacklist.txt'/" files/etc/config/dnscrypt-proxy.toml
sed -i "s/^#.*server_names =.*/server_names = ['quad9-dnscrypt-ip4-filter-pri', 'quad9-dnscrypt-ip4-filter-alt']/" files/etc/config/dnscrypt-proxy.toml
sed -i "s/^block_ipv6.*/block_ipv6 = true/" files/etc/config/dnscrypt-proxy.toml 
sed -i "s/^#.*use_syslog.*/use_syslog = true/" files/etc/config/dnscrypt-proxy.toml 

cat << 'EOF' > files/etc/config/dnscrypt-blacklist.txt
*.home
*.test
*.onion
*.localhost
*.local
*.invalid
*.bind
*.lan
*.internal
*.intranet
*.private
*.workgroup
*.10.in-addr.arpa
*.16.172.in-addr.arpa
*.168.192.in-addr.arpa
*.254.169.in-addr.arpa
*.d.f.ip6.arpa
EOF

cat << 'EOF' > files/usr/sbin/dnscrypt-proxy-one-time-setup.sh
uci set dhcp.@dnsmasq[0].noresolv='1'
uci set dhcp.@dnsmasq[0].localuse='1'
uci add_list dhcp.@dnsmasq[0].server='127.0.0.77#5300'
uci add_list dhcp.@dnsmasq[0].server='/home/'
uci add_list dhcp.@dnsmasq[0].server='/test/'
uci add_list dhcp.@dnsmasq[0].server='/onion/'
uci add_list dhcp.@dnsmasq[0].server='/localhost/'
uci add_list dhcp.@dnsmasq[0].server='/local/'
uci add_list dhcp.@dnsmasq[0].server='/invalid/'
uci add_list dhcp.@dnsmasq[0].server='/bind/'
uci add_list dhcp.@dnsmasq[0].server='/lan/'
uci add_list dhcp.@dnsmasq[0].server='/internal/'
uci add_list dhcp.@dnsmasq[0].server='/intranet/'
uci add_list dhcp.@dnsmasq[0].server='/private/'
uci add_list dhcp.@dnsmasq[0].server='/workgroup/'
uci add_list dhcp.@dnsmasq[0].server='/10.in-addr.arpa/'
uci add_list dhcp.@dnsmasq[0].server='/16.172.in-addr.arpa/'
uci add_list dhcp.@dnsmasq[0].server='/168.192.in-addr.arpa/'
uci add_list dhcp.@dnsmasq[0].server='/254.169.in-addr.arpa/'
uci add_list dhcp.@dnsmasq[0].server='/d.f.ip6.arpa/'
uci commit dhcp
EOF
chmod +x files/usr/sbin/dnscrypt-proxy-one-time-setup.sh

wget https://raw.githubusercontent.com/etam/DNS-over-HTTPS-for-OpenWRT/master/dnscrypt-proxy -O files/etc/init.d/dnscrypt-proxy
chmod +x files/etc/init.d/dnscrypt-proxy
  1. It will generate the following files:
DNSCrypt files
-rwxr-xr-x   files/usr/sbin/dnscrypt-proxy
-rwxr-xr-x   files/usr/sbin/dnscrypt-proxy-one-time-setup.sh
-rw-r--r--   files/etc/config/dnscrypt-blacklist.txt
-rw-r--r--   files/etc/config/dnscrypt-proxy.toml
-rwxr-xr-x   files/etc/init.d/dnscrypt-proxy
  1. Package those files into the build: the image size grows by ~3.5MB. The instructions for image builder.
  2. Deploy the firmware.
  3. Once the router comes back up, execute dnscrypt-proxy-one-time-setup.sh (only once as the name suggest). There is no output if all is good. There is no need to run this script ever again.
  4. Reboot again (or restart dnsmaq) and dnscrypt-proxy should be working.
  5. Run dnscrypt-proxy -resolve google.com on the router to test the setup and make sure that Resolver IP is not your original DNS IP.
  6. Additional info. The most important step I think is to add firewall rule(s) to force all you clients use the router for DNS.