This is a fairly effective solution for securing your network from ads, malware, porn, trackers, etc. It will not secure your network absolutely. I used to advise people who wanted total control over their network to use a whitelist instead, but with the advent of DNS over HTTPS (DoH) it became much more difficult. Basically, anyone who knows how to enable this feature in their browser can bypass the DNS servers advertised by DHCP. This is great for user privacy, but many parents will have mixed feelings.
If anyone knows of a good way to restrict DoH to a specific DNS server, please please get in touch.
Do each of these steps on your firewall/DNS server.
These firewall rules will prevent clients on the network from bypassing the DNS server:
iptables -t nat -I PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53
iptables -t nat -I PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53
Restart the firewall.
Run get-blacklist.sh
to download the blacklist, then add this to the dnsmasq
configuration file (typically at /etc/dnsmasq.conf
):
addn-hosts=/path/to/blacklist.hosts
Restart dnsmasq.
This cron job will run get-blacklist.sh
once per month, but will only
download a new blacklist if it has changed:
0 0 1 * * /path/to/get-blacklist.sh
You can configure OpenDNS to block just about anything. I prefer to leave it purely as a safety net, blocking only what slips through the blacklist.
DNS-O-Matic provides an API to notify OpenDNS when your public IP address changes, which it needs to apply your filtering preferences. Add OpenDNS as a service to DNS-O-Matic.
Add this to the dnsmasq configuration file (typically at /etc/dnsmasq.conf
)
to use the OpenDNS nameservers:
all-servers
no-resolv
server=208.67.222.222
server=208.67.220.220
Restart dnsmasq.
Create a file named config.txt
in the same directory as update-ddns.sh
.
This file must contain your username and password for DNS-O-Matic and must be
formatted as follows:
ddns_user=username
ddns_pass=password
This cron job will run update-ddns.sh
every ten minutes, but will only send
an update to DNS-O-Matic if your public IP address has changed:
*/10 * * * * /path/to/update-ddns.sh
Configuration settings are read from a file named config.txt
. It must live
in the same directory as the script that uses it. All settings must follow the
syntax key=value
with or without spaces around the =
and without quotes
around the value
.
blacklist_add_host
: Specify an additional domain to block. Can occur more than once.blacklist_remove_host
: Unblock a domain. Can occur more than once.blacklist_upload_dest
: The destination to upload the blacklist, formatted as user@host:file. This is useful in case you want to runget-blacklist.sh
from any host other than your firewall/DNS server. If set, dnsmasq will be restarted automatically after the file is uploaded.
ddns_user
: The username for DNS-O-Matic. This setting is required.ddns_pass
: The password for DNS-O-Matic. This setting is required.ddns_ip_src
: The URL from which to obtain your public IP address. If unset, it will default to http://myip.dnsomatic.com.ddns_ca_dir
: The SSL certificate directory. If unset, it will default to /etc/ssl/certs.
In order for this script to run on OpenWrt, you must install ca-certificates and curl:
$ opkg install ca-certificates curl
In addition, you must enable cron:
$ /etc/init.d/cron start
$ /etc/init.d/cron enable
You can get your public IP address without hitting an external URL. Create
a shell script at /www/cgi-bin/ip
with something like the following:
#!/usr/bin/env sh
echo -e 'Content-Type: text/plain\n'
ip -4 addr show eth1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1
Make the script executable:
$ chmod +x /www/cgi-bin/ip
Then add this to config.txt
:
ddns_ip_src=http://127.0.0.1/cgi-bin/ip
I didn't have this option when I wrote this guide, but these days it's probably more practical for most people to use the AdGuard Family Protection nameservers. It's not as configurable as OpenDNS, but it only requires step 3 from part 2 above. Just replace the last two lines of the dnsmasq configuration file with AdGuard's nameservers:
all-servers
no-resolv
server=176.103.130.132
server=176.103.130.134
Of course, many other alternatives exist as well, but I'll leave the research to you.
Much love goes to the OpenWRT community, particularly those who contributed to this thread, and to the folks at Unix & Linux SE, SecureMecca.com and MVPS.org.