1 - Introduction

Gallium Data can act as a programmable proxy for DNS and change how DNS works.

In this tutorial, you will:

  • start Gallium Data

  • look up a name in DNS and see how Gallium Data acts as a proxy

  • intercept a specific DNS request and respond to it

  • intercept a DNS response and modify it


This tutorial typically takes about 15 minutes.

2 - Requirements

To run this tutorial, you just need to have Docker up and running.

To verify that Docker is indeed available,

⇨ Run the following command from a command line:

docker version

Note: on Linux, you may need to run all Docker commands as root, e.g.:

sudo docker version

You should see some output similar to this:

Client: Docker Engine - Community
Cloud integration 1.0.14
Version: 20.10.6
API version: 1.41
etc...

The exact version numbers are not important -- the important thing is that Docker needs to be running. If you get an error message, you'll need to get Docker up and running before you can continue with this tutorial. Fortunately, there are lots of resources that can help you with that.

If you get an error message, such as:

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

the most likely explanation is that Docker is not running -- you'll need to start it and try again.

3 - Start Gallium Data

To start Gallium Data,

Run the following command:

docker run --name gallium-data -p 53:53/udp -p 8089:8080 -e repository_location=/galliumdata/repo_dns galliumdata/gallium-data-engine:1.2.1-1028

This command does not return -- that's on purpose: it will allow you to see the log messages coming out of Gallium Data.

If this is your first time running this tutorial, you'll get some messages indicating that Docker is downloading and installing the Gallium Data image.

Once that's done, you should see output similar to:

[INFO core Sys] 13:53:28.311 [main-1] - Gallium Data v.X.X.X (build XXX) is now starting

[INFO core Sys] 13:53:30.026 [main-1] - Gallium Data is now running

If you don't see this, that means there's a problem, but thankfully we have a troubleshooting section coming up next.

Troubleshooting (expand if needed)

Most problems are caused by the DNS port being already in use.

Windows

If you're running Windows Server, you may get an error similar to:

Exception in thread "main" java.lang.RuntimeException: java.net.BindException: Address already in use

In that case, you'll need to stop the DNS service before you can start Gallium Data. You can do so from the command line with:

net stop dns

There are other options if you prefer not to use the command line.

Once you've done this, run this command before attempting to run Gallium Data again:

docker rm gallium-data-dns

then try to run Gallium Data again.

When you're done with this tutorial, you can restart the normal DNS service with:

net start dns

Note that the firewall can also cause problems on Windows -- you may need to open port 53 (UDP) for this tutorial.


Mac

If you get an error message similar to:

Exception in thread "main" java.lang.RuntimeException: java.net.BindException: Address already in use

it means that you are already running a DNS server on your machine. Only one service can use the standard DNS port (53) at the same time. You'll need stop the DNS server before continuing, then run

docker rm gallium-data-dns

then try to run Gallium Data again.


Linux

If you are running on Linux, and you get a message like:

Error starting userland proxy: listen udp4 0.0.0.0:53: bind: address already in use.

it means that you are already running a DNS server on your machine, and you need to stop it. The exact mechanism to do this depends on your exact flavor of Linux. On Ubuntu, you should be able to run the command:

sudo systemctl stop systemd-resolved

Then clean up the Docker container with:

docker rm gallium-data-dns

and try to start Gallium Data again.

If you're having problems while Gallium Data is running, due to name resolution errors, you may need to set your default name server to 127.0.0.1 while doing this tutorial. This is often done by editing /etc/resolv.conf, but Linux distributions vary.

When you're done with this tutorial, remember to restart the normal DNS service.

At this point, you are running Gallium Data as a DNS proxy on your machine. The proxy is using the public Google DNS server at IP address 8.8.8.8 (thanks, Google!).

You may see DNS messages in the terminal in which you started Gallium Data right away: if you do, they indicate that some programs on your computer are already accessing this DNS service. We'll look at these messages in a minute.

4 - Look up a name using nslookup

⇨ In a separate terminal window, run the following commands (what you type is in bold, the response is not):

nslookup

> server 127.0.0.1

Default server: 127.0.0.1

Address: 127.0.0.1#53

> www.galliumdata.com

Server: 127.0.0.1

Address: 127.0.0.1#53


Non-authoritative answer:

www.galliumdata.com canonical name = ghs.googlehosted.com.

Name: ghs.googlehosted.com

Address: 216.58.194.179 [note: you may see a different address, that's normal]


This is doing a basic lookup for the network address corresponding to the name www.galliumdata.com. We've asked to use the DNS server at127.0.0.1 (which is localhost) so that nslookup does all lookups through Gallium Data.

Leave this terminal open, we'll need it again.

Note that you can use any DNS client -- we're using nslookup because it's widely available, but dig or any other tool would work just as well.

DNS log messages

⇨ Look at the terminal in which you started Gallium Data.

You should see DNS requests and responses, perhaps more than a few, depending on your setup.

Let's look at an example -- the messages you see may not be exactly the same.

DNS REQUEST: 21-05-31 16:47:52.113 [/192.168.188.2] Tx: 1943, q:true, ...

Q - type: A - name: www.galliumdata.com

DNS RESPONSE: 21-05-31 16:47:52.127 [/192.168.188.2] Tx: 1943, q:false, ...

Q - type: A - name: www.galliumdata.com

A - type CNAME - name www.galliumdata.com alias: ghs.googlehosted.com

A - type A - name ghs.googlehosted.com address: /216.58.194.179

The first message (first two lines) shows a DNS request This is a request of type A, which asks for the IP4 address for server www.galliumdata.com.

The second message (last four lines) shows a DNS response containing the original question (prefixed with Q) and two answers (prefixed with A) to that question.

The first answer is of type CNAME -- the DNS server is telling us that the "real" name for this server is actually ghs.googlehosted.com -- that's because Gallium Data's web site is indeed hosted by Google.

The second answer is of type A, and it contains the IP4 address to use to reach that server.

5 - Changing DNS requests

Now that we've seen Gallium Data can proxy and log DNS traffic, let's have some fun and actually change that traffic.

Let's say we've decided that all lookups of the evil.com domain should be rejected. We can easily do this with a request filter in Gallium Data.

A ⇨ Browse to http://localhost:8089

B Log in

C Click the project named Simple demo - DNS

D Expand the Request filters section if it's not already expanded

E ⇨ Click the request filter named Reject evil requests

You'll see some parameters that are set up so that this filter will only get invoked for requests of type A (IP4 address lookup) and AAAA (IP6 address lookup), and only for names that end with ".evil.com".

F ⇨ Select the Code tab

You'll see a bit of JavaScript code that transforms the request into a response, gives it an answer that points back to the caller, and adds a stern message for good measure.

G Activate this filter by selecting the Active checkbox

H Publish this change to Gallium Data clicking the Publish button (top)

Now let's see the result of this change.

I Go back to your nslookup terminal

J Enter: www.evil.com and hit enter

You should see something more or less like:

Server: 127.0.0.1

Address: 127.0.0.1#53


Name: www.evil.com

Address: 127.0.0.1

www.evil.com text = "Not today, evil-doer!" [you may not see this line on Windows]


As you can see, Gallium Data allows you to intercept DNS requests, change them, and even turn them around. You have complete access to the packet and can do anything you want with it. In the real world, you might change the address to point to a page explaining that this domain is blocked, for instance.

6 - Changing DNS responses

This time, we're going to hide some email servers.

A ⇨ Go back to your nslookup terminal

B ⇨ Type the commands in bold:

> set type=MX

> galliumdata.com

Server: 127.0.0.1

Address: 127.0.0.1#53


Non-authoritative answer:

galliumdata.com mail exchanger = 1 aspmx.l.google.com.

galliumdata.com mail exchanger = 10 alt3.aspmx.l.google.com.

galliumdata.com mail exchanger = 10 alt4.aspmx.l.google.com.

galliumdata.com mail exchanger = 5 alt1.aspmx.l.google.com.

galliumdata.com mail exchanger = 5 alt2.aspmx.l.google.com.


Authoritative answers can be found from: [you may not see this line on Windows]

These are all the servers that can accept email for the galliumdata.com domain.

We're going to hide some of the servers -- let's say the ones with a priority of 10.

C ⇨ Go back to the Gallium Data browser window

D ⇨ Go back to the project named Simple demo - DNS using the crumb trail at the top

E Expand the Response filters section if it's not already expanded

F ⇨ Click the response filter named Hide some email servers

You'll see some parameters that restrict this filter to only MX (email) packet types for the name galliumdata.com.

G ⇨ Select the Code tab

You'll see some JavaScript code that changes the response to be authoritative (just for fun), and removes any answers with a preference (a.k.a. priority) of 10 or above.

H ⇨ Activate this filter by selecting the Active checkbox

I Publish this change to Gallium Data clicking the Publish button (top)

Now let's see the result of this change.

J Go back to your nslookup terminal

K ⇨ Type the command in bold:

> galliumdata.com

Server: 127.0.0.1

Address: 127.0.0.1#53


galliumdata.com mail exchanger = 1 aspmx.l.google.com.

galliumdata.com mail exchanger = 5 alt1.aspmx.l.google.com.

galliumdata.com mail exchanger = 5 alt2.aspmx.l.google.com.

Our filter has removed two servers from the response, and because we've changed the response to be authoritative, we no longer see the message Authoritative answers can be found from:

Again, Gallium Data gives you complete control over the DNS response -- you can change it, you can add to it or remove from it, you can even drop it altogether.

7 - Use Gallium Data as your default name server

So far, you may have seen only a few DNS queries and responses -- specifically the ones we ran using nslookup. If you're in the mood, you can go one step further and expose all name lookups on your machine.

In order to see all DNS interactions on your machine, you need to set the default name server to point to your Gallium Data service. This is done very differently depending on your platform, but the goal is to have 127.0.0.1 be the main name server, so that all name resolution is done through Gallium Data.

Attention VPN users: you'll need to temporarily disable your VPN for this to work.

Windows

On Windows, the exact details depend on which version of Windows you are using, but generally speaking, you'll want to open the Settings, select Network & Internet (or something close), and change the adapter options for your main network connection to set the DNS server to 127.0.0.1. You may have to do this twice, once for IP4 and once for IP6.

Important: when you are finished with this tutorial, don't forget to go back and reset things to what they were before.

Mac

A ⇨ Open the System Preferences

B ⇨ Open the Network panel

C ⇨ Click on the Advanced... button

D ⇨ Select the DNS tab

E ⇨ Add a new DNS server with the + button

F ⇨ Give it an address of 127.0.0.1

G ⇨ Click OK

H ⇨ Click Apply

Important: when you are finished with this tutorial, don't forget to remove that DNS server (using the minus button) so that name resolution goes back to normal.

Linux

On most Linux platforms, you have to stop the standard name service to get Gallium Data to start up properly. That means that the default name server is already the local machine, and therefore you shouldn't have to change anything in most cases. If that's not the case, there are lots of pages that can help you figure it out.


On some Linux versions, you may need to edit the file /etc/resolv.conf to set your nameserver to 127.0.0.1


Important: when you are finished with this tutorial, don't forget to undo whatever changes you had to make so that name resolution goes back to normal.

When you're done

If you have more than one name server, make sure that 127.0.0.1 is the first one in the list.

You should almost immediately see requests and responses scrolling by in the Gallium Data terminal window.

Windows users: make sure you have not selected some text in the Gallium Data terminal window, as that can block scrolling -- hit Esc to unblock.

If you do not see requests and responses scrolling by, the most common reason is that you're running a VPN -- try turning it off for now.

If you were successful in setting Gallium Data as your default name server, you will typically see flurries of messages in the Gallium Data terminal window. These are all the name lookups that are done by various applications and services running on your machine. It can be instructive to see how much is really going on behind your back, including lookups for names that you might not expect. The main lesson to draw from this is that everyone is spying on you.

You might be interested at this point to visit your usual web sites (hint: use a private browsing window to avoid caching) and get a sense of what they're doing behind your back.

8 - Conclusion

In just a few minutes, you have taken control of DNS on your machine, and you've seen how you can easily modify how DNS behaves.

This is only an example of the power of Gallium Data. You can get the same power with the databases currently supported (Postgres, Mongo, MySQL and SQL Server) and change requests and responses to anything desired.

9 - Next steps

You should feel free to experiment at this point. Here are a few exercises that you may find interesting.


Blocking advertising sites

If you visit an advertising-rich page like cnn.com, you'll see that it looks up a lot of names like c.amazon-adsystem.com and amplify.outbrain.com. It's easy to block these domains with a request filter that simply drops these requests. The demo repository contains a sample request filter called Block ads. If you activate it (and publish), try looking up the names it blocks (see the filter's parameters) and see how the response never comes.

There is actually an easier way to do this, which is to use a request filter of type Address lookup filter - DNS to do the same thing. It's not as flexible, but it requires no code.


Redirecting requests

Depending on your machine, you may notice some strange DNS requests going by, such as:

DNS REQUEST: 21-05-26 16:21:55.965 [/0:0:0:0:0:0:0:1] Tx: 4708, ...

Q - type: PTR - name: 69.1.168.192.in-addr.arpa

DNS RESPONSE: 21-05-26 16:21:55.971 [/0:0:0:0:0:0:0:1] Tx: 4708, code:Name error

These are reverse lookups -- someone is asking DNS for the name corresponding to the given address (which is written in reverse, with in-addr.arpa at the end).

This is failing because, of course, there is no way for the Google DNS service to know the name of your machine on your network. Google therefore returns a Name error code, indicating that it doesn't know what to do with this request.

There is an easy way to resolve this, explained in the Redirecting requests page.


Service discovery

Certain DNS queries are special, and you may see them at regular intervals. They look something like:

DNS REQUEST: 21-05-26 17:14:15.426 [/0:0:0:0:0:0:0:1] ... code:OK

Q - type: PTR - name: lb._dns-sd._udp.0.1.168.192.in-addr.arpa

DNS RESPONSE: 21-05-26 17:14:15.463 [/0:0:0:0:0:0:0:1] ... code:Name error

Note the unusual name being looked up: lb._dns-sd._udp.0.1.168.192.in-addr.arpa

This is a DNS service discovery lookup. There are many types of services that can be looked up using this mechanism, and most of these calls are expected to fail. They are often issued every few minutes to see if a new service has become available on the network, like a printer, a scanner or a web service. For the full specs on this, see the RFC.

Think of the possibilities... You can respond to these queries yourself, or redirect them, or alter the responses on the fly, and really change how your systems work.

Cleanup

Before you clean everything up -- if you've made any changes you want to keep, the simplest thing to do is to download the repository in the Gallium Data admin app using the hamburger menu.

To stop and remove the Gallium Data Docker instance, you can hit ctrl-c in the terminal running Gallium Data, and execute the commands:

docker stop gallium-data

docker rm gallium-data

Important: if you made changes to your machine to use Gallium Data as your main name server, this would be a good time to undo those changes.


If you also want to get rid of the Gallium Data Docker image, you can run:

docker rmi galliumdata/gallium-data-engine:1.2.1-1028