Как использовать Resolv::DNS::Resource::Generic
Я хотел бы лучше понять, как Resolv::DNS обрабатывает записи, которые не поддерживаются напрямую. Эти записи представлены классом Resolv::DNS::Resource::Generic, но я не смог найти документацию о том, как получить данные из этой записи.
В частности, моя зона будет содержать записи SSHFP и TLSA, и мне нужен способ получить эти данные.
1 ответ
Благодаря обратному инжинирингу я нашел ответ - задокументировал его здесь, чтобы другие могли его увидеть.
Обратите внимание, что это включает недокументированные функции модуля Resolv::DNS, и реализация может со временем измениться.
Записи ресурсов, которые модуль Resolv::DNS не понимает, представлены не через класс Generic, а через подкласс, имя которого представляет тип и класс ответа DNS - например, будет представлена запись SSHFP (тип 44) как Resolv::DNS::Resource::Generic::Type44_Class1
Объект будет содержать метод "data", который дает вам доступ к RDATA записи в простом двоичном формате.
Таким образом, чтобы получить доступ к записи SSHFP, вот как ее получить:
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