Simple Forward DNS

Adding the domain

For every domain or sub-domain which you intend manage using PowerDNS a record is required in the domains table. This entry is used to store various configuration parameters which the PowerDNS daemon uses for each domain and is also used as a foreign key in the records table. Let us start therefore by adding an appropriate entry to the domains table for our example domain.

To do this we shall need to launch the psql application and connect to the dns database as the dns_admin user. This can be done using the commands below.

lisa su - pgadmin
pgadmin@lisa psql dns dns_admin

Now that we are connected to the dns database as the dns_admin user we can enter the SQL command to add the example domain to the domains table. The command below will create a new domain record for the hacking.co.uk domain with the type field set to NATIVE which indicates to the PowerDNS daemon that this domain will be a master domain in the context of DNS but will use the native replication method supported by PowerDNS.

postgres=# INSERT INTO domains(name, type) VALUES('hacking.co.uk', 'NATIVE'); 
INSERT 0 1 

Once we have created a record in the domains table we can start to populate the records table with DNS records to be served by the PowerDNS daemon for this domain. Before we can do so however we need to know the value of the id field which will have been automatically assigned to this record by the PostgreSQL database. To do this we can issue the simple SQL query shown below which should result in output similar to that shown. As you can see the value of the id field for the hacking.co.uk domain in this example is 1.

postgres=# SELECT * FROM domains; 
 id |     name      | master | last_check |  type  | notified_serial | account 
----+---------------+--------+------------+--------+-----------------+--------- 
  1 | hacking.co.uk |        |            | NATIVE |                 | 
(1 row) 

Start of Authority (SOA) record

Arguably the most important record for any domain is the Start of Authority, or SOA, record. This record indicates that the server specified is the authoritative source of information for the domain in question. It also contains other information such as the contact email address of the DNS administrator for that domain as well as a number of values which are only relevant when dealing with replication and therefore will be discussed in the appropriate sections later in this guide.

postgres=# INSERT INTO records(domain_id, name, type, content, ttl, change_date) 
postgres-#   VALUES(1, 'hacking.co.uk', 'SOA', 'ns1.hacking.co.uk hostmaster.hacking.co.uk', 86400, 2008032801); 
INSERT 0 1 

As you can see from the above example the first three values are fairly self explanatory and consist simply of the domain id, which we discussed earlier and in this case is 1, the domain name for which this record will apply, hacking.co.ukin the example, and the type of record which we are inserting which in this case is SOA. The fourth value is a little more complex as it consists of the fully qualified domain name of the primary name server for this domain, which is ns1.hacking.co.uk in the above example, and the email address of the DNS administrator with the @ symbol converted to a period. The fifth value specifies this record's TTL which in layman's terms is the period of time, in seconds, which caching DNS resolvers will keep this record in their cache. The final field is the date on which this record was last modified, in long numeric ISO format, with a two digit sequence number appended.

Name Server (NS) records

In the previous section we created an SOA record for our example domain in which, amongst other things, we specified the primary name server for this domain. This value is, however, only used by secondary DNS servers to determine the address from which to request a zone transfer during replication and will not enable standard DNS resolvers to locate the DNS server for the domain. To enable standard DNS resolvers to obtain the name, and subsequently the IP address, of the DNS servers for the domain we need to add one or more NS records.

Caution:
As name resolution is fundamental to the correct operation of any network more than one DNS server should be provided in any production environment. We discuss replication of DNS records between such servers in later sections. Additional NS records are required for these servers.
 

The SQL statement in the example below will insert such a record into the database using the same structure as the SOA record above. The first two fields again represent the domain id and the name of the record, while the third field is set to NS to indicate that this is a Name Server record. The fourth field specifies the name of a DNS server for this domain, and is ns1.hacking.co.uk in this example. As always the fifth field is the TTL for this record, which in the example is set to 86400 seconds (24 hours), and the sixth and final field is the change date as in the above example.

postgres=# INSERT INTO records(domain_id, name, type, content, ttl, change_date) 
postgres-#   VALUES(1, 'hacking.co.uk', 'NS', 'ns1.hacking.co.uk', 86400, 2008032801); 
INSERT 0 1 

As you may have noticed the above record does not specify the IP address for the name server in question and instead specifies a fully qualified domain name instead. In this example we are using a DNS server on our own domain to answer queries for the DNS records for our domain however this is by no means compulsory. Any fully qualified host name can be used in place of this value, as long as the server to which it resolves to is expecting to serve records for this domain of course.

When the DNS server used to serve records for a domain is on a different domain to that which it is serving the requesting DNS resolver will receive a reply with the name of the DNS server to query. This name will then be looked up at the DNS servers for the domain in question and the process will begin again. This allows a DNS server on a different domain to be the target for queries regarding our domain and is commonly referred to as "out of bailiwick DNS".

In our example above however we are using a DNS server on the same domain as the domain it is serving. This is usually referred to as "in bailiwick DNS" as the DNS server is in the same "bailiwick" as the query domain. When a DNS resolver requests the name server for the domain it receives a reply with the name of the DNS server as before however it cannot resolve this name to an IP address as it would need to query the DNS server in question. To avoid this problem DNS servers which also have an Address record for the host specified in the NS record will include this address in the reply to the NS query. This is commonly referred to as a "glue record" resulting in the rather wonderful phrase "in bailiwick DNS with glue" as a description of the entire process. We shall create a suitable A record in the next section.

Address (A) records

With the SOA and NS records successfully added to the table we can finally begin the process of adding A records for our hosts so that we can actually use our DNS server to resolve host names to IP addresses. As we already have an NS record which needs an A record to use as "glue" we shall use this as our example.

postgres=# INSERT INTO records(domain_id, name, type, content, ttl, change_date) 
postgres-#   VALUES(1, 'ns1.hacking.co.uk', 'A', '192.168.0.3', 3600, 2008032801); 
INSERT 0 1 

As before the first field of the above example is the domain id for the domain we are working with. The second field in this record in the fully qualified host name for the host we are creating the A record for. The third field contains A to indicate to the PowerDNS daemon that this is an Address record. The fourth field therefore contains the IP address which should be associated with this host, which in the above example is 192.168.0.3. The fifth and sixth fields, as always, contain the TTL for this record, which in the example is set to 3600 seconds (1 hour), and the change date.

Testing our configuration

lisa /etc/init.d/pdns start
lisa rc-update add pdns default

Now that we have a complete configuration, albeit a rather minimal one, we are ready to test to see if our new DNS server is correctly answering queries for our domain. To do this we shall use the dig application from the net-dns/bind-tools package we installed earlier. An example dig command to query the NS records for the hacking.co.uk domain using the DNS server located at 192.168.0.3 is given below.

lisa dig @192.168.0.3 hacking.co.uk NS
; <<>> DiG 9.4.1-P1 <<>> @192.168.0.3 hacking.co.uk NS 
; (1 server found) 
;; global options:  printcmd 
;; Got answer: 
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32449 
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 
;; WARNING: recursion requested but not available 
 
;; QUESTION SECTION: 
;hacking.co.uk.	IN      NS 
 
;; ANSWER SECTION: 
hacking.co.uk. 86400 IN NS     ns1.hacking.co.uk. 
 
;; ADDITIONAL SECTION: 
ns1.hacking.co.uk. 3600 IN A   192.168.0.3 
 
;; Query time: 3 msec 
;; SERVER: 192.168.0.3#53(192.168.0.3) 
;; WHEN: Fri Mar 28 12:39:15 2008 
;; MSG SIZE  rcvd: 81 

Assuming everything has gone well thus far you should be presented with output similar to that shown above. The most important output is the Answer Section which contains the answer to the NS query we sent and the Additional Section which should contain the A record for the "glue" part of in bailiwick DNS.