gitea

Development moved to Codeberg

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

It 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 available 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: "",
	}
	c.Dialer := &net.Dialer{
		Timeout: 200 * time.Millisecond,
		LocalAddr: &laddr,
	}
	in, rtt, err := c.Exchange(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: 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==":

If an incoming message contains a TSIG record it MUST be the last record in
the additional section (RFC2845 3.2).  This means that you should make the
call to SetTsig last, right before executing the query.  If you make any
changes to the RRset after calling SetTsig() the signature will be incorrect.

	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.HmacSHA256, 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.HmacSHA256, 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.

A custom TSIG implementation can be used. This requires additional code to
perform any session establishment and signature generation/verification. The
client must be configured with an implementation of the TsigProvider interface:

	type Provider struct{}

	func (*Provider) Generate(msg []byte, tsig *dns.TSIG) ([]byte, error) {
		// Use tsig.Hdr.Name and tsig.Algorithm in your code to
		// generate the MAC using msg as the payload.
	}

	func (*Provider) Verify(msg []byte, tsig *dns.TSIG) error {
		// Use tsig.Hdr.Name and tsig.Algorithm in your code to verify
		// that msg matches the value in tsig.MAC.
	}

	c := new(dns.Client)
	c.TsigProvider = new(Provider)
	m := new(dns.Msg)
	m.SetQuestion("miek.nl.", dns.TypeMX)
	m.SetTsig(keyname, dns.HmacSHA256, 300, time.Now().Unix())
	...
	// TSIG RR is calculated by calling your Generate method

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.HmacSHA256, 300, time.Now().Unix())
			} else {
				// *Msg r has an TSIG records and it was not validated
			}
		}
		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 https://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 (RFC 7871). 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: ECDSAP256SHA256,
ECDSAP384SHA384, RSASHA1, RSASHA256 and RSASHA512.

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