Performing DNS Queries

Problem

You want to find the IP address corresponding to a domain name, or see whether a domain provides a certain service (such as an email server).

Solution

Use the Resolv:: DNS class in the standard resolv library to perform DNS lookups. The most commonly used method is DNS#each_address, which iterates over the IP addresses assigned to a domain name.

	require 
esolv
	 
Resolv::DNS.new.each_address("oreilly.com") { |addr| puts addr }
	# 208.201.239.36
	# 208.201.239.37

Discussion

If you need to check the existence of a particular type of DNS record (such as a MX record for a mail server), use DNS#getresources or the iterator DNS#each_resource. Both methods take a domain name and a class denoting a type of DNS record. They perform a DNS lookup and, for each matching DNS record, return an instance of the given class.

These are the three most common classes:


DNS::Resource::IN::A

Indicates a DNS record pointing to an IP address for the domain.


DNS::RESOURCE::IN::NS

Indicates a DNS record pointing to a DNS nameserver.


DNS::Resource::IN::MX

Indicates a DNS record pointing to a mail server.

This code finds the mail servers and name servers responsible for oreilly.com:

	dns = 
Resolv::DNS.new
	domain = "oreilly.com"
	dns.each_resource(domain, Resolv::DNS::Resource::IN::MX) do |mail_server|
	 puts mail_server.exchange
	end
	# smtp1.oreilly.com
	# smtp2.oreilly.com

	dns.each_resource(domain, Resolv::DNS::Resource::IN::NS) do |nameserver|
	 puts nameserver.name
	end
	# a.auth-ns.sonic.net
	# b.auth-ns.sonic.net
	# c.auth-ns.sonic.net
	# ns.oreilly.com

If your application needs to do a lot of DNS lookups, you can greatly speed things up by creating a separate thread for each lookup. Most of the time spent doing a DNS lookup is spent connecting to the network, so doing all the lookups in parallel can save a lot of time. If you do this, you should include the resolv-replace library along with resolv, to make sure your DNS lookups are thread-safe.

Heres some code that sees which one-letter .com domains (a.com, b.com, etc.) are mapped to IP addresses. It runs all 26 DNS queries at once, in 26 threads, and summarizes the results.

	require 
esolv-replace
	def multiple_lookup(*names)
	 
dns = 
Resolv::DNS.new
	 results = {}
	 threads = []
	 names.each do |name|
	 threads << Thread.new(name) do |name|
	 begin
	 dns.each_address(name) { |a| (results[name] ||= []) << a }
	 rescue Resolv::ResolvError
	 results[name] = nil
	 end
	 end
	 end
	 threads.each { |t| t.join }
	 return results
	end

	domains = ("a".."z").collect { |l| l + .com }
	multiple_lookup(*domains).each do |name, addresses|
	 if addresses
	 puts "#{name}: #{addresses.size} address#{addresses.size == 1 ? "" : "es"}"
	 end
	end
	# x.com: 4 addresses
	# z.com: 1 address
	# q.com: 1 address

See Also

  • Chapter 20 uses a DNS lookup of an MX record to check whether the domain of an email address is valid
  • A DNS lookup is the classic example of a high-latency operation; much of Chapter 20 deals with ways of making high-latency operations run more quickly: see especially Recipe 20.3, "Doing Two Things at Once with Threads," and Recipe 20.6, "Running a Code Block on Many Objects Simultaneously"


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net