paulgorman.org/technical

Privacy with dnsmasq and dnscrypt-proxy

(June 2019)

Let’s make it harder for our unscrupulous ISP (Comcast) and internet advertisers to spy on us.

Install dnscrypt-proxy.

$  sudo apt-get install dnscrypt-proxy

Edit /etc/systemd/system/sockets.target.wants/dnscrypt-proxy.socket:

[Unit]
Description=dnscrypt-proxy listening socket
Documentation=https://github.com/jedisct1/dnscrypt-proxy/wiki
Before=nss-lookup.target
Wants=nss-lookup.target
Wants=dnscrypt-proxy-resolvconf.service

[Socket]
ListenStream=127.0.0.1:53443
ListenDatagram=127.0.0.1:53443
NoDelay=true
DeferAcceptSec=1

[Install]
WantedBy=sockets.target

Then:

$  sudo systemctl daemon-reload
$  sudo systemctl restart dnscrypt-proxy.socket
$  sudo lsof -i | grep dnscrypt
dnscrypt- 3355 _dnscrypt-proxy    3u  IPv4  48981      0t0  UDP 127.0.2.1:53443
dnscrypt- 3355 _dnscrypt-proxy    5u  IPv4  48979      0t0  TCP 127.0.2.1:53443 (LISTEN)

By default, dnscrypt-proxy defaults to using the Cloudflare servers (1.1.1.1). Verify its config in /etc/dnscrypt-proxy/dnscrypt-proxy.toml.

$  sudo apt-get install dnsmasq

Edit /etc/dnsmasq.conf (remember to set the correct interface name for your system):

interface=br0
no-dhcp-interface=br0
server=127.0.0.1#53443
addn-hosts=/etc/dns-bl

cache-size=10000
no-resolv
domain-needed
bogus-priv
local-ttl=2
dhcp-name-match=set:wpad-ignore,wpad
dhcp-ignore-names=tag:wpad-ignore

Check the syntax of the dnsmasq configuration:

$  /usr/sbin/dnsmasq --test 
dnsmasq: syntax check OK.

The addn-hosts= directive effectively specifies another /etc/hosts. This has some limitations, notably that it can’t set wildcard records for all subdomains in a domain. The address directive does affect subdomain, so we could do somthing like:

address=/example.com/127.0.0.1
address=/example.net/127.0.0.1
conf-file=/etc/dnsmasq.more.conf

Make a script to create our blacklist/blocklist, like:

#!/usr/bin/env bash
set -euf

# This script aggregates blacklists/blocklists into an /etc/hosts formatted
# file suitable for use with dnsmasq.
# Paul Gorman, June 2019

bl=/etc/dns-bl
wl=/etc/dns-wl
d=/tmp/dnsbl/
mkdir -p "$d"
cd "$d"

touch "$d"01 "$d"02 "$d"03 "$d"04 "$d"05 "$d"06 "$d"07 "$d"08 "$d"09 "$d"10 "$d"11 "$d"12 \
	"$d"51 "$d"52 "$d"53 "$d"54 "$d"55 "$d"56 "$d"57 "$d"58 "$d"59 "$d"60 \
	"$d"61 "$d"62 "$d"63 "$d"64 "$d"65 "$d"66 "$d"67 "$d"68 "$d"69

# These lists come in hosts file format:
curl --silent --show-error --output "$d"01 https://hosts-file.net/emd.txt
curl --silent --show-error --output "$d"02 https://hosts-file.net/exp.txt
curl --silent --show-error --output "$d"03 https://hosts-file.net/grm.txt
curl --silent --show-error --output "$d"04 https://hosts-file.net/psh.txt
curl --silent --show-error --output "$d"05 https://hosts-file.net/ad_servers.txt
curl --silent --show-error --output "$d"06 http://sysctl.org/cameleon/hosts
curl --silent --show-error --output "$d"07 https://raw.githubusercontent.com/StevenBlack/hosts/master/data/add.2o7Net/hosts
curl --silent --show-error --output "$d"08 https://raw.githubusercontent.com/StevenBlack/hosts/master/data/add.Risk/hosts
curl --silent --show-error --output "$d"09 https://raw.githubusercontent.com/StevenBlack/hosts/master/data/add.Spam/hosts
curl --silent --show-error --output "$d"10 https://raw.githubusercontent.com/StevenBlack/hosts/master/data/KADhosts/hosts
curl --silent --show-error --output "$d"11 https://raw.githubusercontent.com/StevenBlack/hosts/master/data/UncheckyAds/hosts
curl --silent --show-error --output "$d"12 https://raw.githubusercontent.com/vokins/yhosts/master/hosts

cat "$d"01 "$d"02 "$d"03 "$d"04 "$d"05 "$d"06 "$d"07 "$d"08 "$d"09 "$d"10 "$d"11 "$d"12 \
	| sed 's/^\.//' | sed '/^\s*$/d' | sed '/^#.*/d' | awk '{ print $NF }' \
	> "$d"tmp01

# These lists come as just a list of hostnames/domains:
curl --silent --show-error --output "$d"51 https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt
curl --silent --show-error --output "$d"52 https://s3.amazonaws.com/lists.disconnect.me/simple_malvertising.txt
curl --silent --show-error --output "$d"53 https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt
curl --silent --show-error --output "$d"54 https://v.firebog.net/hosts/AdguardDNS.txt
curl --silent --show-error --output "$d"55 https://v.firebog.net/hosts/Airelle-trc.txt
curl --silent --show-error --output "$d"56 https://v.firebog.net/hosts/Airelle-hrsk.txt
curl --silent --show-error --output "$d"57 https://v.firebog.net/hosts/BillStearns.txt
curl --silent --show-error --output "$d"58 https://v.firebog.net/hosts/Easylist.txt
curl --silent --show-error --output "$d"59 https://v.firebog.net/hosts/Easyprivacy.txt
curl --silent --show-error --output "$d"60 https://v.firebog.net/hosts/Kowabit.txt
curl --silent --show-error --output "$d"61 https://v.firebog.net/hosts/Prigent-Ads.txt
curl --silent --show-error --output "$d"62 https://v.firebog.net/hosts/Prigent-Malware.txt
curl --silent --show-error --output "$d"63 https://v.firebog.net/hosts/Prigent-Phishing.txt
curl --silent --show-error --output "$d"64 https://v.firebog.net/hosts/Shalla-mal.txt
curl --silent --show-error --output "$d"65 https://v.firebog.net/hosts/static/w3kbl.txt
curl --silent --show-error --output "$d"66 https://www.dshield.org/feeds/suspiciousdomains_High.txt
curl --silent --show-error --output "$d"67 https://www.dshield.org/feeds/suspiciousdomains_Medium.txt
curl --silent --show-error --output "$d"68 https://www.squidblacklist.org/downloads/dg-ads.acl
curl --silent --show-error --output "$d"69 https://www.squidblacklist.org/downloads/dg-malicious.acl

cat "$d"51 "$d"52 "$d"53 "$d"54 "$d"55 "$d"56 "$d"57 "$d"58 "$d"59 "$d"60 \
	"$d"61 "$d"62 "$d"63 "$d"64 "$d"65 "$d"66 "$d"67 "$d"68 "$d"69 \
	| sed 's/^\.//' | sed '/^\s*$/d' | sed '/^#.*/d' \
	> "$d"tmp02

cat "$d"tmp01 "$d"tmp02 | sort | uniq \
	| comm -2 -3 - "$wl" \
	| awk '{ print "127.0.0.1 " $1 }' \
	> "$d"dns-bl

chown root:root "$d"dns-bl
chmod 644 "$d"dns-bl
mv "$d"dns-bl "$bl"

systemctl reload dnsmasq.service

Our whitelist lives at /etc/dns-wl. We should alphabetically sort this file, or comm will complain.

$  cat /etc/dns-wl
ask.metafilter.com
deviantart.com
docs.google.com
drive.google.com
gofundme.com
googleusercontent.com
hosts-file.net
imgur.com
pastebin.com
proboards.com
raw.githubusercontent.com
s3.amazonaws.com
staticflickr.com
v.firebog.net
www.squidblacklist.org

Schedule the above blocklist update script to run as a cron job, perhaps weekly.

$  sudo crontab -e
@weekly              /home/paul/bin/update-dns-bl

Make sure dnsmasq runs instead of systemd-resolvd:

$  sudo systemctl stop systemd-resolved.service
$  sudo systemctl disable systemd-resolved.service
$  sudo systemctl start dnsmasq
$  sudo systemctl enable dnsmasq

Is it working?

$  dig +short google.com @127.0.0.1
172.217.4.46
$  sudo lsof -i | grep -e domain -e dns
avahi-dae  583           avahi   12u  IPv4  21837      0t0  UDP *:mdns 
avahi-dae  583           avahi   13u  IPv6  21838      0t0  UDP *:mdns 
dnscrypt- 3499 _dnscrypt-proxy    3u  IPv4  53607      0t0  UDP localhost:53443 
dnscrypt- 3499 _dnscrypt-proxy    5u  IPv4  53036      0t0  TCP localhost:53443 (LISTEN)
dnsmasq   5660         dnsmasq    4u  IPv4 131089      0t0  UDP *:domain 
dnsmasq   5660         dnsmasq    5u  IPv4 131090      0t0  TCP *:domain (LISTEN)
dnsmasq   5660         dnsmasq    6u  IPv6 131091      0t0  UDP *:domain 
dnsmasq   5660         dnsmasq    7u  IPv6 131092      0t0  TCP *:domain (LISTEN)