Recently I was testing some applications in a local kubernetes installation running in minikube, especially the access via an ingress. For this I defined the ingress endpoints using a custom otherwise not existing top level domain to produce names like
application2.foobar. (The list of officially registered TLDs can be found at https://www.iana.org/domains/root/db).
Now in order to access these applications locally with an URL like http://application1.foobar/ I need to make the DNS resolution resolve this address to the IP address of my local minikube instance. This IP address can be retrieved with
which in this sample case returns
Now I could add the following line to my /etc/hosts file (which needs to be edited with sudo):
192.168.99.100 application1.foobar appiicaton2.foobar
but this is no nice solution as every time when a new application is added, the /etc/hosts file must be updated.
So instead I set up a local DNS server (using dnsmasq) which will resolve every call to an address with the
.foobar top level domain to our IP address. Then I reconfigure the local name resolution process of macOS to use this DNS resolver for
.foobar addresses – we want to keep the normal DNS resolution working.
Setting up dnsmasq
I am using MacPorts on my machines, other people prefer homebrew, both have dnsmasq as package available. The first step is the installation:
sudo port install dnsmasq
The next step is to edit the dnsmasq configuration, so that any request for an address in the
.foobar domain ist resolved to our ip address. The macports installation has its configuration file at /opt/local/etc/dnsmasq.conf, this file must be edited with
sudo vi /opt/local/etc/dnsmasq.conf and the following line must be added:
After changing the configuration the dnsmasq service is started with
sudo port load dnsmasq. it can be stopped with the corresponding command
sudo port unload dnsmasq.
Now the local running DNS server will return our IP for any host in the foobar domain:
$ dig application1.foobar @localhost +noall +answer ; <<>> DiG 9.10.6 <<>> application1.foobar @localhost +noall +answer ;; global options: +cmd application1.foobar. 0 IN A 192.168.99.100 $ dig adifferenthost.foobar @localhost +noall +answer ; <<>> DiG 9.10.6 <<>> adifferenthost.foobar @localhost +noall +answer ;; global options: +cmd adifferenthost.foobar. 0 IN A 192.168.99.100 $ dig even.subdomains.are.working.foobar @localhost +noall +answer ; <<>> DiG 9.10.6 <<>> even.subdomains.are.working.foobar @localhost +noall +answer ;; global options: +cmd even.subdomains.are.working.foobar. 0 IN A 192.168.99.100
Configuring the system resolving process
The next step is to reconfigure the nameserver resolution of macOS to use our local running dnsmasq when requests for our
.foobar domain come in. For this we need to add a file named foobar to the /etc/resolver directory (which may not yet exist on your machine) and add the following line:
This can be done with:
sudo mkdir -p /etc/resolver echo "nameserver 127.0.0.1" | sudo tee -a /etc/resolver/foobar
After this you can check that this dns resolver is configured by issuing a
scutil --dns command, the output contains an entry like this:
resolver #19 domain : foobar nameserver : 127.0.0.1 flags : Request A records, Request AAAA records reach : 0x00030002 (Reachable,Local Address,Directly Reachable Address)
or you could do a
$ ping application2.foobar PING application2.foobar (192.168.99.100): 56 data bytes 64 bytes from 192.168.99.100: icmp_seq=0 ttl=64 time=0.559 ms 64 bytes from 192.168.99.100: icmp_seq=1 ttl=64 time=0.472 ms $ ping any.hostname.you.can.think.of.foobar PING any.hostname.you.can.think.of.foobar (192.168.99.100): 56 data bytes 64 bytes from 192.168.99.100: icmp_seq=0 ttl=64 time=1.156 ms 64 bytes from 192.168.99.100: icmp_seq=1 ttl=64 time=0.456 ms