Support for add-subnet option from dnsmasq (ECS/EDNS0 Client Subnet)

Did a tcpdump on the device hosting pihole for everything on port 53

All request that have been forwarded from the router contain EDNS0 information (subnet+ MAC), except my wireguard client and router's localhost (both only IP/subnet)

Still have to figure out, why my laptop, both on wifi and eth still sends requests directly to pihole ignoring the DNS server address it gets via DHCP.

Bildschirmfoto zu 2020-08-25 19-50-37

Maybe you edited /etc/resolv.conf (or similar) manually or setup something that does this.

Sot he conclusion is that all packets contain the data but FTL is not seeing them every time? This is ... surprising. How about the log in /var/log/pihole-FTL.log? Are there records for **** new UDP/TCP querys without EDNS(0) information?

Bingo!

I totally forgot about it. It was not directly edited but via systemd-resolvd as a workaround to change the DNS server order for my wireguard interface...


No. Conclusion is: Pihole is doing fine. But one client with two interfaces ignored the DHCP DNS settings and were still sending requests directly to pihole instead of the router, which would then had added EDSN0 information.

2 Likes

But why does this client then show up as mock-device? Because it was able to connect to Pi-hole but separated into a VPN caused Pi-hole to see queries from this client once through the router (with MAC added) and one directly (but without visible MAC address)?

That was what I wanted to figure out/reproduce.

WOW, I have waited so long for this option :slight_smile:

I would have liked to solve this with the proxy protocol, but it works for now. Maybe the proxy protocol will be implemented as well.

So far I have tested the following, and Pihole now receives the IP address of the requesting client.

Dns over port 53 (lokal network):
LAN -(port 53)-> dnsdist -(dns,53, docker internal)-> pihole --(dns,53, docker internal)-> unbound

DoH:
Internet -(HTTPS,443)-> Haproxy -(HTTP,80, docker internal)-> dnsdist -(dns,53, docker internal)-> pihole --(dns,53, docker internal)-> unbound

DoT:
Internet —(DoT,853)—> dnsdist —(dns,53, docker internal)—> pihole --(dns,53, docker internal)—> unbound

Changes in dnsdist:
To evaluate the X-Forwarded-For header of haproxy (haproxy -> dnsdist) you have to activate the parameter addDOHLocal(..., trustForwardedForHeader=true).
https://dnsdist.org/reference/config.html?highlight=trustforwardedforheader

For EDNS (dnsdist -> pihole) you have to adjust three global parameters

setECSOverride(true)
setECSSourcePrefixV4(32)
setECSSourcePrefixV6(128)

and activate newServer(..., useClientSubnet=true) for pihole.
https://dnsdist.org/advanced/ecs.html

in Pihole Docker container I did the following:

# docker exec -it dnsrec_pihole_1 bash
root@32302c83e05e:/var/log# pihole checkout ftl new/edns0
  Please note that changing branches severely alters your Pi-hole subsystems
  Features that work on the master branch, may not on a development branch
  This feature is NOT supported unless a Pi-hole developer explicitly asks!
  Have you read and understood this? [y/N] y

  [✓] Branch new/edns0 exists
  [✓] Downloading and Installing FTL
  [✓] Restarting pihole-FTL service...
  [✓] Enabling pihole-FTL service to start on reboot...

QUESTION: how can I activate this permanently in the pihole docker container?

Here my futile efforts for the implementation of the proxy protocol:

2 Likes

I have never heard of it before, neither have I seen a feature request. You should open a new one as it is not directly related to EDNS(0). Please provide some easily-accessible reading for the proxy protocol so we can have a look. However, if it is something outside of DNS, I don't see much of a chance to get this implemented. EDNS(0) has the benefit of being nice and in-place so it was possible to extend our existing DNS service with little effort (we just started processing something we ignored before, not really added an entirely new thing).

Container always starts "fresh". So you changed something in the container and this change is reset on restart. This is expected. I'm not a docker expert, but I seem to remember that you can docker commit any changes into a new container containing your changes (the checkout). If this doesn't work (or you don't know how to do it), then this is certainly another thing for another new discussion outside of the current topic.

I already opened a Feature Request in February (see link in last post), but at that time only the outdated "DNS X-Proxied-For" (XPF) was supported. But with dnsdist 1.5 the support of the "PROXY protocol" was added.

The most exciting new feature is the implementation of the Proxy Protocol between dnsdist and its backends. Aimed to replace the use of EDNS Client Subnet and our own XPF, the Proxy Protocol is an existing standard where a small header is prepended to the query, passing not only the source and destination addresses and ports along to the backend, but also custom values. Support for parsing the Proxy Protocol is already available in the development tree of the PowerDNS Recursor ;

Do this. Any posts on this thread about a different topic will be ignored.

I have just successfully tested the following.

LAN-Client -(port 53)-> pfsense (with dnsmasq) -(port 53)-> dnsdist -(dns,53, docker internal)-> pihole --(dns,53, docker internal)-> unbound

In pfsense I entered the value "add-subnet=32,128" under "Services -> DNS Forwarder ->Custom options".
In dnsdist I had to remove "setECSOverride(true)".

With these settings I can continue to assign the IP address of pfsense (default geatway) as DNS server to my clients. So the DNS resolution of DHCP clients still works and in pihole I still see the client IP address.

Of course you can also do this without dnsdist and forward the DNS forwarder from pfsense directly to pihole.

@christian82 What is dnsdist doing for you in this setup?

A privacy question.
Is it possible to activate the EDNS client subnet extension in Pihole for incoming requests and deactivate (configurable) it for outgoing requests?
I am concerned that now the internal IP addresses of the internal devices are forwarded to the Cloud DNS servers (e.g. Google, Cloudflare, etc.), which is probably not desired by some people for privacy reasons.
(of course you should not use Google and co. at all for privacy reasons, but I wanted to address the topic, because otherwise it might be overlooked)

just to play. I also run my dns-servers in the internet with dnsdist, therefore also in lan.

Yes, it is. Disabled in sending is even the standard configuration.

EDNS(0) data is only sent if explicitly enabled in Pi-hole. EDNS(0) data is always analyzed when received.

edit: To be precise, you have to add the following lines to have dnsmasq send out some relevant information:

Someone knows the formatting to add these lines in config.gateway.json (for my Ubiquiti USG)
I thought it was something as service dns (forwarding?) options

Now my DHCP hands out my 2 pihole's as DNS, but if I wanted to use it with ECS/EDNS0 I will set the upstream DNS of the router to my 2 pihole's and set dhcp back to auto so that my router handles local dns resoluatin. To prevent hard coded dns I had the following lines in my config.gateway.json:

"nat": {
      "rule": {
        "1": {
          "description": "Redirect DNS requests",
          "destination": {
            "port": "53"
          },
          "inbound-interface": "eth1.10",
          "inside-address": {
            "address": "10.10.50.40-10.10.50.41",
            "port": "53"
          },
          "source": {
            "address": "!10.10.50.40-10.10.50.41"
          },
          "log": "disable",
          "protocol": "tcp_udp",
          "type": "destination"
        },
        "2": {
          "description": "Redirect DNS requests",
          "destination": {
            "port": "53"
          },
          "inbound-interface": "eth1.20",
          "inside-address": {
            "address": "10.10.50.40-10.10.50.41",
            "port": "53"
          },
          "source": {
            "address": "!10.10.50.40-10.10.50.41"
          },
          "log": "disable",
          "protocol": "tcp_udp",
          "type": "destination"
        },
        "3": {
          "description": "Redirect DNS requests",
          "destination": {
            "port": "53"
          },
          "inbound-interface": "eth1.30",
          "inside-address": {
            "address": "10.10.50.40-10.10.50.41",
            "port": "53"
          },
          "source": {
            "address": "!10.10.50.40-10.10.50.41"
          },
          "log": "disable",
          "protocol": "tcp_udp",
          "type": "destination"
        },
        "4": {
          "description": "Redirect DNS requests",
          "destination": {
            "port": "53"
          },
          "inbound-interface": "eth1.50",
          "inside-address": {
            "address": "10.10.50.40-10.10.50.41",
            "port": "53"
          },
          "source": {
            "address": "!10.10.50.40-10.10.50.41"
          },
          "log": "disable",
          "protocol": "tcp_udp",
          "type": "destination"
        },
        "5": {
          "description": "Redirect DNS requests",
          "destination": {
            "port": "53"
          },
          "inbound-interface": "eth1.90",
          "inside-address": {
            "address": "10.10.50.40-10.10.50.41",
            "port": "53"
          },
          "source": {
            "address": "!10.10.50.40-10.10.50.41"
          },
          "log": "disable",
          "protocol": "tcp_udp",
          "type": "destination"
        },
        "6000": {
          "description": "MASQ DNS requests to LAN",
          "destination": {
            "address": "10.10.50.40-10.10.50.41",
            "port": "53"
          },
          "log": "disable",
          "outbound-interface": "eth1",
          "protocol": "tcp_udp",
          "type": "masquerade"
        }
      }
    }
  }
}

Will these continue to work? Or will I need to edit them?

This may be relevant for you:

https://community.ui.com/questions/DNSMASQ-in-USG/4eebf6a8-fa27-40dc-b2dd-f6eaa3fd62a9?page=1

Ok thx.
I suppose the add-mac / add-subnet has to be where's in the example "server=..."

Just read through this entire topic - excellent functionality! Thanks @DL6ER and @_FailSafe !

2 minor questions from my side:

  1. This was merged into the dev branch and as such should be in there, correct? (just doublechecking)
  2. Does this require another action (editing a .conf file for instance) to activate or is this 'live' by default?

I'd love to have this functionality available and am looking at the 'sender' to make this available (for reference, I'm running a Firewalla Blue in simple (so not DHCP) mode, and refer to Pi-Hole as DNS server. I've contacted the Firewalla dev team to see if they can provide the required info to Pi-Hole)

1 Like

Yes and live by default :blush:

1 Like

I have a strange issue: I use a router which runs dnsmasq, I enabled add-mac and add-subnet=32. ECS client resolution across subnets works great with pihole. But queries from the router itself are attributed to localhost

Any idea why and how to fix that?

1 Like

This is an interesting side-effect and even expected now that I think of it. What the router does is telling Pi-hole in its ECS data who is the original requestor. When the router does a lookup itself the he says himself (as in 127.0.0.1) is doing the lookup. Interesting and a bit unexpected.

The only solution I have imagine right now is ignoring the ECS data in case it is within 127.0.0.0/8. Any other suggestions?