DHCP+DNS on two interfaces, ad-blocking only one

Hi, I'd like to set up pihole as the DHCP and DNS server for my whole LAN (several connected subnets), but I only want ad-blocking on one of the networks. I realize that I could transparently redirect DNS queries from the non-blocked network to the upstream DNS servers, but then clients on that network would not be able to resolve local names accumulated in pihole via dnsmasq.

I considered running one instance of pihole that provides DHCP services and does not block ads, and then another one that does not provide DHCP services and does block ads, forwarding DNS requests to the first pihole. But this strikes me as cumbersome and inefficient.

Is there some way to bypass ad-blocking on DNS queries coming from one interface, while still using pihole's DNS cache? I guess this would entail specifying per-interface blocklists.

I'd appreciate any suggestions on how to do this. Below I describe the system I've been using to achieve something similar and why I want to change it.

Thanks!

Details about my system:
In my current setup I have several VLANs on a Cisco switch, and I bridge them via a multi-NIC linux machine so they function as one broadcast domain. I use netfilter to redirect DNS queries arriving at the bridge to separate pihole instances based on the incoming interface. All other traffic transits the bridge unimpeded. I'm currently using my FiOS router as the site DHCP server and as the DNS server to which the pihole instances forward requests.

This setup allows me to select different flavors of DNS on machines by placing them on different VLANs, while the bridging allows all machines to reside on the same broadcast domain. So everything works fine when a machine moves to a different vlan (it'll get the same IP address,, and can still see broadcast-heavy devices like Sonos speakers, printers, home automation gizmos, etc.).

The downside to this configuration is that all of my traffic has to flow through the linux software bridges to reach the router. I get good throughput, but it does introduce some latency and jitter that affects things like gaming. Hence my desire to bridge the VLANs in hardware. I can do that easily, but then I can no longer transparently redirect DNS requests as described above.

You can use the Group management for that. It allows to specify an group based on subnets and interfaces

Clients may be described either by their IP addresses (IPv4 and IPv6 are supported), IP subnets (CIDR notation, like 192.168.2.0/24 ), their MAC addresses (like 12:34:56:78:9A:BC ), by their hostnames (like localhost ), or by the interface they are connected to (prefaced with a colon, like :eth0 ).

Note that client recognition by IP addresses (incl. subnet ranges) are prefered over MAC address, host name or interface recognition as the two latter will only be available after some time. Furthermore, MAC address recognition only works for devices at most one networking hop away from your Pi-hole.

Create a new group "unfiltered" and assign the desired interface/subnet. That's all you need to do, as long as no adlist is assigned to that group, no filtering will happen.

P.S. You might need to change Pihole's listening behaviour (Settings/DNS) to "All interfaces"

Awesome, thanks! I feel like an idiot for not having realized that. I've been using pihole for years and never even noticed that feature :blush:

The feature was added recently (included in "define clients by MAC")

Well, it seemed promising, but unfortunately does not work for my case. While pihole does initially assign a newly seen client to its proper group based upon its incoming interface, it does not reassign the client to the correct interface-specific group when a request comes from it on a different interface assigned to a different group. Seems the classification system is very much centered on IP address as the distinguishing feature of a client. This probably makes sense for 95% of users, but it does strike me as perhaps not quite what the developers intended?

Thanks, though.

How did you identify the client? By MAC, IP, interface etc?

I created two groups: ":eth2" and ":eth3" for requests arriving on those two interfaces, as described on the "Client group management" page of the web app. When a new request comes in for a never-before-seen client on one of those interfaces, pihole appears to do the right thing. But if I send a request from a client that was first seen on ":eth2" to the listening socket on ":eth3", pihole treats the request as though it arrived on ":eth2".

I verified this using dig on several clients on different subnets to direct queries to specific interfaces. I created more interfaces on the pihole machine in different subnets and sent queries to them, all with the same result: pihole is using the IP address of the client instead of the ingress interface of the request for deciding by which group's rules the query should abide.

Technically, DNS knows IP addresses only.
An IP address is indeed the only available piece of data identifying a client in a DNS request.

Additional information like MACs or interfaces has to be learned separately and completely independently from DNS requests. It also has to be learned asynchronously, so it doesn't impede DNS resolution speed and burden it with the cost of probing and analysing your network.
It is therefore expected that alternative association methods (anything other than IP addresses) may lag in applying the correct association.
The UI mentions this explicitly.

However, your observation is adding yet another level to it:
A roaming device that appears on different interfaces over time would mean that Pi-hole has to relearn an IP address for a new interface while forgetting about the previous one. This is somewhat different than learning another IP for a MAC address, and it may pose a major challenge for client identity associations in historical data (i.e. you'd have a hard time telling what filtering group would have been used for a specific DNS request at the time it was made).

There have been intense and extensive discussion both within the Pi-hole team and within the Pi-hole community, but they have indeed mostly focused on MAC addresses.

Could you confirm that new interfaces for roaming client devices indeed do not get learned over time?

Also, since you are the first user applying interfaces for fltering that I come across, could you explain your actual usage scenario and goals for filtering by interface?
That would help our understanding and maybe allow for finding alternative solutions to still achieve what you want to do if filtering by interface doesn't fit your bill currently.

My usage case is that I have separate VLANs for filtered and unfiltered traffic. These segments are bridged so that they comprise a single broadcast domain. A wireless client can choose between 'blocked' and 'unblocked' SSIDs to specify which VLAN they land in, and wired clients can have interface VLANs reassigned if necessary to the same end.

The goal is to allow switching flavor of DNS without changing the IP address of a client device, and without changing its general disposition within the network.

So if the kids find that adblocking is messing up their school connectivity they can quickly change wifi network without losing their ability to see the printer. Or if a streaming device won't load a youtube video, it can be quickly switched over to the non-blocked VLAN without losing its ability to stream audio to a Sonos speaker, etc.

I realize that much of this could be achieved by enabling and disabling pihole for individual devices via the web app, but it's so much simpler and much more practical to tell everyone: "if ad blocking is messing up your workflow, switch from wireless network A to B".

I mentioned in my original post that I have been doing this successfully with a transparent linux bridge. Clients on the adblock VLAN have to cross the bridge to join the non-adblocked portion of the LAN. In crossing, all DNS requests are intercepted and passed to pihole, which forwards its queries to the FIOS router. Clients on the non-adblocked segment just talk directly to the FIOS router, which also handles all DHCP for the entire network.

The problem with my current approach is that the software bridge induces some unnecessary latency.

One work-around I came up with involves having linux containers to proxy DNS requests from the two different segments of the network, so all clients on network A send DNS requests to machine A, which IP-masquerades the request before passing it to the pihole server. Ditto for B. So pihole only sees two IP addresses making queries: that of machine A and that of B. Ads are blocked for A and not for B. This works fine, but then I don't have any visibility into which clients are making which queries.

I'm not really sure what you mean by interfaces being learned over time. It appears to me that an IP address is assigned to a group based on the first interface it is seen upon, and then does not change after that.

Yes, that was indeed the intent of my question :wink: : to find out whether you saw your clients being filtered for the correct interface after a while when watching them for a longer period.
It seems you haven't, so Pi-hole would stick with the first interface a client shows up through.

I don't know the exact timings for Pi-hole to update its network analysis details, so I'm going to check with the development team.

In the meantime:

How important are those fixed client IP addresses to you?

If you could live with (and configure) changing IPs per VLAN, I'm confident that Pi-hole would be able to apply the filtering in the exact way you envision it.
To still be able to relate to IPs, you could make them match a pattern, e.g. assign 192.168.0.26 on VLAN#1 and 192.168.10.26 on VLAN#2 for the same device.

As an added bonus, those switch in filters would always kick in immediately, as it would be based on DNS-native IP addresses. As mentioned, all other association methods may incur a lag, especially in a dynamically regrouping situation as yours.

I had considered using two separate IP address ranges, but really do prefer to keep the IP addresses static for many of my devices. The solution I'm using right now is to have pihole hand out two DNS server addresses: one for network A and one for B. Network A is ad-blocked and goes to the main pihole address. The other address, for network B, points at a proxy with a fixed IP address that forwards the requests to pihole from its one IP address. I configured pihole not to block ads for that one client.

I don't get query logs for the unblocked network, but I do get them for the blocked network, and that seems most useful anyways.

Thanks for your suggestions and help :slight_smile:

1 Like

When a client (= an IP address) first appears, we query the groups to apply from the database. If we find a matching entry for :eth0 , we'll use the groups associated to this entry. However, we never recheck anything because this isn't expected right now (the same IP appearing on another interface) - mostly because this somehow feels "wrong".

However, I made some changes to (hopefully!) trigger an update of the associated groups on interface change of the same IP. Please add

DEBUG_CLIENTS=true
DEBUG_DATABASE=true

to your /etc/pihole/pihole-FTL.conf (create if it does not exist) and run

pihole checkout ftl new/iface_change_same_IP

to get my proposed solution. The try changing the client between different interfaces and check the log file (/var/log/pihole-FTL.log) for lines like:

Client <ip-address> (<name-if-known>) changed interface: eth0 -> eth1
Initializing gravity statements for <ip-address>

Looks good! Works as expected.

I really appreciate your willingness to make this change, and have made a donation to the project in recognition of your effort.

Cheers :smiley:

1 Like

Thanks for your confirmation, we're bringing out a small Christmas update today, mostly containing bug fixes. Unfortunately, your change cam after our series of tests has already been started but should be included in the next regular update. I'll still update the branch you're currently on so you get the latest version + your special addition right now.

You can follow the progress here

Thanks for the donation! It's much appreciated and helps us to keep the support up, e.g., by giving us some money to buy new boards when users have problems getting Pi-hole running on them.

Merry Christmas! :christmas_tree:

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.