Local dns load balance

Hello everyone,

So I have some systems which works in load balance mode and need to use local DNS to support more IPs pr domain. So that if I add gateway.hostname, I can add it more than once but with different return IPs, so that when query for gateway.hostname it returns one of the IPs. This is possible with almost all DNS, just not pihole.

Is this something you maybe would could add?

Something like below?

While Pi-hole's web UI would only allow you to add a single IPv4 and IPv6 address for a given name, it is possible to edit /etc/hosts or /etc/pihole/custom.list to have Pi-hole create the respective A and AAAA records, e.g. by adding:

10.0.0.100 gateway.hostname
10.0.0.101 gateway.hostname
10.0.0.102 gateway.hostname

If you'd add those to custom.list, they will show up in Pi-hole's UI, even though you can't add them via that UI.
Run pihole restartdns to make Pi-hole reread those files.

There's one notable caveat here:
Documentation for Pi-hole's embedded dnsmasq claims it will only ever create a single reverse lookup PTR record for the first IP address it encounters (so e.g. only nslookup 10.10.10.101 would be reversed to gateway.hostname).

However, in a quick test, I was able to successfully do reverse lookups for all three IPs nevertheless.

Still, if successful reverse lookups are important for your use case, you may want to verify that they actually work as intended.

1 Like

For reverse lookups, you can also finetune with below directive:

pi@ph5b:~ $ man dnsmasq
[..]
       --ptr-record=<name>[,<target>]
              Return a PTR DNS record.

Seems like this is what I need, as long it's not the same IP returned every time, doesn't need to be totally every time, but a bit random is what I need.

Any DNS server will always return all known records for a DNS request.
For the given example, a client's A record request for gateway.hostname will always result in the full set of known IPs being returned every time.:

click for example
:~$ dig gateway.hostname

; <<>> DiG 9.11.5-P4-5.1+deb10u6-Debian <<>> gateway.hostname
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23245
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;gateway.hostname.              IN      A

;; ANSWER SECTION:
gateway.hostname.       60      IN      A       10.10.10.101
gateway.hostname.       60      IN      A       10.10.10.102
gateway.hostname.       60      IN      A       10.10.10.100

;; Query time: 1 msec
;; SERVER: 192.168.0.28#53(192.168.0.28)
;; WHEN: Wed Mar 02 08:16:05 CET 2022
;; MSG SIZE  rcvd: 93

A client is then free to make use of any of those IP addresses - by the books, a client should pick an address randomly. But most client implementations just settled for using the first record returned, so it would be the first IP address that would take the brunt of requests.
Hence, DNS server software started to shuffle address records, in an attempt to distribute load over multiple targets (and Pi-hole will do so as well).

Note however, that this at the most would amount to a very crude load balancing approach.
DNS record shuffling cannot take into account neither client nor server related information, e.g. a client may require to communicate with the exact same server over a prolongued period as the server keeps state of the communication (like knowing your shopping cart contents), and switching to another one may break the existing session, or the server at the first IP address handed out already is at 100% load.

A DNS server is not and cannot be aware of any of those potentially influential client-side and server-side parameters.

Depending on your servers usage scenario, you should probably consider deploying dedicated load balancing software that can be made aware of at least a few of those parameters (e.g. with support for sticky sessions).

1 Like

Thank you for your input. I do know how DNS, load balancing and such works and normally I would use dedicated load balance system, but since this is for a internal IRC server, where the building I live in can join and there is running 2 of them which are linked, so in this case, normal DNS is enough.

Before I used local host in pihole I used cloudflare which shuffles which IP is returned first and that is enough for some things. Ofc not for stricky and most that you mention, but that's not my case atm, just need the first IP returned to be shuffled. It seems however that Pihole does not do this, it's the same order of returned IPs every time.

I guess I'll have to take a look at the FTL code, to see if I can change this myself.

According to my /var/log/pihole.log, Pi-hole does shuffle the order of its answers:

Mar  2 08:16:05 dnsmasq[2494]: 4811 192.168.0.28/55740 query[A] gateway.hostname from 192.168.0.28
Mar  2 08:16:05 dnsmasq[2494]: 4811 192.168.0.28/55740 /etc/pihole/custom.list gateway.hostname is 10.10.10.101
Mar  2 08:16:05 dnsmasq[2494]: 4811 192.168.0.28/55740 /etc/pihole/custom.list gateway.hostname is 10.10.10.102
Mar  2 08:16:05 dnsmasq[2494]: 4811 192.168.0.28/55740 /etc/pihole/custom.list gateway.hostname is 10.10.10.100
Mar  2 08:16:19 dnsmasq[2494]: 4819 fd08:::cde/51125 query[A] gateway.hostname from fd08::cde
Mar  2 08:16:19 dnsmasq[2494]: 4819 fd08::cde/51125 /etc/pihole/custom.list gateway.hostname is 10.10.10.102
Mar  2 08:16:19 dnsmasq[2494]: 4819 fd08::cde/51125 /etc/pihole/custom.list gateway.hostname is 10.10.10.100
Mar  2 08:16:19 dnsmasq[2494]: 4819 fd08::cde/51125 /etc/pihole/custom.list gateway.hostname is 10.10.10.101

This is also reflected in the results as returned by dig or nslookup: For me, they return a different ordered set of the same IPs upon each repeated request.

Okay, I haven't been able to get it to return different order, it's the same every time, but I will do some more testing.

I clean both my PCs DNS cache and pihole cache, to make sure it doesn't just return cached result.

Tailing the logs as well now to see first hand, but it's the same order every run. Will report back later if it has changed.

The logs should still have your lookups.
You should be able to retrieve them, e.g. by

grep gateway.hostname /var/log/pihole.log*
root@grandpa:~# tail -f /var/log/pihole.log  | grep "/etc/pihole/custom.list gateway.hostname"
Mar  2 10:58:32 dnsmasq[30940]: /etc/pihole/custom.list gateway.hostname is 10.0.0.140
Mar  2 10:58:32 dnsmasq[30940]: /etc/pihole/custom.list gateway.hostname is 10.0.0.130
Mar  2 10:58:46 dnsmasq[30940]: /etc/pihole/custom.list gateway.hostname is 10.0.0.140
Mar  2 10:58:46 dnsmasq[30940]: /etc/pihole/custom.list gateway.hostname is 10.0.0.130
Mar  2 10:59:02 dnsmasq[30940]: /etc/pihole/custom.list gateway.hostname is 10.0.0.140
Mar  2 10:59:02 dnsmasq[30940]: /etc/pihole/custom.list gateway.hostname is 10.0.0.130
Mar  2 10:59:56 dnsmasq[30940]: /etc/pihole/custom.list gateway.hostname is 10.0.0.140
Mar  2 10:59:56 dnsmasq[30940]: /etc/pihole/custom.list gateway.hostname is 10.0.0.130
tail: /var/log/pihole.log: file truncated
Mar  2 11:00:30 dnsmasq[3993]: /etc/pihole/custom.list gateway.hostname is 10.0.0.140
Mar  2 11:00:30 dnsmasq[3993]: /etc/pihole/custom.list gateway.hostname is 10.0.0.130
Mar  2 11:01:13 dnsmasq[3993]: /etc/pihole/custom.list gateway.hostname is 10.0.0.140
Mar  2 11:01:13 dnsmasq[3993]: /etc/pihole/custom.list gateway.hostname is 10.0.0.130
Mar  2 11:02:05 dnsmasq[3993]: /etc/pihole/custom.list gateway.hostname is 10.0.0.140
Mar  2 11:02:05 dnsmasq[3993]: /etc/pihole/custom.list gateway.hostname is 10.0.0.130

As you can see, same order every time, I do flush and clear caches before every run

Clearing caches should not be necessary nor involved here.
The contents of pihole.log shows how your Pi-hole reacts to those requests, and I find it unusual to see it replying the same order.

You could upload a debug log for me to see if I can spot anything in your configuration that may cause that divergence.

To that end, please upload a debug log and post just the token URL that is generated after the log is uploaded by running the following command from the Pi-hole host terminal:

pihole -d

or do it through the Web interface:

Tools > Generate Debug Log

1 Like

0FWtMnra

There is nothing in your debug log that would contribute towards your observation.

You even seem to run the exact same version of `pihole-FTL` as me, i.e. the same armv7hf binary.
   [2022-03-02 11:00:17.032 3991M] FTL branch: master
   [2022-03-02 11:00:17.033 3991M] FTL version: v5.14
   [2022-03-02 11:00:17.033 3991M] FTL commit: 52e6b95
   [2022-03-02 11:00:17.033 3991M] FTL date: 2022-02-12 19:58:34 +0000
   [2022-03-02 11:00:17.033 3991M] FTL user: pihole
   [2022-03-02 11:00:17.033 3991M] Compiled for armv7hf (compiled on CI) using arm-linux-gnueabihf-gcc (Debian 6.3.0-18) 6.3.0 20170516

I've tried to recreate your configuration by switching on my Pi-hole's DHCP server and applying your custom pihole-FTL.conf, and still, Pi-hole reliably provided the two IP addresses in alternating order for each of my successive nslookups.

I've run dry on ideas why it isn't on your system. :frowning:

1 Like

At least you've tried, so thanks for that mate :slight_smile:

I've noticed in my query log that when I try to lookup the local domain, like gateway.hostname, then there is 2 different lookups in the logs, 1 for gateway.hostname and 1 for gateway.hostname.hostname.
Can that cause it?

Edit: The right lookup does return the IPs, but the hostname.hostname returens NXDOMAIN

nslookup ads the local configured search/suffix domain to the query if you dont anchor the query with a dot "." at the end eg:

nslookup pi-hole.net.

For my Pi-hole host, that is below one:

pi@ph5a:~ $ dnsdomainname
home.dehakkelaar.nl

And configured here:

pi@ph5a:~ $ tail /etc/dhcpcd.conf
[..]
interface eth0
  static ip_address=10.0.0.2/24
  static routers=10.0.0.1
  static domain_name=home.dehakkelaar.nl
  static domain_name_servers=10.0.0.1

For your DHCP clients, it will be the one advertised via DHCP:

pi@ph5a:~ $ pihole-FTL dhcp-discover
Scanning all your interfaces for DHCP servers
[..]
   domain-name: "home.dehakkelaar.nl"
C:\>nslookup avr
Server:  ph5a.home.dehakkelaar.nl
Address:  10.0.0.2

Name:    avr.home.dehakkelaar.nl
Address:  10.0.0.9
pi@ph5a:~ $ pihole -t
[..]
Mar  3 16:35:29: query[A] avr.home.dehakkelaar.nl from 10.0.0.11
Mar  3 16:35:29: DHCP avr.home.dehakkelaar.nl is 10.0.0.9
Mar  3 16:35:29: query[AAAA] avr.home.dehakkelaar.nl from 10.0.0.11
Mar  3 16:35:29: config avr.home.dehakkelaar.nl is NODATA-IPv6

I currently only use host.hostname, would it be better to use host.hostname.tld?

What do you mean by "use host.hostname"?
Can you show output from the prompt?

Configure the domain suffix discovered with pihole-FTL dhcp-discover if unsure.

I saw that your local host, is home.dehakkelaar.nl, which is host.hostname.tld, I don't use the last tld for my hosts, mine is like, router.myroute and not router.myroute.nl

root@grandpa:/home/pi# pihole-FTL dhcp-discover
Scanning all your interfaces for DHCP servers
Timeout: 10 seconds

* Received 300 bytes from eth0:10.0.0.150
  Offered IP address: 10.0.0.244
  Server IP address: 10.0.0.150
  Relay-agent IP address: N/A
  BOOTP server: (empty)
  BOOTP file: (empty)
  DHCP options:
   Message type: DHCPOFFER (2)
   server-identifier: 10.0.0.150
   lease-time: 86400 ( 1d )
   renewal-time: 43200 ( 12h )
   rebinding-time: 75600 ( 21h )
   netmask: 255.255.255.0
   broadcast: 10.0.0.255
   dns-server: 10.0.0.150
   domain-name: "myroute"
   router: 10.0.0.1
   --- end of options ---

DHCP packets received on interface eth0: 1
DHCP packets received on interface wlan0: 0
DHCP packets received on interface lo: 0
root@grandpa:/home/pi#

No.

Note that it is quite common that nslookup would send additional queries by appending the local search domain. Furthermore, that search domain or local domain or Pi-hole domain name effectively is a TLD, even if a private one.

That wouldn't make any difference for your issue.
From a DNS perspective, those are different domains, separate from the ones you expect IP addresses to be shuffled for.