...

Source file src/github.com/miekg/dns/doc.go

Documentation: github.com/miekg/dns

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

View as plain text