The github.com/bodgit/tsig package adds support for additional TSIG methods used in DNS queries. It is designed to be used alongside the github.com/miekg/dns package which is used to construct and parse DNS queries and responses.
This is most useful for allowing RFC 3645 GSS-TSIG which is necessary for dealing with Windows DNS servers that require 'Secure only' updates or BIND if it has been configured to use Kerberos.
Here is an example client, it is necessary that your Kerberos or Active Directory environment is configured and functional:
package main
import (
"fmt"
"net"
"time"
"github.com/bodgit/tsig"
c "github.com/bodgit/tsig/client"
"github.com/bodgit/tsig/gss"
"github.com/miekg/dns"
)
func main() {
host := "ns.example.com"
g, err := gss.New()
if err != nil {
panic(err)
}
defer g.Close()
// Negotiate a context with the chosen server using the
// current user. See also g.NegotiateContextWithCredentials()
// and g.NegotiateContextWithKeytab() for alternatives
keyname, _, err := g.NegotiateContext(host)
if err != nil {
panic(err)
}
client := c.Client{}
client.Net = "tcp"
client.TsigAlgorithm = map[string]*c.TsigAlgorithm{
tsig.GSS: {
Generate: g.GenerateGSS,
Verify: g.VerifyGSS,
},
}
client.TsigSecret = map[string]string{*keyname: ""}
// Use the DNS client as normal
msg := new(dns.Msg)
msg.SetUpdate(dns.Fqdn("example.com"))
insert, err := dns.NewRR("test.example.com. 300 A 192.0.2.1")
if err != nil {
panic(err)
}
msg.Insert([]dns.RR{insert})
msg.SetTsig(*keyname, tsig.GSS, 300, time.Now().Unix())
rr, _, err := client.Exchange(msg, net.JoinHostPort(host, "53"))
if err != nil {
panic(err)
}
if rr.Rcode != dns.RcodeSuccess {
fmt.Printf("DNS error: %s (%d)\n", dns.RcodeToString[rr.Rcode], rr.Rcode)
}
// Cleanup the context
err = g.DeleteContext(keyname)
if err != nil {
panic(err)
}
}
Note that it is necessary for the package to ship its own DNS client rather
than use the one provided in the github/com/miekg/dns package as it needs to
permit the additional TSIG algorithms however it behaves mostly the same and
exports the same Exchange()
method so they can be use interchangeably in
code with a suitable interface, (see tsig.Exchanger
for an example).