This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Getting Started

Getting Started with dnsmonster

Passive DNS monitoring framework built on Golang. dnsmonster implements a packet sniffer for DNS traffic. It Ability to accept traffic from a pcap file, a live interface or a dnstap socket, and Ability to be used to index and store hundreds of thousands of DNS queries per second as it has shown to be capable of indexing 200k+ DNS queries per second on a commodity computer. It aims to be scalable, simple and easy to use, and help security teams to understand the details about an enterprise’s DNS traffic. dnsmonster doesn’t look to follow DNS conversations, rather it aims to index DNS packets as soon as they come in. It also doesn’t aim to breach the privacy of the end-users, with the ability to mask Layer 3 IPs (IPv4 and IPv6), enabling teams to perform trend analysis on aggregated data without being able to trace back the queries to an individual. Blogpost

Main features

  • Ability to use Linux’s afpacket and zero-copy packet capture.
  • Supports BPF
  • Ability to mask IP address to enhance privacy
  • Ability to have a pre-processing sampling ratio
  • Ability to have a list of “skip” fqdns to avoid writing some domains/suffix/prefix to storage
  • Ability to have a list of “allow” domains, used to log access to certain domains
  • Hot-reload of skip and allow domain files/urls
  • Modular output with configurable logic per output stream.
  • Automatic data retention policy using ClickHouse’s TTL attribute
  • Built-in Grafana dashboard for ClickHouse output.
  • Ability to be shipped as a single, statically linked binary
  • Ability to be configured using environment variables, command line options or configuration file
  • Ability to sample outputs using ClickHouse’s SAMPLE capability
  • Ability to send metrics using prometheus and statstd
  • High compression ratio thanks to ClickHouse’s built-in LZ4 storage
  • Supports DNS Over TCP, Fragmented DNS (udp/tcp) and IPv6
  • Supports dnstrap over Unix socket or TCP
  • built-in SIEM integration with Splunk and Microsoft Sentinel

1 - installation

Learn how to install dnsmonster on your platform using Docker, prebuilt binaries, or compiling it from the source on any platform Go supports

dnsmonster has been built with minimum dependencies. In runtime, the only optional dependency for dnsmonster is libpcap. By building dnsmonster without libpcap, you will lose the ability to set bpf filters on your live packet captures.

installation methods

Prebuilt binaries

Each relase of dnsmonster will ship with two binaries. One for Linux amd64, built statically against an Alpine based image, and one for Windows amd64, which depends on a capture library to be installed on the OS. I’ve tested thw Windows binary with the latest version of Wireshark installed on the system and there was no issues to run the executable.

Prebuilt packages

Per each release, the statically-linked binary mentioned above is also wrapped into deb and rpm packages with no dependencies, making it easy to deploy it in Debian and RHEL based distributions. Note that the packages don’t generate any service files or configuration templates at installation time.

Run as a container

The container build process only generates a Linux amd64 output. Since dnsmonster uses raw packet capture funcationality, Docker/Podman daemon must grant the capability to the container

sudo docker run --rm -it --net=host --cap-add NET_RAW --cap-add NET_ADMIN --name dnsmonster ghcr.io/mosajjal/dnsmonster:latest --devName lo --stdoutOutputType=1

Check out the configuration section to understand the provided command line arguments.

Build from the source

  • with libpcap: Make sure you have go, libpcap-devel and linux-headers packages installed. The name of the packages might differ based on your distribution. After this, simply clone the repository and run go build .
git clone https://github.com/mosajjal/dnsmonster --depth 1 /tmp/dnsmonster 
cd /tmp/dnsmonster
go get
go build -o dnsmonster ./cmd/dnsmonster
  • without libpcap: dnsmonster only uses one function from libpcap, and that’s converting the tcpdump-style filters into BPF bytecode. If you can live with no BPF support, you can build dnsmonster without libpcap. Note that for any other platform, the packet capture falls back to libpcap so it becomes a hard dependency (*BSD, Windows, Darwin)
git clone https://github.com/mosajjal/dnsmonster --depth 1 /tmp/dnsmonster 
cd /tmp/dnsmonster
go get
go build -o dnsmonster -tags nolibpcap ./cmd/dnsmonster

The above build also works on ARMv7 (RPi4) and AArch64.

Build Statically

If you have a copy of libpcap.a, you can build the statically link it to dnsmonster and build it fully statically. In the code below, please change /root/libpcap-1.9.1/libpcap.a to the location of your copy.

git clone https://github.com/mosajjal/dnsmonster --depth 1 /tmp/dnsmonster
cd /tmp/dnsmonster/
go get
go build --ldflags "-L /root/libpcap-1.9.1/libpcap.a -linkmode external -extldflags \"-I/usr/include/libnl3 -lnl-genl-3 -lnl-3 -static\"" -a -o dnsmonster ./cmd/dnsmonster

For more information on how the statically linked binary is created, take a look at Dockerfiles in the root of the repository responsible for generating the published binaries.

2 - post-installation

Set up services and shell completions for dnsmonster

Post-install

After you install dnsmonster, you might need to take a few extra steps to build services so dnsmonster runs automatically on system startup. These steps aren’t included in the installation process by default.

Systemd service

If you’re using a modern and popular distro like Debian, Ubuntu, Fedora, Arch, RHEL, you’re probably using systemd as your init system. To have dnsmonster as a service, created a file in /etc/systemd/system/ named dnsmonster.service, and define your systemd unit there. The name dnsmonster as a service name is totally optional.

cat > /etc/systemd/system/dnsmonster.service << EOF
[Unit]
Description=Dnsmonster Service
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
Restart=always
RestartSec=3
ExecStart=/sbin/dnsmonster --config /etc/dnsmonster.ini

[Install]
WantedBy=multi-user.target

EOF

The above systemd service looks at /etc/dnsmonster.ini as a configuration file. Checkout the configuration section to see how that configuration file is generated.

to start the service and ebable it at boot time, run the following

sudo systemctl enable --now dnsmonster.service

You can also build a systemd service that takes the interface name dynamically and runs the dnsmonster instance per interface. To do so, create a service unit like this:

cat > /etc/systemd/system/[email protected] << EOF
[Unit]
Description=Dnsmonster Service
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
Restart=always
RestartSec=3
ExecStart=/sbin/dnsmonste --devName=%i --config /etc/dnsmonster.ini

[Install]
WantedBy=multi-user.target

EOF

The above unit creates a dynamic systemd service that can be enabled for multiple Interfaces. For example, to run the service for the loopback interface in linux (lo), run the following:

sudo systemctl enable --now [email protected]

Note that the above example only works if you’re not specifying a dnstap or a local pcap file as an input inside the configuration file.

init.d service

bash and fish completion