summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/miekg/dns/doc.go
blob: ceabd24c1061c49d64ceebdc8ed82ef58db024f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
/*
Package dns implements a full featured interface to the Domain Name System.
Server- and client-side programming is supported.
The package allows complete control over what is sent out to the DNS. The package
API follows the less-is-more principle, by presenting a small, clean interface.

The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing.
Note that domain names MUST be fully qualified, before sending them, unqualified
names in a message will result in a packing failure.

Resource records are native types. They are not stored in wire format.
Basic usage pattern for creating a new resource record:

     r := new(dns.MX)
     r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX,
     Class: dns.ClassINET, Ttl: 3600}
     r.Preference = 10
     r.Mx = "mx.miek.nl."

Or directly from a string:

     mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.")

Or when the default origin (.) and TTL (3600) and class (IN) suit you:

     mx, err := dns.NewRR("miek.nl MX 10 mx.miek.nl")

Or even:

     mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")

In the DNS messages are exchanged, these messages contain resource
records (sets). Use pattern for creating a message:

     m := new(dns.Msg)
     m.SetQuestion("miek.nl.", dns.TypeMX)

Or when not certain if the domain name is fully qualified:

	m.SetQuestion(dns.Fqdn("miek.nl"), dns.TypeMX)

The message m is now a message with the question section set to ask
the MX records for the miek.nl. zone.

The following is slightly more verbose, but more flexible:

     m1 := new(dns.Msg)
     m1.Id = dns.Id()
     m1.RecursionDesired = true
     m1.Question = make([]dns.Question, 1)
     m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}

After creating a message it can be sent.
Basic use pattern for synchronous querying the DNS at a
server configured on 127.0.0.1 and port 53:

     c := new(dns.Client)
     in, rtt, err := c.Exchange(m1, "127.0.0.1:53")

Suppressing multiple outstanding queries (with the same question, type and
class) is as easy as setting:

	c.SingleInflight = true

More advanced options are availabe using a net.Dialer and the corresponding API.
For example it is possible to set a timeout, or to specify a source IP address
and port to use for the connection:

	c := new(dns.Client)
	laddr := net.UDPAddr{
		IP: net.ParseIP("[::1]"),
		Port: 12345,
		Zone: "",
	}
	d := net.Dialer{
		Timeout: 200 * time.Millisecond,
		LocalAddr: &laddr,
	}
	in, rtt, err := c.ExchangeWithDialer(&d, m1, "8.8.8.8:53")

If these "advanced" features are not needed, a simple UDP query can be sent,
with:

	in, err := dns.Exchange(m1, "127.0.0.1:53")

When this functions returns you will get dns message. A dns message consists
out of four sections.
The question section: in.Question, the answer section: in.Answer,
the authority section: in.Ns and the additional section: in.Extra.

Each of these sections (except the Question section) contain a []RR. Basic
use pattern for accessing the rdata of a TXT RR as the first RR in
the Answer section:

	if t, ok := in.Answer[0].(*dns.TXT); ok {
		// do something with t.Txt
	}

Domain Name and TXT Character String Representations

Both domain names and TXT character strings are converted to presentation
form both when unpacked and when converted to strings.

For TXT character strings, tabs, carriage returns and line feeds will be
converted to \t, \r and \n respectively. Back slashes and quotations marks
will be escaped. Bytes below 32 and above 127 will be converted to \DDD
form.

For domain names, in addition to the above rules brackets, periods,
spaces, semicolons and the at symbol are escaped.

DNSSEC

DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It
uses public key cryptography to sign resource records. The
public keys are stored in DNSKEY records and the signatures in RRSIG records.

Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit
to a request.

     m := new(dns.Msg)
     m.SetEdns0(4096, true)

Signature generation, signature verification and key generation are all supported.

DYNAMIC UPDATES

Dynamic updates reuses the DNS message format, but renames three of
the sections. Question is Zone, Answer is Prerequisite, Authority is
Update, only the Additional is not renamed. See RFC 2136 for the gory details.

You can set a rather complex set of rules for the existence of absence of
certain resource records or names in a zone to specify if resource records
should be added or removed. The table from RFC 2136 supplemented with the Go
DNS function shows which functions exist to specify the prerequisites.

 3.2.4 - Table Of Metavalues Used In Prerequisite Section

  CLASS    TYPE     RDATA    Meaning                    Function
  --------------------------------------------------------------
  ANY      ANY      empty    Name is in use             dns.NameUsed
  ANY      rrset    empty    RRset exists (value indep) dns.RRsetUsed
  NONE     ANY      empty    Name is not in use         dns.NameNotUsed
  NONE     rrset    empty    RRset does not exist       dns.RRsetNotUsed
  zone     rrset    rr       RRset exists (value dep)   dns.Used

The prerequisite section can also be left empty.
If you have decided on the prerequisites you can tell what RRs should
be added or deleted. The next table shows the options you have and
what functions to call.

 3.4.2.6 - Table Of Metavalues Used In Update Section

  CLASS    TYPE     RDATA    Meaning                     Function
  ---------------------------------------------------------------
  ANY      ANY      empty    Delete all RRsets from name dns.RemoveName
  ANY      rrset    empty    Delete an RRset             dns.RemoveRRset
  NONE     rrset    rr       Delete an RR from RRset     dns.Remove
  zone     rrset    rr       Add to an RRset             dns.Insert

TRANSACTION SIGNATURE

An TSIG or transaction signature adds a HMAC TSIG record to each message sent.
The supported algorithms include: HmacMD5, HmacSHA1, HmacSHA256 and HmacSHA512.

Basic use pattern when querying with a TSIG name "axfr." (note that these key names
must be fully qualified - as they are domain names) and the base64 secret
"so6ZGir4GPAqINNh9U5c3A==":

	c := new(dns.Client)
	c.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
	m := new(dns.Msg)
	m.SetQuestion("miek.nl.", dns.TypeMX)
	m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
	...
	// When sending the TSIG RR is calculated and filled in before sending

When requesting an zone transfer (almost all TSIG usage is when requesting zone transfers), with
TSIG, this is the basic use pattern. In this example we request an AXFR for
miek.nl. with TSIG key named "axfr." and secret "so6ZGir4GPAqINNh9U5c3A=="
and using the server 176.58.119.54:

	t := new(dns.Transfer)
	m := new(dns.Msg)
	t.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
	m.SetAxfr("miek.nl.")
	m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
	c, err := t.In(m, "176.58.119.54:53")
	for r := range c { ... }

You can now read the records from the transfer as they come in. Each envelope is checked with TSIG.
If something is not correct an error is returned.

Basic use pattern validating and replying to a message that has TSIG set.

	server := &dns.Server{Addr: ":53", Net: "udp"}
	server.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
	go server.ListenAndServe()
	dns.HandleFunc(".", handleRequest)

	func handleRequest(w dns.ResponseWriter, r *dns.Msg) {
		m := new(dns.Msg)
		m.SetReply(r)
		if r.IsTsig() != nil {
			if w.TsigStatus() == nil {
				// *Msg r has an TSIG record and it was validated
				m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
			} else {
				// *Msg r has an TSIG records and it was not valided
			}
		}
		w.WriteMsg(m)
	}

PRIVATE RRS

RFC 6895 sets aside a range of type codes for private use. This range
is 65,280 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
can be used, before requesting an official type code from IANA.

see http://miek.nl/2014/September/21/idn-and-private-rr-in-go-dns/ for more
information.

EDNS0

EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated
by RFC 6891. It defines an new RR type, the OPT RR, which is then completely
abused.
Basic use pattern for creating an (empty) OPT RR:

	o := new(dns.OPT)
	o.Hdr.Name = "." // MUST be the root zone, per definition.
	o.Hdr.Rrtype = dns.TypeOPT

The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891)
interfaces. Currently only a few have been standardized: EDNS0_NSID
(RFC 5001) and EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note
that these options may be combined in an OPT RR.
Basic use pattern for a server to check if (and which) options are set:

	// o is a dns.OPT
	for _, s := range o.Option {
		switch e := s.(type) {
		case *dns.EDNS0_NSID:
			// do stuff with e.Nsid
		case *dns.EDNS0_SUBNET:
			// access e.Family, e.Address, etc.
		}
	}

SIG(0)

From RFC 2931:

    SIG(0) provides protection for DNS transactions and requests ....
    ... protection for glue records, DNS requests, protection for message headers
    on requests and responses, and protection of the overall integrity of a response.

It works like TSIG, except that SIG(0) uses public key cryptography, instead of the shared
secret approach in TSIG.
Supported algorithms: DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256 and
RSASHA512.

Signing subsequent messages in multi-message sessions is not implemented.
*/
package dns