Go DNS package
Go DNS is a package that implements a DNS interface in Go.
This library takes a new, innovative and enterprise ready
approach sends and receives queries to and from the DNS.
It is licensed under the same license as the official Go code, as
this is a fork of that code.
The aim is to be powerful, simple and fast.
Supported:
- All RR types;
- Synchronous and asynchronous queries and replies;
- DNSSEC: validation, signing, key generation, reading
.private
key files - (Fast) sending/receiving/printing packets, RRs;
- Full control over what is being send;
- Zone transfers, EDNS0, TSIG, NSID;
- Server side programming (a full blown nameserver).
- (Fast) reading zones/RRs from files/strings.
Code⌗
The git repository is hosted on github.
Examples using this library can be found in exdns repository over at github.
Tutorials and more info.⌗
Printing MX records⌗
A small peek in to how to print MX records with Go DNS.
We want to create a little program that prints out the MX records of domains, like so:
% mx miek.nl
miek.nl. 86400 IN MX 10 elektron.atoom.net.
Or
% mx microsoft.com
microsoft.com. 3600 IN MX 10 mail.messaging.microsoft.com.
First the normal header of a Go program, with a bunch of imports. We need the dns
package:
package main
import (
"github.com/miekg/dns"
"os"
"net"
"fmt"
"log"
)
Next we need to get the local nameserver to use:
config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
Then we create a dns.Client
to perform the queries for us. In Go:
c := new(dns.Client)
We skip some error handling and assume a zone name is given. So we prepare our question. For that to work, we need:
- a new packet (
dns.Msg
); - setting some header bits;
- define a question section;
- fill out the question section:
os.Args[1]
contains the zone name.
Which translates into:
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeMX)
m.RecursionDesired = true
Then we need to finally ‘ask’ the question. We
do this by calling the Exchange()
function. The unused return value
is the rtt
(round trip time).
r, _, err := c.Exchange(m, net.JoinHostPort(config.Servers[0], config.Port))
Check if we got something sane. The following code snippet prints the answer section of the received packet:
Bail out on an error:
if r == nil {
log.Fatalf("*** error: %s", err)
}
if r.Rcode != dns.RcodeSuccess {
log.Fatalf(" *** invalid answer name %s after MX query for %s", os.Args[1], os.Args[1])
}
// Stuff must be in the answer section
for _, a := range r.Answer {
fmt.Printf("%v\n", a)
}
And we are done.
Full Source⌗
package main
import (
"github.com/miekg/dns"
"net"
"os"
"log"
"fmt"
)
func main() {
config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
c := new(dns.Client)
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeMX)
m.RecursionDesired = true
r, _, err := c.Exchange(m, net.JoinHostPort(config.Servers[0], config.Port))
if r == nil {
log.Fatalf("*** error: %s", err)
}
if r.Rcode != dns.RcodeSuccess {
log.Fatalf(" *** invalid answer name %s after MX query for %s", os.Args[1], os.Args[1])
}
// Stuff must be in the answer section
for _, a := range r.Answer {
fmt.Printf("%v\n", a)
}
}