trailofbits / algo

Set up a personal VPN in the cloud
https://blog.trailofbits.com/2016/12/12/meet-algo-the-vpn-that-works/
GNU Affero General Public License v3.0
28.66k stars 2.31k forks source link

Simplify DNS provision, avoid need for random DNS server IP. #1478

Open dr8 opened 5 years ago

dr8 commented 5 years ago

I have a similar personal project to this, that I've been developing; which has some different approaches to DNS server provision that seem simpler. They may not, in fact, be better, but they seem to work for me:

  1. dnscrypt-proxy can do both dns filtering (for ad blocking) and dns over https, removing the need for dnsmasq
  2. dnscrypt-proxy can use systemd socket activation, which means that the dnscrypt-proxy binary doesn't need any privileges
  3. by using a Systemd socket drop in file that specifies FreeBind=yes, the socket can be assigned to the wireguard address(es) even if the interface is not up and it will gracefully attach to the relevant ip addresses whenever the interface is up and the addresses available.
  4. which in turn removes the need for a random IP address to be created to avoid the DNS leakage, as DNS requests from the client will always be routed to the wireguard endpoint.

To set up dnscrypt-proxy using socket activation, simply don't specify any server ip addresses in the config file dnscrypt-proxy.toml, and create the following file at /etc/systemd/system/dnscrypt-proxy.socket.d/algo.conf

[Socket]
FreeBind=yes
ListenDatagram={{ wireguard_server_ip }}:53
ListenStream={{ wireguard_server_ip }}:53

For context, I've tested this for wireguard using ipv4, but not ipv6. I don't see any reason why it wouldn't work for ipv6. Just add lines for as many ip addresses as necessary in the socket drop-in file

I have also not looked at using this with IPsec, as I no longer use IPsec since setting up wireguard.

davidemyers commented 5 years ago

This sounds like an elegant approach. One thing to consider is whether this removes an option users currently have. Algo can be deployed as follows:

DNS Encryption DNS Blocking
1 Yes No
2 Yes Yes
3 No No
4 No Yes

1 is of course the default. But can 4 be implemented with only dnscrypt-proxy?

dr8 commented 5 years ago

Very good question. I am not sure whether or not it can (or how easy it would be).

It looks as though all servers need to be specified using DNS stamps (rather than just an IP address or FQDN), and although a plain DNS server looks to be supported in the spec, it would mean writing code to create the stamp, and that's reintroducing complexity.

A quick search doesn't give me much confidence that anyone's using dnscrypt-proxy like this, so it's totally possible that it would work, but it would have to be an experiment to try it out.

jackivanov commented 5 years ago

I don't see any disadvantages or any specific reasons why anybody wants to use the adblocking without encryption, so, I would rather remove the 4th option to simplify the installation, and we're good to go with dnscrypt-proxy only

jackivanov commented 5 years ago

@dr8 Is there any way to implement the same behaviour for FreeBSD?

jackivanov commented 5 years ago

No, not possible. This should be handled by the daemon itself, but not by the system. Needs to be implemented here.

rodeodomino commented 5 years ago

This is far beyond my personal bash scripting skills, but moving dns adblocking to dnscrypt-proxy allows non-domain wildcard ad blocking. Not sure if it would be helpful to have the adblocking script force add a couple of these to the beginning of the list (or go one step further to remove domains that would be covered in the wildcards like this script.

TC1977 commented 5 years ago

Would taking dnsmasq out of the picture speed up or slow down the Adblock list loading and the actual ad blocking? Is there any reliable and meaningful way for us to test?

davidemyers commented 5 years ago

The reloading is super fast using #1480 with the default list:

root@vpn6:~# time /usr/local/sbin/adblock.sh
Downloading hosts lists...
Restarting dns service...

real    0m0.648s
user    0m0.471s
sys     0m0.066s
TC1977 commented 5 years ago

Faster even than dnsmasq. This is what I got on my March-era deployment (Lightsail $3.50/mo plan):

root@ip-172-26-11-214:~# time /usr/local/sbin/adblock.sh
Downloading hosts lists...
Restarting dnsmasq service...

real    0m2.309s
user    0m0.574s
sys 0m0.060s

But I was also asking about the actual ad blocking. Any way we could test this? For example, use a script to run a whole bunch of digs off an un-cached list?

jackivanov commented 5 years ago

I put the tests here