Examples -- DNS Updates

Examples -- DNS Updates -- RFC 2136 DNS Updates

RFC 2136 DNS Updates

By constructing a specially formatted DNS packet and sending it to a nameserver, a dynamic DNS update can be performed very easily. RFC 2136 defines some variations of a DNS packet that are used by Net_DNS to request an update. The nameserver must first be configured to accept DNS updates, a key must be established between the client and server, and most importantly, the PHP mhash extension must be included for processing the MD5 digest of the key.

The format of the DNS packet is very specific and requires in-depth knowledge of how DNS updates work. Net_DNS currently does not support any abstraction of these specially formatted packets. Packets must currently be crafted and sent manually. The full formatting of update packets can be found in RFC 2136.

For a complete listing of all of the fields that are available for DNS updates, please review RFC2136 (http://www.ietf.org/rfc/rfc2136.txt). The following examples show the simplest forms of a DNS update.

Example 48-1. Sending a dynamic DNS update packet to a nameserver

<?php
require_once 'Net/DNS.php';

$resolver = new Net_DNS_Resolver();

// We should only send the request to the master server
// accepting DNS updates for the zone.
$resolver->nameservers = array('192.168.0.254');

// We must manually construct the DNS packet for a DNS update
// First we must instantiate the packet object
$packet = new Net_DNS_Packet();

// Create the header for the update packet.  Most of the defaults are
// acceptable, but we must set the header OPCODE to "UPDATE"
$packet->header = new Net_DNS_Header();
$packet->header->id = $resolver->nextid();
$packet->header->qr = 0;
$packet->header->opcode = "UPDATE";

// As specified in RFC2136, the question section becomes the "ZONE" section.
// This specifies the zone for which we are requesting a change.  This
// reflects the zone configuration as specified in the nameserver
// configuration.
$packet->question[0] = new Net_DNS_Question('example.com', "SOA", "IN");

// The "ANSWER" section of the packet becomes the "PREREQUISITE" section of
// the packet. Section 2.4 of RFC2136 defines the possible values for this
// section.  As show below, without any prerequisites the nameserver will
// attempt to perform the update unconditionally.
$packet->answer = array();

// The AUTHORITY section becomes the "UPDATE" section of the DNS packet.  The
// UPDATE section is a collection of resource record updates that should be
// modified in one form or another.  RRs can be deleted or added based on the
// values passed in the RR object.  These values are specified in RFC2136 but
// are summarized here:
//
// Adding an RR
// A complete RR object with a non-zero TTL is considered an addition.
//
// Deleting an RR
// A complete RR object with a zero TTL is considered an deletion. An RR that
// matches (exactly) with all values except for the TTL will be removed.
//
// Deleting an RRset
// A complete RR object with a zero TTL and a type of ANY is considered a
// deletion of all RRs with the specified name and type. An RR that matches
// (exactly) with all values except for the TTL and the TYPE will be removed.
//
// Deleting all RRsets for a name 
// A complete RR object with a zero TTL, a type of ANY, and a class of ANY is
// considered a deletion of all RRs with the specified name. Any RR that
// matches the name section of the query will be removed.
//
// The following specification will delete the RR that has a name of
// "example.com", class of "IN", type of "A", and an address of
// "192.0.34.166".
$rrDelete = new Net_DNS_RR("example.com. 0 IN A 192.0.34.166");
//
// The following specification will add an RR that has a name of example.com,
// a TTL of 1 hour, a class of "IN", type of "A", and an address of
// "192.0.34.155").  Note that the only difference between this RR and the
// previous RR is the value of the TTL.
$rrAdd = new Net_DNS_RR("example.com. 3600 IN A 192.0.34.166");
//
// The RR modifications are added to the authority (UPDATE) section of the DNS
// packet.
$packet->authority[0] = $rrDelete;
$packet->authority[1] = $rrAdd;
//
// The signature must be present in any packet sent to a nameserver that
// requires authentication.  The TSIG RR is added to the additional section of
// the DNS packet.
$tsig = new Net_DNS_RR("keyname.as.specified.in.server. TSIG ThisIsMyKey");
$packet->additional = array($tsig);
// Net_DNS does not automatically calculate the number of records stored in
// each section.  This calculation must be done manually.
$packet->header->qdcount = count($packet->question);
$packet->header->ancount = count($packet->answer);
$packet->header->nscount = count($packet->authority);
$packet->header->arcount = count($packet->additional);
//
// After creating your packet, you must send it to the name server for
// processing.  DNS updates must use the send_tcp() method: 
$response = $resolver->send_tcp($packet, $packet->data());
//
// The response from the server will vary.  If the update was successfuly, the
// server will have a response code of "NOERROR".  Any other error types will
// be reported in the response packet's header "rcode" variable.
if ($response->header->rcode != "NOERROR") {
  return($response->header->rcode);
}

?>