thuantran / dnscrypt-asuswrt-installer

dnscrypt installer for Asus router with merlin firmware
GNU General Public License v3.0
111 stars 16 forks source link

DNSSEC should be validated by dnscrypt instead of dnsmasq #31

Closed caribpa closed 6 years ago

caribpa commented 6 years ago

Hi, I've found out that DNSSEC is being validated by dnsmasq (if enabled in the UI) instead of dnscrypt-proxy. To change this behavior we have to append to dnsmasq.conf the option proxy-dnssec, to do that we edit the line 86 of the file manager like this:

append_on_demand /etc/dnsmasq.conf "no-resolv" "proxy-dnssec" "server=127.0.0.1#65053"

Then we have to disable DNSSEC in the UI to prevent it from adding the option dnssec to dnsmasq.conf:

LAN (Advanced Settings) → DHCP Server → DNS and WINS Server Setting → Enable DNSSEC support = No

And then we reboot the router.

I know that this proxy-dnssec option is not well known and does not appear in every manual but it's the way to take advantage of dnscrypt's full potential.

You can read about proxy-dnssec here and it's recommended in the Arch Wiki.

caribpa commented 6 years ago

After playing a little more with your scripts I believe that there's a better way to do what I said above so that the user doesn't have to care about DNSSEC in the UI. Also I've fixed some other issues regarding dnsmasq waiting and timing out because dnscrypt is not ready at startup.

I've changed the dnsmasq section in the manager's file (/jffs/dnscrypt/manager) to:

dnsmasq)
    sed -i "/^servers-file=.*$/d" /etc/dnsmasq.conf
    append_on_demand /etc/dnsmasq.conf "no-resolv"
    if [ -f /tmp/dnscrypt-start ]; then
            sed -i "/^dnssec.*$/d; /^trust-anchor=.*$/d" /etc/dnsmasq.conf
            append_on_demand /etc/dnsmasq.conf "proxy-dnssec" "server=127.0.0.1#65053"
    else
        for i in `nvram get wan0_dns1_x` `nvram get wan0_dns2_x`; do
            append_on_demand /etc/dnsmasq.conf "server=$i"
        done
        grep "^dnssec$" /etc/dnsmasq.conf && append_on_demand /etc/dnsmasq.conf "dnssec-check-unsigned"
    fi
;;

Now I'm going to explain what happened before this fix:

Let's start saying that dnsmasq starts with errors because the script /jffs/scripts/dnsmasq.postconf is executed before /jffs/scripts/wan-start, so the file /tmp/resolv.dnsmasq doesn't exist when dnsmasq is trying to open it, which means that it won't be able to connect to the internet right away (but eventually will once the file is created). Also we know that dnscrypt starts after the execution of /jffs/scripts/wan-start which means that dnsmasq will timeout a lot waiting for it at startup (I believe it's because it will try to connect to the NTP servers to set the system's time), making the startup of the router and the network very slow.

Now that we know the issues, I'm going to try to explain how I fixed it:

First, we need to remove the servers-file option and append no-resolv to /etc/dnsmasq.conf to prevent it from using any other resolver and waiting for a file that doesn't exist at startup. Second, to know when dnscrypt is ready, we will create a file (/tmp/dnscrypt-start) when /jffs/scripts/wan-start is executed, and then we will restart dnsmasq's service.

The first time dnsmasq launches has to be without dnscrypt. So, if the file /tmp/dnscrypt-start doesn't exist, we append the WAN's DNS servers we chose manually (I didn't try with the automatic option) in the UI (WAN (Advanced Settings) → Internet Connection → WAN DNS Settings) using a for loop so internet will be available right away, and if the user enabled DNSSEC in the UI (LAN (Advanced Settings) → DHCP Server → DNS and WINS Server Setting → Enable DNSSEC support) then we also append the dnsmasq option dnssec-check-unsigned for further protection, as we will be using dnsmasq to validate DNSSEC until dnscrypt is ready.

When dnscrypt is ready (the file /tmp/dnscrypt-start exists), we delete all the dnssec options and append the option proxy-dnssec and server=127.0.0.1#65053 to the file /etc/dnsmasq.conf because we want to use dnscrypt as upstream server and proxy it the DNSSEC requests.

For all this process to work, we also have to edit one of the startup scripts (/jffs/scripts/) as follow:

/jffs/scripts/wan-start
----------------------------
#!/bin/sh
[ -x /jffs/dnscrypt/manager ] && touch /tmp/dnscrypt-start && service restart_dnsmasq

So, in the end there's no need in starting dnscrypt in /jffs/scripts/wan-start as the manager (/jffs/dnscrypt/manager) will automatically launch it.

You can find my scripts here: dnscrypt-files.zip

Note that I'm using a RT-AC86U with firmware AsusWRT-Merlin 384.3, so I don't know if this applies to other firmwares and routers.

caribpa commented 6 years ago

Today, after powering up my RT-AC86U again, I found out that the manager's monitor didn't start dnscrypt automatically as it does after a reboot, so now I understand why it was necessary to launch it manually in the wan-start.

So the wan-start should be:

/jffs/scripts/wan-start
----------------------------
#!/bin/sh
[ -x /jffs/dnscrypt/manager ] && touch /tmp/dnscrypt-start && service restart_dnsmasq && sleep 2 && /jffs/dnscrypt/manager dnscrypt-start

But it seems strange that the monitor doesn't launch dnscrypt after a cold boot.

I'm going to investigate what can be changed in the manager's monitor to prevent this.

thuantran commented 6 years ago

Well, I'm no expert at DNSSEC but from what I read I have a few things that I think differently from yours:

So what do I think is a good config: Use a DoH, or DNSCrypt server that does DNSSEC validation (e.g. google). That way you don't even need to do validation on dnsmasq or on your client. And in case, your upstream server does not support validation but does proxy DNSSEC signature, enable the DNSSEC settings in WebUI for dnsmasq. Unless you want to use DNSSEC validation on your client, then you need to include proxy-dnssec on dnsmasq.conf as suggested in your first post, which is a rather unique use case, that I'm not willing to support.

TL;DR, I haven't seen a sound reason to do what you've suggested, sorry.

caribpa commented 6 years ago

The first thing I'd like to say is that I'm not sure if proxy-dnssec should be added or not in dnsmasq.conf as I've been using it since I saw it recommended at the Arch Wiki but I didn't research it deep enough to know what it does.

Leaving proxy-dnssec aside, I believe that the rest of my suggestions should be considered because I modified the scripts after I found out that your dnscrypt-proxy's scripts were the responsible for the considerable slower startup of my router (RT-AC86U) and the network. Of course these changes should be tested in other routers to see if they don't work with them.

Now, returning to proxy-dnssec, here is its description from the official documentation:

--proxy-dnssec Copy the DNSSEC Authenticated Data bit from upstream servers to downstream clients and cache it. This is an alternative to having dnsmasq validate DNSSEC, but it depends on the security of the network between dnsmasq and the upstream servers, and the trustworthiness of the upstream servers.

Maybe I'm not right but this is what I understand from the description above:

So in my understanding, the benefit in having the proxy-dnssec option is that there is less overhead because of the cached DNSSEC data bits.

In any case, adding proxy-dnssec to dnsmasq when the user is not using DNSSEC won't hurt because dnsmasq will just wait for the validated DNSSEC request from dnscrypt, but it doesn't mean that dnsmasq will receive any.

thuantran commented 6 years ago

Using dnscrypt-proxy with slow DNS server or automatic mode might slow down the boot process. To go into details, as far as I have tested, using Google or Cisco server although not as private, they're really fast, and virtually have no impact on your boot time. For those OpenNIC servers, they are definitely slower at least from my location. Although there's a way to fix this simply by first not modifying dnsmasq.conf before dnscrypt-proxy started, then only restart dnsmasq after wan-start and dnscrypt-proxy have started. I don't like how the log is clogging up with these logs and because this is a side effect of user configuration and not like you reboot your router every half an hour, I won't implement this unless there's a bigger issue with it.

As for proxy-dnssec cache, any kind of DNSSEC option either validation or proxy, it will be cached according to the same manual page you sent. To be specific, read dnssec option document.

caribpa commented 6 years ago

Sorry, I believe I didn't explain myself correctly.

When my RT-AC86U boots and I'm using your scripts, I have to wait almost 2 minutes for the network because your script adds server=127.0.0.1#65053 (manager - line 86) to /etc/dnsmasq.conf before dnscrypt is executed. Meaning that dnsmasq is waiting for the upstream server (dnscrypt) to resolve the early queries (such as setting the router's time), and it will timeout because dnscrypt is not running at that time. For solving that, I suggested this change in /jffs/dnscrypt/manager:

dnsmasq)
    sed -i "/^servers-file=.*$/d" /etc/dnsmasq.conf
    append_on_demand /etc/dnsmasq.conf "no-resolv"
    if [ -f /tmp/dnscrypt-start ]; then
            sed -i "/^dnssec.*$/d; /^trust-anchor=.*$/d" /etc/dnsmasq.conf
            append_on_demand /etc/dnsmasq.conf "proxy-dnssec" "server=127.0.0.1#65053"
    else
        for i in `nvram get wan0_dns1_x` `nvram get wan0_dns2_x`; do
            append_on_demand /etc/dnsmasq.conf "server=$i"
        done
        grep -q "^dnssec$" /etc/dnsmasq.conf && append_on_demand /etc/dnsmasq.conf "dnssec-check-unsigned"
    fi
;;

In combination with this change in /jffs/scripts/wan-start:

[ -x /jffs/dnscrypt/manager ] && touch /tmp/dnscrypt-start && service restart_dnsmasq && sleep 2 && /jffs/dnscrypt/manager dnscrypt-start

Meaning:

To prove the slow startup, I'm going to show you the logs of my RT-AC86U using your scripts before and after the changes I suggested. I'll be showing just until the network has access to the internet, but you can download the full logs: Before:

Mar  6 09:43:42 haveged: haveged starting up
Mar  6 09:43:42 kernel: Emergency Sync completeIDPfw: Exit IDPfwmod epilog takes 0 jiffiesIDPfw: Exit IDPfwExit chrdev /dev/idpfw with major 191Exit chrdev /dev/detector with major 190br0: port 6(eth6) entered disabled statebr0: port 5(eth5) entered disabled state br0: port 3(eth3) entered disabled statedevice eth1 left promiscuous modebr0: port 1(eth1) entered disabled statedevice eth2 left promiscuous modebr0: port 2(eth2) entered disabled statedevice eth3 left promiscuous modebr0: port3(eth3) entered
Mar  6 09:43:42 kernel: ____________________________________________________________________________
Mar  6 09:43:42 kernel: IGMP Query send failed
Mar  6 09:43:42 kernel: IGMP Query send failed
Mar  6 09:43:43 nat: apply redirect rules
Mar  6 09:43:44 custom_script: Running /jffs/scripts/dnsmasq.postconf (args: /etc/dnsmasq.conf)
Mar  6 09:43:44 RT-AC86U: start httpd:80
[...]
Mar  6 09:44:18 hour_monitor: daemon is starting
Mar  6 09:45:20 disk_monitor: be idle
Mar  6 09:45:20 Samba_Server: daemon is started
Mar  6 09:45:21 custom_script: Running /jffs/scripts/services-start
Mar  6 09:45:21 jffs2: valid logs(1)
Mar  6 09:45:22 custom_script: Running /jffs/scripts/wan-start (args: 0)
Mar  6 09:45:22 admin: Start dnscrypt-proxy
Mar  6 09:45:22 odhcp6c[1309]: Failed to send DHCPV6 message to ff02::1:2 (Cannot assign requested address)
Mar  6 09:45:22 nat: apply nat rules (/tmp/nat_rules_eth0_eth0)
Mar  6 09:45:23 custom_script: Running /jffs/scripts/firewall-start (args: eth0)
Mar  6 09:45:23 wan: finish adding multi routes
Mar  6 09:45:23 dnscrypt-proxy[1317]: dnscrypt-proxy 2.0.6
Mar  6 09:45:23 dnscrypt-proxy[1317]: Now listening to 127.0.0.1:65053 [UDP]
Mar  6 09:45:23 dnscrypt-proxy[1317]: Now listening to 127.0.0.1:65053 [TCP]
Mar  6 09:45:23 dnscrypt-proxy[1317]: [dnscrypt.nl] OK (crypto v1) - rtt: 56ms
Mar  6 09:45:23 dnscrypt-proxy[1317]: [dnscrypt.nl.ipv6] TIMEOUT
Mar  6 09:45:23 dnscrypt-proxy[1317]: Server with the lowest initial latency: dnscrypt.nl (rtt: 56ms)
Mar  6 09:45:23 dnscrypt-proxy[1317]: dnscrypt-proxy is ready - live servers: 1
Mar  6 09:45:23 odhcp6c[1309]: Failed to send DHCPV6 message to ff02::1:2 (Cannot assign requested address)
Mar  6 09:45:24 qos: Applying codel patch
Mar  6 09:45:26 kernel: SHN Release Version: 2.0.1 3529123_patch
Mar  6 09:45:26 kernel: UDB Core Version: 0.2.14 r3529123
Mar  6 09:45:26 kernel: sizeof forward pkt param = 280
Mar  6 09:45:27 WAN_Connection: WAN was restored.
Mar  6 09:45:27 ntp: start NTP update
[...]

After:

Mar  6 09:19:05 haveged: haveged starting up
Mar  6 09:19:05 kernel: Emergency Sync completeIDPfw: Exit IDPfwmod epilog takes 0 jiffiesIDPfw: Exit IDPfwExit chrdev /dev/idpfw with major 191Exit chrdev /dev/detector with major 190br0: port 6(eth6) entered disabled statebr0: port 5(eth5) entered disabled state br0: port 3(eth3) entered disabled statedevice eth1 left promiscuous modebr0: port 1(eth1) entered disabled statedevice eth2 left promiscuous modebr0: port 2(eth2) entered disabled statedevice eth3 left promiscuous modebr0: port3(eth3) entered
Mar  6 09:19:05 kernel: ____________________________________________________________________________
Mar  6 09:19:05 kernel: IGMP Query send failed
Mar  6 09:19:05 kernel: IGMP Query send failed
Mar  6 09:19:06 nat: apply redirect rules
Mar  6 09:19:07 custom_script: Running /jffs/scripts/dnsmasq.postconf (args: /etc/dnsmasq.conf)
Mar  6 09:19:07 RT-AC86U: start httpd:80
Mar  6 09:19:09 disk_monitor: be idle
Mar  6 09:19:09 hour_monitor: daemon is starting
Mar  6 09:19:10 Samba_Server: daemon is started
Mar  6 09:19:11 custom_script: Running /jffs/scripts/services-start
Mar  6 09:19:11 jffs2: valid logs(1)
Mar  6 09:19:14 custom_script: Running /jffs/scripts/wan-start (args: 0)
Mar  6 09:19:14 rc_service: service 973:notify_rc restart_dnsmasq
Mar  6 09:19:14 nat: apply nat rules (/tmp/nat_rules_eth0_eth0)
Mar  6 09:19:14 odhcp6c[968]: Failed to send DHCPV6 message to ff02::1:2 (Cannot assign requested address)
Mar  6 09:19:14 custom_script: Running /jffs/scripts/firewall-start (args: eth0)
Mar  6 09:19:14 wan: finish adding multi routes
Mar  6 09:19:15 odhcp6c[968]: Failed to send DHCPV6 message to ff02::1:2 (Cannot assign requested address)
Mar  6 09:19:15 qos: Applying codel patch
Mar  6 09:19:16 admin: Start dnscrypt-proxy
Mar  6 09:19:16 WAN_Connection: WAN was restored.
Mar  6 09:19:16 ntp: start NTP update
Mar  6 09:19:16 dnscrypt-proxy[1100]: dnscrypt-proxy 2.0.6
Mar  6 09:19:16 dnscrypt-proxy[1100]: Now listening to 127.0.0.1:65053 [UDP]
Mar  6 09:19:16 dnscrypt-proxy[1100]: Now listening to 127.0.0.1:65053 [TCP]
Mar  6 09:19:16 dnscrypt-proxy[1100]: [dnscrypt.nl] OK (crypto v1) - rtt: 55ms
Mar  6 09:28:39 rc_service: ntp 1046:notify_rc restart_upnp
Mar  6 09:28:39 rc_service: waitting "restart_dnsmasq" via  ...
Mar  6 09:28:40 kernel: SHN Release Version: 2.0.1 3529123_patch
Mar  6 09:28:40 kernel: UDB Core Version: 0.2.14 r3529123
Mar  6 09:28:40 kernel: sizeof forward pkt param = 280
Mar  6 09:28:41 dnscrypt-proxy[1100]: [dnscrypt.nl.ipv6] OK (crypto v1) - rtt: 57ms
Mar  6 09:28:41 dnscrypt-proxy[1100]: Server with the lowest initial latency: dnscrypt.nl (rtt: 55ms)
Mar  6 09:28:41 dnscrypt-proxy[1100]: dnscrypt-proxy is ready - live servers: 2
Mar  6 09:28:44 nat: apply nat rules (/tmp/nat_rules_eth0_eth0)
[...]

If you just look at the WAN_Connection: WAN was restored message's time, you can see how before I have to wait almost 2 minutes for the network, and after it's only 11 seconds for a "no dnscrypt network" and 3 seconds more for a "dnscrypt network" (Note that there's a NTP time update right when dnscrypt is starting up at 09:19:16).

And now, again with proxy-dnssec, If you don't use proxy-dnssec in dnsmasq and use dnssec + other dnssec options, you are creating an avoidable overhead. Quoting jedisct1:

[...] If you are using public resolvers, having dnsmasq validate DNSSEC signatures locally is not necessary, but wouldn't be a bad thing.

But again, I believe that it's more important the issue of the slow startup.

Note that if this is an issue that only happens in the RT-AC86U, I suggest testing my changes in other routers to see if there's a difference. In the case that there's no difference when booting other routers, then my changes should be applied to your scripts.

thuantran commented 6 years ago

So what do I think is a good config: Use a DoH, or DNSCrypt server that does DNSSEC validation (e.g. google). That way you don't even need to do validation on dnsmasq or on your client.

This is the same thing as what you quoted jedisct1. My opinion is the same. And according to that opinion, if you understand it correctly, the proxy-dnssec is useless anyway. As it's for validation on clients behind the router.

The modification you can do to the manager script to achieve what you want can be done like this (this is what I did in the early state of this script): https://drive.google.com/open?id=19phusbl9doGR1FBLEwg92psBQ1LlcIgB

Much simpler. I do have other ideas, as I don't like the fact that I need to specifically restart dnsmasq, but it would require more testing, so I don't promise anything. Also have you tried specify only google or cisco as dns server for dnscrypt-proxy and see how it goes?