TinyDNS backend for PowerDNS

This is first development version of TinyDNS backend for PowerDNS. PowerDNS is great authoritative DNS server which uses backends for zone data storage and retrieval. I've noticed in TODO that there is no TinyDNS backend. I've decided to help a little and to write that backend. Unfortunately my C/C++ programming skills are not sufficient as I prefer other languages. However there is pipe backend which makes it possible to run almost any program as backend. My TinyDNS backend itself is written in PHP and consists of two files. One – backend.php – acts as PIPE protocol wrapper and uses object defined in second file – tinydns.php – for the TinyDNS related loading/lookups etc... You can use backend.php to create another backends easily. PHP may seem strange choice for system daemon like this but it is very flexible and the development is quick. Surely it have some overhead about pure C/C++ but this is not so big problem (see Performance details later) in middle sized installations. And super-sized installations with 100K+ zones would use some database storage.

Features

The backend has these features:

The code is still in beta state – it should work but it definitely needs lot of testing and fine tuning. Also some optimizations, code cleanup and more comments are needed. I would be very pleased if people could test it and report errors/problems/ideas for improvement.

Performance

Backend runs as process which gets queries on standard input and responds with records on standard output. One process can handle many queries so initial loading/parsing of PHP code should be insignificant. I use PHP associative arrays (hashes) for storing the values so searching the record should be also comparable to pure C/C++ code. However PHP will have significant memory overhead. For the sake of speed I store each record twice - once for it's record class and second for any query type – this allows query-type specific and nonspecific lookups to be done with only one array access. This means that 1 record occupies at all about 800Bytes of memory - I used test file with 3311 zones and 42880 records. It used 36.17MB of memory at all (including all other structures and whichever memory PHP needs). I also use location lookup cache (if you do not use locations, you wont need it). It stores found location for every requesting IP (if there are records with locations in question). Every cache record uses about 100Bytes of memory. You can setup maximum count of cached records to limit memory usage.

CPU intensive tasks have not so big overhead. Loading of mentioned test file took 4.047 sec on my old testing server (P3 800MHz). This is not problem when starting the backend but can lead to timeouts when zone file is reloaded – zonefiles are (for now) checked for change just after query is received so reloading can take more time than impatient client will wait for response. This should occur only once after each reload. The lookup itself took 0.00023secs in average (on mentioned HW and test file) and complete query took from 2ms to 7ms (measured via dig).

Wildcard handling

PowerDNS handles wildcards on its own. If the backend returns negative answer for www.example.com it will ask whether the backend have SOA for example.com and if so it will send query *.example.com. The TinyDNS uses similar notation for wildcards. I don't know whether the wildcards processing logic is the same and whether I should implement TinyDNS logic or stick with PowerDNS.

Instalation

  1. Download this package and unpack

  2. Change path in require directive in backend.php (somwhere around line 104)

  3. Change path and other configuration option on the begging of tinydns.php (object variables)

  4. You may need to increase memory limit for PHP applications in php.ini

  5. Install pipe backend for PowerDNS

  6. Add these two options into PowerDNS configuration: (change the path to suit your needs)

    pipe-command=/root/pdns/backend.php
    pipebackend-abi-version=2
  7. Configure PowerDNS to use the backend via configuration option

    launch=pipe
  8. Restart PowerDNS

Testing

You can test the plugin itself by executing backend.php from shell. You need to initialize it using HELO command. All fields are TAB separated! Example communication can be found here:

#./backend.php
HELO    1
OK      PHP TinyDNS Backend ver 0.9 (PID 25063):  2 zones with 25 records loaded in 0.003s using 0.24MB
Q       www2.geizhals.at        IN      ANY     1       127.0.0.1
DATA            www2.geizhals.at        IN      A       3600    12      81.223.238.135
END

Lines to be entered are bolded. The most important command is “Q” command. It's fields are (in order) Q, queried record, class (always IN), query type (ANY), record ID (could be obtained by previous queries) and IP address of the requester. Backend responses with records found (if any) and with END keyword.

Contact and license

Code is licensed using GNU/GPLv2 but I would be very pleased if you could let me know about any significant modifications to the code. I would also be very pleased with info whether you find this useful. And I would appreciate error/performance reports, ideas for improvement or any feedback. You can reach me at r.hladik-nospam (at) cybersales (dot) cz.