Skip to content
Snippets Groups Projects
Massimiliano Adamo's avatar
Max Adamo authored
d1e1794d
History
Name Last commit Last update
.gitignore
README.md
go.mod
go.sum
main.go

dns-checker

Table of contents

  1. Preamble
  2. Compiling the program
  3. Keepalived and LVS
  4. Available options
  5. Setting up systemd

Preamble

What problems this application tries to solve? UDP can't be easily checked. This application checks the local DNS and optionally Consul DNS and serves the status through a Web page.

I use it in conjunction with LVS and my understanding is that LVS does not allow to run multiple instances of the same check. For instance, LVS has a DNS_CHECK statement, but in my case I need to run it multiple times, to check either the DNS and Consul DNS.

This application runs as a daemon on the same machine where the DNS is running and it can be used in conjunction with your UDP load-balancer to check the status of your DNS.

You can also use it from Nagios, Sensu and issue a simple HTTP check.

Compiling the program

You can install GO and copy/paste the followings:

git checkout main
git pull
LATEST_TAG=$(git describe --tags $(git rev-list --tags --max-count=1))
PROG_VERSION=${LATEST_TAG:1}
BUILD_TIME=$(date -u '+%Y-%m-%d_%H:%M:%S')
git checkout $LATEST_TAG

go get -ldflags "-s -w -X main.appVersion=${PROG_VERSION} -X main.buildTime=${BUILD_TIME}" .

Keepalived and LVS

For instance, with Keepalived + LVS I am using a configuration as follows:

HTTP_GET {
  connect_port 10053
  connect_timeout 3
  delay_before_retry 1
  http_protocol 1.1
  nb_get_retry 2
  url {
    digest 6d3bcaba1fff8c5a461669b409c1a6d2
    path /ipv4
  }
}

the digest is calculated using this command (genhash belongs to keepalived package):

genhash -s 127.0.0.1 -p 10053 -u /ipv4

And if you receive a 200 status code, you'll get the same digest as mine, because the digest is computed against the small HTML snippet embedded in the main.go.

You could also use the HTTP status code: man keepalived.conf and search for status_code.

Available options

You can check the options as follows:

$ dns-checker --help
DNS Checker:
  - checks DNS and optionally Consul and report the status on a Web page
  
Usage:
  dns-checker [--listen-address=LISTENADDRESS] [--listen-port=LISTENPORT] [--verbose]
  dns-checker -h | --help
  dns-checker -b | --build
  dns-checker -v | --version
  
Options:
  -h --help                         Show this screen
  -b --build                        Print version and build information and exit
  -v --version                      Print version information and exit
  --listen-address=LISTENADDRESS    Web server address. Check Go net/http documentation [default: any]
  --listen-port=LISTENPORT          Web server port [default: 8000]
  --verbose                         Log also successful connections

Once it is installed you can check the status using curl (with curl -I you get the status code):

curl http://localhost:8000/sectigo_ev/index.html

Setting up systemd

In this case I am also checking Consul, and I check the existance of one local record called dumb-record.dumb.zone in the DNS and one record called consul.service.domain.org in Consul.

It is not sensible to check for a record on a forwarded zone, because there can be a problem elsewhere (in the network, or in he SOA of the other domain) and we don't want to bring our DNS down if something else is broken.

In this case I run it as unbound user because I use unbound:

#
# Start ACME web service on port 8000
#
[Unit]
Description=ACME Web service written in Go
Wants=basic.target
After=basic.target network.target

[Service]
User=root
Group=root
ExecStart=/usr/bin/acme-web
Restart=on-failure
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=acme-web

[Install]
WantedBy=multi-user.target