Recently at work I needed a way to quickly filter out displaying links to sites that some folks might find 'unsavory' to say the least. Rather than try go find a list of 'naughty words' (which would inevitably be incomplete or quickly become out of date), I opted for re-using existing infrastructure. In this case, leveraging OpenDNS and its hordes of users to easily determine which domains are either "questionable" in content, or possibly even phishing or spam domains. I was able to quickly hack together some Ruby code that uses Net::DNS to query OpenDNS and make a decision based on their categorization whether to block or allow the domain.
The code is below, the gist of it is that OpenDNS returns a set of IPs for domains that fall into their classifications (adult, non-existent, phishing / scam, etc.), so if any query falls into that range of IPs, we can consider it blocked. Eventually, I may add a function to determine why the domain was blocked, rather than just relying on the true/false result.
require 'net/dns/resolver'
require 'net/dns/packet'
class OpenDNSFilter
VERSION = "0.1"
DNS_HOSTS = ["208.67.222.222", "208.67.220.220"]
BLOCKED_RESPONSES = {
"67.215.65.130" => "hit-adult.opendns.com",
"67.215.65.131" => "hit-block.opendns.com",
"67.215.65.132" => "hit-nxdomain.opendns.com",
"67.215.65.133" => "hit-phish.opendns.com",
"67.215.65.134" => "hit-servfail.opendns.com",
"67.215.65.135" => "block.opendns.com",
"67.215.65.136" => "guide.opendns.com",
"67.215.65.137" => "phish.opendns.com",
"67.215.65.138" => "block.opendns.com",
"67.215.65.139" => "guide.opendns.com",
}
def initialize
@resolver = Net::DNS::Resolver.new(
:nameservers => DNS_HOSTS,
:recursive => true,
:retry => 10
)
end
def blocked?(hostname)
packet = @resolver.search(hostname)
packet.each_address do |ip|
puts "IP to str: #{ip.to_s}"
if BLOCKED_RESPONSES.keys.include?(ip.to_s)
return true
end
end
return false
end
end