powerdns_pipe is a Ruby library for developing PowerDNS pipe backend resolvers.
More information on the PowerDNS pipe backend can be found here.
sudo gem install powerdns_pipe
PowerDNS::Pipe works by handling all the communication with PowerDNS for you. It handles the HELO
and PING
and stuff, but calls a block when a query or axfr request is made. The block has access to a question
object which has information about the query from PowerDNS, and the answer
method, which provides responses to PowerDNS.
PowerDNS::Pipe.new
takes a hash of options, all are optional and the defaults are usually all you need:
- :input
-
The IO object to read requests from PowerDNS. Defaults to STDIN
- :output
-
The IO object to write responses to PowerDNS. Defaults to STDOUT
- :err
-
The IO object to write debugging information. Defaults to STDERR, but is rarely used.
- :version_range
-
A Range instance representing the Pipe protocol versions this backend supports. Defaults to 1..2
- :banner
-
A string used in response to HELO requests from PowerDNS, is logged to the PowerDNS logs. Defaults to “Ruby PowerDNS::Pipe”
The question
object provides information about the query from the server:
name
-
The record being requested, e.g:
www.example.com
qtype
-
The request type, such as
A
orMX
. PowerDNS often usesANY
, to which you should return all valid records for the name and PowerDNS worries about returning the right one to the client. You must support this type. qclass
-
The request class, this is always
IN
. remote_ip_address
-
The IP address of the host making the dns request. You could use this to return different records for different geographic regions.
local_ip_address
-
The server IP address the request came into. Useful if your PowerDNS server is listening on multiple IPs and you want to consider that in your answers.
id
-
The id of the last answer to this question provided to PowerDNS by this backend for this. This might be useful to you to speed up subsequent lookups. -1 by default and can be ignored.
query?
-
Returns true if this is a normal Q query.
axfr?
-
Returns true if this is an axfr query.
The answer
method is used to return records to PowerDNS. It can be called multiple times to return multiple records. Any exceptions are caught for you so garbage is not returned to PowerDNS. If you have nothing to return, just don’t call answer at all.
It takes the following options:
:name
-
The record name, e.g:
www.example.com
. Can usually just be set toquestion.name
:ttl
-
Time to Live in seconds. Defaults to 3600
:content
-
The content of the response, so an IP address string for
A
answers, or arbitrary text forTXT
answers. For records with a priority (like MX records) put the priority first and then a space and then the content, e.g:10 mail.example.com
:id
-
An integer id for this answer. PowerDNS will remember this and pass it back for subsequent requests for the same record. You might use this to pass around a primary key or something to speed up subsequent lookups. Defaults to -1 and can be ignored.
:class
-
The class of this answer, defaults to
IN
and shouldn’t be changed.
Return an A
record of 1.2.3.4
for all queries:
require 'powerdns_pipe' PowerDNS::Pipe.new.run! do answer :name => question.name, :type => 'A', :ttl => 60, :content => '1.2.3.4' end
Return the HTTP Server header as a TXT record for the host requested.
Example usage:
$ host -t txt www.ubuntu.com.example.com ubuntu.com.example.com descriptive text "Apache/2.2.8 (Ubuntu) mod_python/3.3.1"
Code:
require 'powerdns_pipe' require 'net/http' re = Regexp.new("^(.+)\.example\.com$") pipe = PowerDNS::Pipe.new :banner => 'HTTP Server Header TXT Pipe' pipe.run! do if m = re.match(question.name) domain = m[1] case question.qtype when "TXT", "ANY" res = Net::HTTP.get_response(URI.parse("http://" + domain)) answer :name => question.name , :type => 'TXT', :ttl => 3600, :content => res['Server'] end end end
- Author
-
John Leach ([email protected])
- Copyright
-
Copyright © 2010 John Leach
- License
-
MIT
- Github
See also the ruby-pdns library which does things differently, with some limitations.