Setting up multiple instances of dnscrypt-proxy with dnscrypt-proxy-multi
DNSCrypt has become the most ideal solution for having secure DNS resolving sessions. The protocol has not been submitted to IETF, but a lot of people has already started using it, and multiple client and server implementations already exist.
DNSCrypt is simply a protocol that allows authentication and encryption between two parties - the service which most of the time is the resolver, and the client which requests for domain names to be resolved. Rather than creating a local server of named
or unbound
that recursively resolves domain names in the open, it would be more practical to just rely on another public service that supports DNSCrypt, since traffic with a normal DNS protocol is open to eavesdropping (from unwanted parties like your ISP), and forgery. Note that even DNSSec is not encrypted, and that not all domain names support DNSSec. You also have to consider the latency when a local DNS server resolves things manually. You might also consider connecting through Tor, but Tor generally does not support UDP, and falling back to TCP may not always be allowed by DNS servers. The latency even becomes worse with Tor.
So DNSCrypt is indeed the most practical solution, but relying on free public services won’t guarantee uptime and reliability. Some services become inaccessible or unresponsive from time to time. Some also become unable to resolve domain names. This is why I came up with the idea of using multiple instances of dnscrypt-proxy
to connect to those services, so one service can fill up the absence of another once they go offline.
dnscrypt-proxy-multi is a Ruby script that I created to do the task. It extracts entries from a database or resolvers list, and then checks those entries if the services they point to is available, i.e., if the port the service listens to is open.
After discovering the services, dnscrypt-proxy-multi
creates the instances of dnscrypt-proxy
that would connect to those services, in the order of how fast the services have responded from the port check. Once an instance of dnscrypt-proxy
is created, it can be optionally checked for its capability to resolve specific domain names through the --resolver-check
option. If an instance fails to resolve a domain name, it gets terminated, and the service that it has connected to would be ignored.
Once all the required instances are up, dnscrypt-proxy-multi
goes idle and just waits for all of them to terminate.
Installing dnscrypt-proxy-multi
dnscrypt-proxy-multi
can be downloaded using the browser, or by using curl
or wget
:
curl -O https://raw.githubusercontent.com/konsolebox/scripts/master/dnscrypt-proxy-multi.rb
wget https://raw.githubusercontent.com/konsolebox/scripts/master/dnscrypt-proxy-multi.rb
After downloading, you can install it to /usr/local/bin
:
install -m 0755 dnscrypt-proxy-multi.rb /usr/local/bin/dnscrypt-proxy-multi
If you’re using Gentoo, you can install the konsolebox
overlay through layman:
layman -a konsolebox
Or by placing konsolebox.conf to /etc/portage/repos.conf/
:
curl -o /etc/portage/repos.conf/konsolebox.conf \
https://raw.githubusercontent.com/konsolebox/overlay/master/konsolebox.conf.example
The file should contain something like this:
[konsolebox]
auto-sync = yes
location = /var/local/overlays/konsolebox
masters = gentoo
sync-type = git
sync-uri = git://github.com/konsolebox/overlay.git
You can change location
to refer a different directory, and also sync-uri
to use https://
instead of git://
.
After checking the file, you can update the repositories:
emerge --sync
And then add net-dns/dnscrypt-proxy-multi **
to /etc/portage/package.keywords
. Example:
echo 'net-dns/dnscrypt-proxy-multi **' > \
/etc/portage/package.keywords/net-dns.dnscrypt-proxy-multi
Then install the package like the usual emerge
method:
emerge net-dns/dnscrypt-proxy-multi
Required version of dnscrypt-proxy
Most of dnscrypt-proxy-multi
’s functions work well with the latest release version of dnscrypt-proxy
which as of this writing is 1.6.1, but the --dnscrypt-proxy-syslog
feature requires a new function which is currently only available in the latest source code of dnscrypt-proxy
, which is in its own repository in GitHub.
Installing the newest version from source would depend on the distro, but if you’re using Gentoo, you can just follow the steps above. Just target dnscrypt-proxy
, instead of dnscrypt-proxy-multi
.
Also check if 1.6.2, or a newer version is already available,
Usage
Here’s the output of dnscrypt-proxy-multi --help
:
dnscrypt-proxy-multi 2016-06-01
Runs multiple instances of dnscrypt-proxy.
Usage: /usr/bin/dnscrypt-proxy-multi [options]
Options:
-c, --resolver-check=FQDN[,FQDN2][/TIMEOUT[/WAIT]]
Check instances of dnscrypt-proxy if they can resolve all specified FQDN
and replace them with another instance that targets another resolver entry
if they don't. Default timeout is 5.0. Default amount of wait-time to
allow an instance to load and initialize before checking it is 0.1.
-C, --change-owner=USER[:GROUP]
Change ownership of directories to specified user-group before opening files
instantiating dnscrypt-proxy's, and dropping privilege to a user if
configured.
-d, --dnscrypt-proxy=PATH
Set path to dnscrypt-proxy executable.
Default is "/usr/sbin/dnscrypt-proxy".
-D, --instance-delay=SECONDS
Wait SECONDS seconds before creating the next instance of dnscrypt-proxy.
Default is 0.0.
-g, --group=GROUP
Drop priviliges to GROUP before creating instances of dnscrypt-proxy.
-G, --debug
Show debug messages.
-i, --local-ip=RANGE
Set range of IP addresses to listen to. Default is "127.0.100.1-254".
Example: "127.0.1-254.1-254,10.0.0.1"
-I, --ignore-ip-format
Do not check if a local IP address starts or ends with 0 or 255.
-l, --log [LOG_DIR]
Enable logging files to LOG_DIR.
Default directory is "/var/log/dnscrypt-proxy-multi".
-L, --log-level=LEVEL
When logging is enabled, tell dnscrypt-proxy to use log level LEVEL.
Default level is 6. See dnscrypt-proxy(8) for info.
-m, --max-instances=N
Set maximum number of dnscrypt-proxy instances. Default is 10.
-o, --log-output=FILE
When logging is enabled, write main log output to FILE.
Default is "<LOG_DIR>/dnscrypt-proxy-multi.log".
-O, --log-overwrite
When logging is enabled, do not append output to main log-file.
-p, --local-port=RANGE
Set range of ports to listen to.
Default is "53". Example: "2053,5300-5399"
-r, --resolvers-list=PATH
Set resolvers list file to use.
Default is "/usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv".
-R, --resolvers-list-encoding
Set encoding of resolvers list. Default is "utf-8".
-s, --port-check-async=N
Set number of port-check queries to send simultaneously. Default is 10.
-S, --syslog [PREFIX]
Log messages to system log. PREFIX gets inserted at the beginning of every
message sent to syslog if it's specified. See also -Z.
-t, --port-check-timeout=SECONDS
Set timeout when waiting for a port-check reply. Default is 5.0.
-u, --user=USER
Drop priviliges to USER before creating instances of dnscrypt-proxy.
Note that this might prevent dnscrypt-proxy from being able to listen to
ports lower than 1024.
-U, --dnscrypt-proxy-user=USER
Tell dnscrypt-proxy to drop privileges as USER.
Please consider that this may or may not work with --user.
-v, --verbose
Show verbose messages.
-V, --version
Show version and exit.
-w, --wait-for-connection=HOST[:PORT][,HOST2[:PORT2][,...]]
Wait until any of the specified hosts acknowledges connection, or responds
with an ICMP Echo reply if no port is specified. Checking with ICMP needs
net-ping gem, and requires root/administrative privileges.
-W, --write-pids [DIR]
Enable writing PID's to DIR.
Default directory is "/var/run/dnscrypt-proxy-multi".
-Z, --dnscrypt-proxy-syslog [PREFIX]
Tell dnscrypt-proxy to log messages to system log. It is automatically
configured to have a prefix of '[REMOTE_IP:PORT]'. If PREFIX is specified,
it is added to it with a space as a separator.
Note that this disables file-logging in dnscrypt-proxy.
-h, --help
Show this help info and exit.
Notes:
* Directories are automatically created recursively when needed.
* Services are checked with TCP ports since TCP is a common fallback.
* Local ports are first used up before the next IP address in range is used.
* Local ports are not checked if they are currently in use.
* Names of log files are created based on the remote address, while names of
PID files are based on the local address.
* dnscrypt-proxy creates files as the calling user; not the one specified with
--user, so changing ownership of directories and existing files may not be
necessary.
Simple Usage Example
Here’s a simple example of using dnscrypt-proxy-multi
:
dnscrypt-proxy-multi --local-ip=127.0.0.1 --local-port=5300-5309 \
--dnscrypt-proxy-user=dnscrypt --syslog --dnscrypt-proxy-syslog
The command specifies that port 5300 to 5309 will be used by dnscrypt-proxy
to listen to for connections, and that dnscrypt-proxy
will drop its privilege to user dnscrypt
, and do chroot(2)
to its home directory. See --user
option in dnscrypt-proxy(8)
.
Both --syslog
and --dnscrypt-proxy-syslog
specify that dnscrypt-proxy-multi
and dnscrypt-proxy
use syslog
to log messages.
Specifying a different resolvers list
Sometimes we would want to specify a custom resolvers list of our own. For example, we may want the resolvers list to exclude those from OpenDNS to prevent restrictions. This is the basic indiscriminate command to produce it:
grep -vi opendns /usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv > \
/var/local/dnscrypt-resolvers-custom.csv
Now we add the option --resolvers-list
to the command:
dnscrypt-proxy-multi --local-ip=127.0.0.1 --local-port=5300-5399 \
--dnscrypt-proxy-user=dnscrypt --syslog --dnscrypt-proxy-syslog \
--resolvers-list=/var/local/dnscrypt-resolvers-custom.csv
Checking services for their capability to resolve domain names
We can also configure dnscrypt-proxy-multi
to check if a service - that an instance of dnscrypt-proxy is connecting to - is capable of resolving domains.
The option’s format is --resolver-check=FQDN[,FQDN2][/TIMEOUT[/WAIT]]
.
Example usage:
--resolver-check=kernel.org,gentoo.org,disqus.com,a.disqus.com
It would tell dnscrypt-proxy-multi
to check that the service is able to resolve all the FQDN’s (Fully Qualified Domain Names) specified above. It would terminate the dnscrypt-proxy
process connecting to the service if it fails to resolve any of it.
We can also customize the amount of time (in seconds) that we can allow the service to respond. Example is 10 seconds instead of 5:
--resolver-check=kernel.org,gentoo.org,disqus.com,a.disqus.com/10.0
Note that a higher value means longer time for dnscrypt-proxy-multi to initialize. On the other hand, it should also be considered that some services take longer time to respond since they need to make multiple recursive queries to other name servers when the information about an FQDN is not yet in the cache, or is no longer valid, so having a longer waiting time would also be sensible.
Making dnscrypt-proxy-multi wait for connection before starting up
We can also make dnscrypt-proxy-multi
wait for a connection before it starts checking if DNS servers are available.
This is helpful during startup when Internet connection may not yet be active.
An example usage is --wait-for-connection=208.67.220.220:53,208.67.222.222:53
, which would allow dnscrypt-proxy-multi
to continue if a response is received from either of those addresses.
This will be the complete command so far:
dnscrypt-proxy-multi --local-ip=127.0.0.1 --local-port=5300-5399 \
--dnscrypt-proxy-user=dnscrypt --syslog --dnscrypt-proxy-syslog \
--resolvers-list=/var/local/dnscrypt-resolvers-custom.csv \
--resolver-check=kernel.org,gentoo.org,disqus.com,a.disqus.com \
--wait-for-connection=208.67.202.202:53,208.67.222.222:53
Here’s an example output after running the command:
# dnscrypt-proxy-multi --local-ip=127.0.0.1 --local-port=5300-5399 \
> --dnscrypt-proxy-user=dnscrypt --syslog --dnscrypt-proxy-syslog \
> --resolvers-list=/var/local/dnscrypt-resolvers-custom.csv \
> --resolver-check=kernel.org,gentoo.org,disqus.com,a.disqus.com \
> --wait-for-connection=208.67.202.202:53,208.67.222.222:53
----------------------------------------
Starting up.
[Warning] Ignoring entry with invalid or unsupported resolver address: Resolver address
[Warning] Using default port 443 for 51.254.115.48.
[Warning] Using default port 443 for 208.67.220.220.
[Warning] Using default port 443 for 208.67.220.123.
[Warning] Ignoring entry with invalid or unsupported resolver address: [2620:0:ccc::2]
[Warning] Using default port 443 for 113.20.6.2.
[Warning] Using default port 443 for 113.20.8.17.
[Warning] Using default port 443 for 162.221.207.228.
[Warning] Using default port 443 for 212.83.175.31.
[Warning] Using default port 443 for 195.154.61.33.
[Warning] Using default port 443 for 185.60.147.77.
[Warning] Using default port 443 for 46.165.222.246.
[Warning] Using default port 443 for 212.129.46.86.
[Warning] Using default port 443 for 212.129.46.32.
[Warning] Using default port 443 for 95.141.47.58.
[Warning] Using default port 443 for 173.234.159.235.
[Warning] Using default port 443 for 173.234.56.115.
[Warning] Using default port 443 for 70.32.38.67.
[Warning] Using default port 443 for 108.62.19.131.
[Warning] Using default port 443 for 76.164.234.11.
[Warning] Using default port 443 for 104.238.194.235.
[Warning] Using default port 443 for 217.12.203.133.
[Warning] Using default port 443 for 81.2.237.32.
[Warning] Using default port 443 for 82.211.31.248.
[Warning] Using default port 443 for 185.137.15.105.
[Warning] Using default port 443 for 77.66.108.93.
[Warning] Using default port 443 for 85.25.105.193.
[Warning] Using default port 443 for 37.235.49.61.
[Warning] Using default port 443 for 31.14.133.188.
[Warning] Using default port 443 for 89.111.13.60.
[Warning] Using default port 443 for 178.17.170.133.
[Warning] Using default port 443 for 185.14.29.140.
[Warning] Using default port 443 for 77.81.104.121.
[Warning] Using default port 443 for 41.79.69.13.
[Warning] Using default port 443 for 217.12.210.54.
[Warning] Using default port 443 for 77.66.84.233.
[Warning] Ignoring entry with invalid or unsupported resolver address: [2001:1448:243::dc2]
[Warning] Using default port 443 for 176.56.237.171.
[Warning] Ignoring entry with invalid or unsupported resolver address: [2a00:d880:3:1::a6c1:2e89]
[Warning] Using default port 443 for 212.47.228.136.
[Warning] Using default port 443 for 185.121.177.177.
[Warning] Using default port 443 for 185.121.177.53.
[Warning] Using default port 443 for 79.133.43.124.
[Warning] Using default port 443 for 172.81.176.146.
[Warning] Ignoring entry with invalid or unsupported resolver address: [2602:ffb6:2:0:f816:3eff:fe23:ae28]
[Warning] Using default port 443 for 185.97.7.7.
[Warning] Using default port 443 for 185.115.125.185.
[Warning] Using default port 443 for 93.170.96.119.
[Warning] Using default port 443 for 95.154.236.104.
[Warning] Using default port 443 for 103.53.199.71.
[Warning] Using default port 443 for 217.78.6.191.
[Warning] Using default port 443 for 91.247.228.155.
[Warning] Using default port 443 for 185.99.132.5.
[Warning] Ignoring entry with invalid or unsupported resolver address: [2a06:1280:bee1::dea:5]
[Warning] Using default port 443 for 173.44.61.182.
[Warning] Using default port 443 for 194.132.32.32.
[Warning] Using default port 443 for 93.95.228.87.
[Warning] Using default port 443 for 23.226.227.93.
[Warning] Ignoring entry with invalid or unsupported resolver address: [2a02:7aa0:1619::c434:714c]:5353
[Warning] Ignoring entry with invalid or unsupported resolver address: [2001:470:70:4ff::2]:2053
[Warning] Using default port 443 for 40.68.125.220.
Waiting for connection.
Checking resolver address 51.254.115.48:443.
Checking resolver address 208.67.220.220:443.
Checking resolver address 208.67.220.123:443.
Checking resolver address 208.67.220.220:53.
Checking resolver address 113.20.6.2:443.
Checking resolver address 113.20.8.17:443.
Checking resolver address 162.221.207.228:443.
Checking resolver address 212.83.175.31:443.
Checking resolver address 195.154.61.33:443.
Checking resolver address 185.60.147.77:443.
Checking resolver address 46.165.222.246:443.
Checking resolver address 212.129.46.86:443.
Checking resolver address 212.129.46.32:443.
Checking resolver address 95.141.47.58:443.
Checking resolver address 173.234.159.235:443.
Checking resolver address 173.234.56.115:443.
Checking resolver address 70.32.38.67:443.
Checking resolver address 108.62.19.131:443.
Checking resolver address 76.164.234.11:443.
Checking resolver address 104.238.194.235:443.
Checking resolver address 217.12.203.133:443.
Checking resolver address 81.2.237.32:443.
Checking resolver address 82.211.31.248:443.
Checking resolver address 185.137.15.105:443.
Checking resolver address 77.66.108.93:443.
Checking resolver address 37.187.0.40:54.
Checking resolver address 85.25.105.193:443.
Checking resolver address 37.235.49.61:443.
Checking resolver address 31.14.133.188:443.
Checking resolver address 89.111.13.60:443.
Checking resolver address 178.17.170.67:54.
Checking resolver address 95.85.9.86:80.
Checking resolver address 185.83.217.248:5353.
Checking resolver address 178.17.170.133:443.
Checking resolver address 185.14.29.140:443.
Checking resolver address 77.81.104.121:443.
Checking resolver address 91.214.71.181:80.
Checking resolver address 128.199.248.105:54.
Checking resolver address 41.79.69.13:443.
Checking resolver address 217.12.210.54:443.
Checking resolver address 77.66.84.233:443.
Checking resolver address 176.56.237.171:443.
Checking resolver address 212.47.228.136:443.
Checking resolver address 185.121.177.177:443.
Checking resolver address 185.121.177.53:443.
Checking resolver address 79.133.43.124:443.
Checking resolver address 172.81.176.146:443.
Checking resolver address 185.97.7.7:443.
Checking resolver address 185.115.125.185:443.
Checking resolver address 93.170.96.119:443.
Checking resolver address 95.154.236.104:443.
Checking resolver address 103.53.199.71:443.
Checking resolver address 217.78.6.191:443.
Checking resolver address 91.247.228.155:443.
Checking resolver address 185.99.132.5:443.
Checking resolver address 173.44.61.182:443.
Checking resolver address 194.132.32.32:443.
Checking resolver address 93.95.228.87:443.
Checking resolver address 23.226.227.93:443.
Checking resolver address 130.255.73.90:5353.
Checking resolver address 46.227.67.134:55.
Checking resolver address 93.115.92.252:5353.
Checking resolver address 95.215.46.195:5353.
Checking resolver address 45.55.117.60:8080.
Checking resolver address 45.55.113.239:8080.
Checking resolver address 178.216.201.222:2053.
Checking resolver address 40.68.125.220:443.
Checking resolver address 77.88.8.78:15353.
Starting dnscrypt-proxy instance for 208.67.220.123:443 (127.0.0.1:5300).
Checking if 208.67.220.123:443 (127.0.0.1:5300) can resolve kernel.org.
Success: 194.44.204.199
Checking if 208.67.220.123:443 (127.0.0.1:5300) can resolve gentoo.org.
Success: 134.167.16.89
Checking if 208.67.220.123:443 (127.0.0.1:5300) can resolve disqus.com.
Success: 134.33.235.23
Checking if 208.67.220.123:443 (127.0.0.1:5300) can resolve a.disqus.com.
Success: 134.52.101.151
Starting dnscrypt-proxy instance for 208.67.220.220:53 (127.0.0.1:5301).
Checking if 208.67.220.220:53 (127.0.0.1:5301) can resolve kernel.org.
Success: 194.44.204.199
Checking if 208.67.220.220:53 (127.0.0.1:5301) can resolve gentoo.org.
Success: 134.167.16.89
Checking if 208.67.220.220:53 (127.0.0.1:5301) can resolve disqus.com.
Success: 134.33.235.23
Checking if 208.67.220.220:53 (127.0.0.1:5301) can resolve a.disqus.com.
Success: 134.52.101.151
Starting dnscrypt-proxy instance for 128.199.248.105:54 (127.0.0.1:5302).
Checking if 128.199.248.105:54 (127.0.0.1:5302) can resolve kernel.org.
Success: 194.44.204.199
Checking if 128.199.248.105:54 (127.0.0.1:5302) can resolve gentoo.org.
Success: 134.167.16.89
Checking if 128.199.248.105:54 (127.0.0.1:5302) can resolve disqus.com.
Success: 134.85.156.104
Checking if 128.199.248.105:54 (127.0.0.1:5302) can resolve a.disqus.com.
Success: 134.40.101.151
Starting dnscrypt-proxy instance for 208.67.220.220:443 (127.0.0.1:5303).
Checking if 208.67.220.220:443 (127.0.0.1:5303) can resolve kernel.org.
Success: 194.44.204.199
Checking if 208.67.220.220:443 (127.0.0.1:5303) can resolve gentoo.org.
Success: 134.167.16.89
Checking if 208.67.220.220:443 (127.0.0.1:5303) can resolve disqus.com.
Success: 134.81.156.104
Checking if 208.67.220.220:443 (127.0.0.1:5303) can resolve a.disqus.com.
Success: 134.24.101.151
Starting dnscrypt-proxy instance for 185.121.177.53:443 (127.0.0.1:5304).
Checking if 185.121.177.53:443 (127.0.0.1:5304) can resolve kernel.org.
Success: 194.44.204.199
Checking if 185.121.177.53:443 (127.0.0.1:5304) can resolve gentoo.org.
Success: 134.167.16.89
Checking if 185.121.177.53:443 (127.0.0.1:5304) can resolve disqus.com.
Success: 134.81.156.104
Checking if 185.121.177.53:443 (127.0.0.1:5304) can resolve a.disqus.com.
Success: 134.24.101.151
Starting dnscrypt-proxy instance for 185.121.177.177:443 (127.0.0.1:5305).
Checking if 185.121.177.177:443 (127.0.0.1:5305) can resolve kernel.org.
Success: 194.44.204.199
Checking if 185.121.177.177:443 (127.0.0.1:5305) can resolve gentoo.org.
Success: 134.167.16.89
Checking if 185.121.177.177:443 (127.0.0.1:5305) can resolve disqus.com.
Success: 134.81.156.104
Checking if 185.121.177.177:443 (127.0.0.1:5305) can resolve a.disqus.com.
Success: 134.24.101.151
Starting dnscrypt-proxy instance for 104.238.194.235:443 (127.0.0.1:5306).
Checking if 104.238.194.235:443 (127.0.0.1:5306) can resolve kernel.org.
Success: 69.4.20.149
Checking if 104.238.194.235:443 (127.0.0.1:5306) can resolve gentoo.org.
Success: 134.167.16.89
Checking if 104.238.194.235:443 (127.0.0.1:5306) can resolve disqus.com.
Success: 134.37.235.23
Checking if 104.238.194.235:443 (127.0.0.1:5306) can resolve a.disqus.com.
Success: 134.24.101.151
Starting dnscrypt-proxy instance for 103.53.199.71:443 (127.0.0.1:5307).
Checking if 103.53.199.71:443 (127.0.0.1:5307) can resolve kernel.org.
Success: 194.44.204.199
Checking if 103.53.199.71:443 (127.0.0.1:5307) can resolve gentoo.org.
Success: 134.167.16.89
Checking if 103.53.199.71:443 (127.0.0.1:5307) can resolve disqus.com.
Success: 134.37.235.23
Checking if 103.53.199.71:443 (127.0.0.1:5307) can resolve a.disqus.com.
Success: 134.40.101.151
Starting dnscrypt-proxy instance for 45.55.113.239:8080 (127.0.0.1:5308).
Checking if 45.55.113.239:8080 (127.0.0.1:5308) can resolve kernel.org.
Success: 194.44.204.199
Checking if 45.55.113.239:8080 (127.0.0.1:5308) can resolve gentoo.org.
Success: 134.167.16.89
Checking if 45.55.113.239:8080 (127.0.0.1:5308) can resolve disqus.com.
Success: 134.85.156.104
Checking if 45.55.113.239:8080 (127.0.0.1:5308) can resolve a.disqus.com.
Success: 134.40.101.151
Starting dnscrypt-proxy instance for 23.226.227.93:443 (127.0.0.1:5309).
Checking if 23.226.227.93:443 (127.0.0.1:5309) can resolve kernel.org.
Success: 140.20.145.198
Checking if 23.226.227.93:443 (127.0.0.1:5309) can resolve gentoo.org.
Success: 134.167.16.89
Checking if 23.226.227.93:443 (127.0.0.1:5309) can resolve disqus.com.
Success: 134.81.156.104
Checking if 23.226.227.93:443 (127.0.0.1:5309) can resolve a.disqus.com.
Success: 134.52.101.151
Running dnscrypt-proxy-multi from an init script
Creating a service for dnscrypt-proxy-multi
is pretty straightforward, and is about the same as any other service. The only difference is that we have to explicitly specify the Ruby program that would directly run dnscrypt-proxy-multi
.
An example to this is this OpenRC script for Gentoo provided by net-dns/dnscrypt-proxy-multi:
#!/sbin/openrc-run
# Copyright 1999-2016 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
RUBY_EXEC=${RUBY_EXEC:-/usr/bin/ruby}
PID_FILE=${PID_FILE:-/run/dnscrypt-proxy-multi.pid}
description="Runs multiple instances of dnscrypt-proxy"
depend() {
use net
before dns
after logger
}
start() {
ebegin "Starting dnscrypt-proxy-multi"
start-stop-daemon --start --quiet --background --pidfile "${PID_FILE}" --make-pidfile --exec "${RUBY_EXEC}" -- \
/usr/bin/dnscrypt-proxy-multi ${DNSCRYPT_PROXY_MULTI_OPTIONS}
eend "$?"
}
stop() {
ebegin "Stopping dnscrypt-proxy-multi"
start-stop-daemon --stop --quiet --pidfile "${PID_FILE}"
eend "$?"
}
Setting up named or unbound to forward requests to the instances of dnscrypt-proxy
Now that we have instances of dnscrypt-proxy
set up, we can now use a local DNS server to catch all requests from the system and forward them to the instances.
Here’s an example for named
(/etc/bind/named.conf
). The most important directives are forward
and forwarders
.
/*
* Refer to the named.conf(5) and named(8) man pages, and the documentation
* in /usr/share/doc/bind-9 for more details.
* Online versions of the documentation can be found here:
* http://www.isc.org/software/bind/documentation
*/
acl "xfer" {
none;
};
acl "trusted" {
127.0.0.0/8;
};
options {
directory "/var/bind";
pid-file "/run/named/named.pid";
listen-on { 127.0.0.1; };
allow-query {
trusted;
};
allow-query-cache {
trusted;
};
allow-recursion {
trusted;
};
allow-transfer {
none;
};
allow-update {
none;
};
forward only;
forwarders {
127.0.0.1 port 5300; // dnscrypt-proxy-multi
127.0.0.1 port 5301; // dnscrypt-proxy-multi
127.0.0.1 port 5302; // dnscrypt-proxy-multi
127.0.0.1 port 5303; // dnscrypt-proxy-multi
127.0.0.1 port 5304; // dnscrypt-proxy-multi
127.0.0.1 port 5305; // dnscrypt-proxy-multi
127.0.0.1 port 5306; // dnscrypt-proxy-multi
127.0.0.1 port 5307; // dnscrypt-proxy-multi
127.0.0.1 port 5308; // dnscrypt-proxy-multi
127.0.0.1 port 5309; // dnscrypt-proxy-multi
};
recursion yes;
};
include "/etc/bind/logging.conf";
zone "." in {
type hint;
file "/var/bind/named.cache";
};
zone "localhost" IN {
type master;
file "pri/localhost.zone";
notify no;
};
zone "127.in-addr.arpa" IN {
type master;
file "pri/127.zone";
notify no;
};
And here’s an example configuration for unbound
:
server:
verbosity: 1
interface: 127.0.0.1
chroot: "/chroot/unbound"
root-hints: "/etc/root.hints"
do-not-query-localhost: no
forward-zone:
name: "."
forward-addr: 127.0.0.1@5300
forward-addr: 127.0.0.1@5301
forward-addr: 127.0.0.1@5302
forward-addr: 127.0.0.1@5303
forward-addr: 127.0.0.1@5304
forward-addr: 127.0.0.1@5305
forward-addr: 127.0.0.1@5306
forward-addr: 127.0.0.1@5307
forward-addr: 127.0.0.1@5308
forward-addr: 127.0.0.1@5309
forward-first: no
Notice that we had to use do-not-query-localhost: no
since it is yes
by default, and queries sent to 127.0.0.1/8
and ::1
are not allowed. If you think it’s a security risk, you can make dnscrypt-proxy
listen to local addresses besides 127.0.0.1
, like 127.1.0.1
, and add custom do-not-query-address
values that would target localhost addresses besides it, like 127.0.0.1/16
.
Once configured, start the name server with your service manager. For example:
/etc/init.d/named start
/etc/init.d/unbound start
After that, running dig kernel.org @127.0.0.1
should give us something like this:
; <<>> DiG 9.10.3-P2 <<>> kernel.org @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35985
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;kernel.org. IN A
;; ANSWER SECTION:
kernel.org. 571 IN A 199.204.44.194
kernel.org. 571 IN A 198.145.20.140
kernel.org. 571 IN A 149.20.4.69
Seeing that everything’s ok, we can now add 127.0.0.1
to /etc/resolv.conf
:
# echo 'nameserver 127.0.0.1' > /etc/resolv.conf
You can make it permanent by configuring your network interface with the network manager you use, just like this one:
Side note: We actually can just make instances of dnscrypt-proxy
listen to multiple IP addresses like 127.53.0.1 to 127.53.0.10 where each would listen to port 53, and just add those IP addresses to /etc/resolv.conf
; no longer needing a local name server in between, but I still prefer the idea of having everything managed by a single server, where the server may also cache the DNS data by itself.
Filtering syslog messages
If we’re using syslog
to all instances of dnscrypt-proxy
and dnscrypt-proxy-multi
, we can filter them and send them to another file by configuring syslog-ng
(granting syslog-ng
is our system logger application).
Here’s an example configuration in /etc/syslog-ng/syslog-ng.conf
. Note that I have excluded the options
directive.
...
source s_system { system(); internal(); };
filter f_dnscrypt_proxy { program(^dnscrypt-proxy$); };
filter f_dnscrypt_proxy_multi { program(^dnscrypt-proxy-multi$); };
filter f_messages { not program(^unbound$) and not program(^dnscrypt-proxy$) and not program(^dnscrypt-proxy-multi$); };
filter f_unbound { program(^unbound$); };
destination d_console_all { file("/dev/tty12"); };
destination d_dnscrypt_proxy { file("/var/log/dnscrypt-proxy.log"); };
destination d_dnscrypt_proxy_multi { file("/var/log/dnscrypt-proxy-multi.log"); };
destination d_messages { file("/var/log/messages"); };
destination d_unbound { file("/var/log/unbound.log"); };
log { source(s_system); filter(f_dnscrypt_proxy); destination(d_dnscrypt_proxy); };
log { source(s_system); filter(f_dnscrypt_proxy_multi); destination(d_dnscrypt_proxy_multi); };
log { source(s_system); destination(d_console_all); };
log { source(s_system); filter(f_messages); destination(d_messages); };
log { source(s_system); filter(f_unbound); destination(d_unbound); };
For more informtion on how those directives work, please see syslog-ng.conf(5)
.
After making the changes, restart the syslog-ng
to make it work. In Gentoo, you can do it with /etc/init.d/syslog-ng restart
.
Running dnscrypt-proxy-multi in a chroot environment
I’ll be updating this article for that information, but if you’re using Gentoo and OpenRC, you can install the konsolebox
overlay and use the chroot
flag when you install net-dns/dnscrypt-proxy-multi
. After installing the package, configure /etc/conf.d/dnscrypt-proxy-multi-chroot
and run /etc/conf.d/dnscrypt-proxy-multi-chroot setup
. Run /etc/conf.d/dnscrypt-proxy-multi-chroot start
afterwards. Don’t forget to add the init script at boot time with rc-config add dnscrypt-proxy-multi-chroot
if you need to.
It should also be noted that dnscrypt-proxy
is already capable of doing chroot
by itself when specified with a user, which can be configured through dnscrypt-proxy-multi
’s --dnscrypt-proxy-user
option. See dnscrypt-proxy(8)
for more info about the --user
option, which is called by dnscrypt-proxy-multi
when --dnscrypt-proxy-user
is used.