Kevin Keane
Kevin Keane

Reputation: 1658

How to use Resolv::DNS::Resource::Generic

I would like to better understand how Resolv::DNS handles records that are not directly supported. These records are represented by the Resolv::DNS::Resource::Generic class, but I could not find documentation about how to get the data out of this record.

Specifically, my zone will contain SSHFP and TLSA records, and I need a way to get to that data.

Upvotes: 3

Views: 603

Answers (1)

Kevin Keane
Kevin Keane

Reputation: 1658

Through reverse engineering, I found the answer - documenting it here for others to see.

Please note that this involves undocumented features of the Resolv::DNS module, and the implementation may change over time.

Resource Records that the Resolv::DNS module does not understand are represented not through the Generic class, but rather through a subclass whose name represents the type and class of the DNS response - for instance, an SSHFP record (type 44) will be represented as Resolv::DNS::Resource::Generic::Type44_Class1

The object will contain a method "data" that gives you access to the RDATA of the record, in plain binary format.

Thus, to access an SSHFP record, here is how to get it:

def handle_sshfp(rr) do
   # the RDATA is a string but contains binary data
   data = rr.data.bytes
   algo = data[0].to_s
   fptype = data[1].to_s
   fp = data[2..-1].to_s
   hex = fp.map{|b| b.to_s(16).rr.rjust(2,'0') }.join(':')
   puts "The SSHFP record is: #{fptype} #{algo} #{hex}"
end

Resolv::DNS.open do |dns|
   all_records = dns.getresources('myfqdn.example.com', Resolv::DNS::Resource::IN::ANY ) rescue nil
   all_records.each do |rr|
      if rr.is_a? Resolv::DNS::Resource::Generic then
         classname = rr.class.name.split('::').last
         handle_sshfp(rr) if classname == "Type44_Class1"
      end
   end
end

Upvotes: 4

Related Questions