1/* 2Package dns implements a full featured interface to the Domain Name System. 3Server- and client-side programming is supported. 4The package allows complete control over what is send out to the DNS. The package 5API follows the less-is-more principle, by presenting a small, clean interface. 6 7The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers, 8TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing. 9Note that domain names MUST be fully qualified, before sending them, unqualified 10names in a message will result in a packing failure. 11 12Resource records are native types. They are not stored in wire format. 13Basic usage pattern for creating a new resource record: 14 15 r := new(dns.MX) 16 r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX, 17 Class: dns.ClassINET, Ttl: 3600} 18 r.Preference = 10 19 r.Mx = "mx.miek.nl." 20 21Or directly from a string: 22 23 mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.") 24 25Or when the default TTL (3600) and class (IN) suit you: 26 27 mx, err := dns.NewRR("miek.nl. MX 10 mx.miek.nl.") 28 29Or even: 30 31 mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek") 32 33In the DNS messages are exchanged, these messages contain resource 34records (sets). Use pattern for creating a message: 35 36 m := new(dns.Msg) 37 m.SetQuestion("miek.nl.", dns.TypeMX) 38 39Or when not certain if the domain name is fully qualified: 40 41 m.SetQuestion(dns.Fqdn("miek.nl"), dns.TypeMX) 42 43The message m is now a message with the question section set to ask 44the MX records for the miek.nl. zone. 45 46The following is slightly more verbose, but more flexible: 47 48 m1 := new(dns.Msg) 49 m1.Id = dns.Id() 50 m1.RecursionDesired = true 51 m1.Question = make([]dns.Question, 1) 52 m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET} 53 54After creating a message it can be send. 55Basic use pattern for synchronous querying the DNS at a 56server configured on 127.0.0.1 and port 53: 57 58 c := new(dns.Client) 59 in, rtt, err := c.Exchange(m1, "127.0.0.1:53") 60 61Suppressing multiple outstanding queries (with the same question, type and 62class) is as easy as setting: 63 64 c.SingleInflight = true 65 66If these "advanced" features are not needed, a simple UDP query can be send, 67with: 68 69 in, err := dns.Exchange(m1, "127.0.0.1:53") 70 71When this functions returns you will get dns message. A dns message consists 72out of four sections. 73The question section: in.Question, the answer section: in.Answer, 74the authority section: in.Ns and the additional section: in.Extra. 75 76Each of these sections (except the Question section) contain a []RR. Basic 77use pattern for accessing the rdata of a TXT RR as the first RR in 78the Answer section: 79 80 if t, ok := in.Answer[0].(*dns.TXT); ok { 81 // do something with t.Txt 82 } 83 84Domain Name and TXT Character String Representations 85 86Both domain names and TXT character strings are converted to presentation 87form both when unpacked and when converted to strings. 88 89For TXT character strings, tabs, carriage returns and line feeds will be 90converted to \t, \r and \n respectively. Back slashes and quotations marks 91will be escaped. Bytes below 32 and above 127 will be converted to \DDD 92form. 93 94For domain names, in addition to the above rules brackets, periods, 95spaces, semicolons and the at symbol are escaped. 96 97DNSSEC 98 99DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It 100uses public key cryptography to sign resource records. The 101public keys are stored in DNSKEY records and the signatures in RRSIG records. 102 103Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit 104to a request. 105 106 m := new(dns.Msg) 107 m.SetEdns0(4096, true) 108 109Signature generation, signature verification and key generation are all supported. 110 111DYNAMIC UPDATES 112 113Dynamic updates reuses the DNS message format, but renames three of 114the sections. Question is Zone, Answer is Prerequisite, Authority is 115Update, only the Additional is not renamed. See RFC 2136 for the gory details. 116 117You can set a rather complex set of rules for the existence of absence of 118certain resource records or names in a zone to specify if resource records 119should be added or removed. The table from RFC 2136 supplemented with the Go 120DNS function shows which functions exist to specify the prerequisites. 121 122 3.2.4 - Table Of Metavalues Used In Prerequisite Section 123 124 CLASS TYPE RDATA Meaning Function 125 -------------------------------------------------------------- 126 ANY ANY empty Name is in use dns.NameUsed 127 ANY rrset empty RRset exists (value indep) dns.RRsetUsed 128 NONE ANY empty Name is not in use dns.NameNotUsed 129 NONE rrset empty RRset does not exist dns.RRsetNotUsed 130 zone rrset rr RRset exists (value dep) dns.Used 131 132The prerequisite section can also be left empty. 133If you have decided on the prerequisites you can tell what RRs should 134be added or deleted. The next table shows the options you have and 135what functions to call. 136 137 3.4.2.6 - Table Of Metavalues Used In Update Section 138 139 CLASS TYPE RDATA Meaning Function 140 --------------------------------------------------------------- 141 ANY ANY empty Delete all RRsets from name dns.RemoveName 142 ANY rrset empty Delete an RRset dns.RemoveRRset 143 NONE rrset rr Delete an RR from RRset dns.Remove 144 zone rrset rr Add to an RRset dns.Insert 145 146TRANSACTION SIGNATURE 147 148An TSIG or transaction signature adds a HMAC TSIG record to each message sent. 149The supported algorithms include: HmacMD5, HmacSHA1, HmacSHA256 and HmacSHA512. 150 151Basic use pattern when querying with a TSIG name "axfr." (note that these key names 152must be fully qualified - as they are domain names) and the base64 secret 153"so6ZGir4GPAqINNh9U5c3A==": 154 155 c := new(dns.Client) 156 c.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="} 157 m := new(dns.Msg) 158 m.SetQuestion("miek.nl.", dns.TypeMX) 159 m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix()) 160 ... 161 // When sending the TSIG RR is calculated and filled in before sending 162 163When requesting an zone transfer (almost all TSIG usage is when requesting zone transfers), with 164TSIG, this is the basic use pattern. In this example we request an AXFR for 165miek.nl. with TSIG key named "axfr." and secret "so6ZGir4GPAqINNh9U5c3A==" 166and using the server 176.58.119.54: 167 168 t := new(dns.Transfer) 169 m := new(dns.Msg) 170 t.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="} 171 m.SetAxfr("miek.nl.") 172 m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix()) 173 c, err := t.In(m, "176.58.119.54:53") 174 for r := range c { ... } 175 176You can now read the records from the transfer as they come in. Each envelope is checked with TSIG. 177If something is not correct an error is returned. 178 179Basic use pattern validating and replying to a message that has TSIG set. 180 181 server := &dns.Server{Addr: ":53", Net: "udp"} 182 server.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="} 183 go server.ListenAndServe() 184 dns.HandleFunc(".", handleRequest) 185 186 func handleRequest(w dns.ResponseWriter, r *dns.Msg) { 187 m := new(dns.Msg) 188 m.SetReply(r) 189 if r.IsTsig() != nil { 190 if w.TsigStatus() == nil { 191 // *Msg r has an TSIG record and it was validated 192 m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix()) 193 } else { 194 // *Msg r has an TSIG records and it was not valided 195 } 196 } 197 w.WriteMsg(m) 198 } 199 200PRIVATE RRS 201 202RFC 6895 sets aside a range of type codes for private use. This range 203is 65,280 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these 204can be used, before requesting an official type code from IANA. 205 206see http://miek.nl/2014/September/21/idn-and-private-rr-in-go-dns/ for more 207information. 208 209EDNS0 210 211EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated 212by RFC 6891. It defines an new RR type, the OPT RR, which is then completely 213abused. 214Basic use pattern for creating an (empty) OPT RR: 215 216 o := new(dns.OPT) 217 o.Hdr.Name = "." // MUST be the root zone, per definition. 218 o.Hdr.Rrtype = dns.TypeOPT 219 220The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891) 221interfaces. Currently only a few have been standardized: EDNS0_NSID 222(RFC 5001) and EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note 223that these options may be combined in an OPT RR. 224Basic use pattern for a server to check if (and which) options are set: 225 226 // o is a dns.OPT 227 for _, s := range o.Option { 228 switch e := s.(type) { 229 case *dns.EDNS0_NSID: 230 // do stuff with e.Nsid 231 case *dns.EDNS0_SUBNET: 232 // access e.Family, e.Address, etc. 233 } 234 } 235 236SIG(0) 237 238From RFC 2931: 239 240 SIG(0) provides protection for DNS transactions and requests .... 241 ... protection for glue records, DNS requests, protection for message headers 242 on requests and responses, and protection of the overall integrity of a response. 243 244It works like TSIG, except that SIG(0) uses public key cryptography, instead of the shared 245secret approach in TSIG. 246Supported algorithms: DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256 and 247RSASHA512. 248 249Signing subsequent messages in multi-message sessions is not implemented. 250*/ 251package dns 252