DNS enumeration with Ruby

10 Aug 2026
Security For Rails Developers

Develop the right mindset for Rails security

Avoid shipping vulnerable code by learning how to prevent security issues in your Rails applications.

Get the course for $99

I love Ruby and it is my goto scripting language. Even in the age of AI, I like to write short custom scripts for my tool arsenal. One way to find subdomains of a potential hacking target is to initiate a DNS zone transfer. You can use various shell tools for this, but if it is part of a process(my case), it might be easier and more flexible to just script it in Ruby. I decided to use the dnsruby gem to save some work, otherwise I would need to do a TCP connection to the nameservers myself. For the sake of demonstration, I converted my script into a command line one, that will accept 2 parameters, the host and an optional IP address of a nameserver:

domain = ARGV[0] or abort "You have to specify a domain"
nameservers = [ARGV[1]].compact
zone = domain.chomp('.').downcase

The next step is to fetch the nameservers if there wasn’t one provided:

resolver = Dnsruby::Resolver.new
if nameservers.empty?
  nameservers = resolver.query(zone, Dnsruby::Types.NS).answer
    .select { |rr| rr.type == Dnsruby::Types.NS }
    .map { |rr| rr.nsdname.to_s }
    .uniq
end

abort "No NS records found for #{zone}" if nameservers.empty?

Dnsruby makes this really simple, it has a Resolver class and constants to query for various records, in this case we are looking for the NS records of the domain.

Once we have the nameservers, we want to try a zone transfer on each of them:

nameservers.each do |ns|
  puts "\n== Trying zone transfer from #{ns} =="

  begin
    transfer = Dnsruby::ZoneTransfer.new
    transfer.server = ns

    records = transfer.transfer(zone)
    puts "Transferred #{records.size} records"

    records.each do |rr|
      name = rr.name.to_s.chomp('.').downcase
      next if name == zone
      next unless name.end_with?(".#{zone}")

      subdomains << name
    end
  rescue => e
    warn "Failed from #{ns}: #{e.message}"
  end
end

puts "\nSubdomains found:"
puts subdomains.uniq.sort

This is again, very simple with this gem, we can just create a ZoneTransfer class, set the nameserver we want t arget and call the transfer method. In case of success, we get the records and we can loop over them to find the subdomains. That’s it, pretty simple and beautiful Ruby.

Or follow me on Twitter

Related posts