Skip to content
/ tsig Public

Golang library to support additional TSIG methods for DNS queries

License

Notifications You must be signed in to change notification settings

bodgit/tsig

Folders and files

NameName
Last commit message
Last commit date
Jul 29, 2024
Sep 27, 2023
Oct 13, 2023
Sep 27, 2023
Jul 29, 2024
Jan 8, 2021
Sep 27, 2023
Sep 27, 2023
Sep 23, 2023
Jan 19, 2018
Feb 28, 2024
Dec 14, 2024
Dec 14, 2024
Sep 27, 2023
Sep 27, 2023
Sep 27, 2023
Sep 27, 2023
Sep 23, 2023
Sep 27, 2023

Repository files navigation

GitHub release Build Status Coverage Status Go Report Card GoDoc Go version Go version

Additional TSIG methods

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.

⚠️ Windows DNS servers don't accept wildcard resource names in dynamic updates.

Here is an example client, it is necessary that your Kerberos or Active Directory environment is configured and functional:

package main

import (
        "fmt"
        "time"

        "github.com/bodgit/tsig"
        "github.com/bodgit/tsig/gss"
        "github.com/miekg/dns"
)

func main() {
        dnsClient := new(dns.Client)
        dnsClient.Net = "tcp"

        gssClient, err := gss.NewClient(dnsClient)
        if err != nil {
                panic(err)
        }
        defer gssClient.Close()

        host := "ns.example.com:53"

        // Negotiate a context with the chosen server using the
        // current user. See also gssClient.NegotiateContextWithCredentials()
        // and gssClient.NegotiateContextWithKeytab() for alternatives
        keyname, _, err := gssClient.NegotiateContext(host)
        if err != nil {
                panic(err)
        }

        dnsClient.TsigProvider = gssClient

        // 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 := dnsClient.Exchange(msg, host)
        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 = gssClient.DeleteContext(keyname)
        if err != nil {
                panic(err)
        }
}

If you need to deal with both regular TSIG and GSS-TSIG together then this package also exports an HMAC TSIG implementation. To use both together set your client up something like this:

package main

import (
        "github.com/bodgit/tsig"
        "github.com/bodgit/tsig/gss"
        "github.com/miekg/dns"
)

func main() {
        dnsClient := new(dns.Client)
        dnsClient.Net = "tcp"

        // Create HMAC TSIG provider
        hmac := tsig.HMAC{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}

        // Create GSS-TSIG provider
        gssClient, err := gss.NewClient(dnsClient)
        if err != nil {
                panic(err)
        }
        defer gssClient.Close()

        // Configure DNS client with both providers
        dnsClient.TsigProvider = tsig.MultiProvider(hmac, gssClient)

        // Use the DNS client as normal
}