Class: DNSBL::Client
- Inherits:
-
Object
- Object
- DNSBL::Client
- Defined in:
- lib/dnsbl/client.rb,
lib/dnsbl/client/version.rb
Overview
Client actually handles the sending of queries to a recursive DNS server and places any replies into DNSBLResults
Constant Summary collapse
- VERSION =
Current version of the dnsbl-client gem
"1.0.5"
Instance Method Summary collapse
-
#_encode_query(item, itemtype, domain, apikey = nil) ⇒ Object
converts an ip or a hostname into the DNS query packet requires to lookup the result.
-
#add_dnsbl(name, domain, type = 'ip', codes = {"0"=>"OK","127.0.0.2"=>"Blacklisted"}) ⇒ Object
allows the adding of a new DNSBL to the set of configured DNSBLs.
-
#dnsbls ⇒ Object
returns a list of DNSBL names currently configured.
-
#initialize(config = YAML.load(File.open(File.expand_path('../../../data', __FILE__)+"/dnsbl.yaml").read), two_level_tldfile = File.expand_path('../../../data', __FILE__)+"/two-level-tlds", three_level_tldfile = File.expand_path('../../../data', __FILE__)+"/three-level-tlds") ⇒ Client
constructor
initialize a new DNSBL::Client object the config file automatically points to a YAML file containing the list of DNSBLs and their return codes the two-level-tlds file lists most of the two level tlds, needed for hostname to domain normalization.
-
#lookup(item) ⇒ Object
returns an array of DNSBLResult.
-
#nameservers=(ns = Resolv::DNS::Config.new.nameservers) ⇒ Object
sets the nameservers used for performing DNS lookups in round-robin fashion.
-
#normalize(domain) ⇒ Object
Converts a hostname to the domain: e.g., www.google.com => google.com, science.somewhere.co.uk => somewhere.co.uk.
Constructor Details
#initialize(config = YAML.load(File.open(File.expand_path('../../../data', __FILE__)+"/dnsbl.yaml").read), two_level_tldfile = File.expand_path('../../../data', __FILE__)+"/two-level-tlds", three_level_tldfile = File.expand_path('../../../data', __FILE__)+"/three-level-tlds") ⇒ Client
initialize a new DNSBL::Client object the config file automatically points to a YAML file containing the list of DNSBLs and their return codes the two-level-tlds file lists most of the two level tlds, needed for hostname to domain normalization
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/dnsbl/client.rb', line 40 def initialize(config = YAML.load(File.open(File.('../../../data', __FILE__)+"/dnsbl.yaml").read), two_level_tldfile = File.('../../../data', __FILE__)+"/two-level-tlds", three_level_tldfile = File.('../../../data', __FILE__)+"/three-level-tlds") @dnsbls = config @two_level_tld = [] @three_level_tld = [] File.open(two_level_tldfile).readlines.each do |l| @two_level_tld << l.strip end File.open(three_level_tldfile).readlines.each do |l| @three_level_tld << l.strip end @sockets = [] config = Resolv::DNS::Config.new config.nameservers.each do |ip,port| sock = UDPSocket.new sock.connect(ip,port) @sockets << sock break # let's just the first nameserver in this version of the library end @socket_index = 0 end |
Instance Method Details
#_encode_query(item, itemtype, domain, apikey = nil) ⇒ Object
converts an ip or a hostname into the DNS query packet requires to lookup the result
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/dnsbl/client.rb', line 108 def _encode_query(item,itemtype,domain,apikey=nil) label = nil if itemtype == 'ip' label = item.split(/\./).reverse.join(".") elsif itemtype == 'domain' label = normalize(item) end lookup = "#{label}.#{domain}" if apikey lookup = "#{apikey}.#{lookup}" end txid = lookup.sum = Resolv::DNS::Message.new(txid) .rd = 1 .add_question(lookup,Resolv::DNS::Resource::IN::A) .encode end |
#add_dnsbl(name, domain, type = 'ip', codes = {"0"=>"OK","127.0.0.2"=>"Blacklisted"}) ⇒ Object
allows the adding of a new DNSBL to the set of configured DNSBLs
96 97 98 99 100 |
# File 'lib/dnsbl/client.rb', line 96 def add_dnsbl(name,domain,type='ip',codes={"0"=>"OK","127.0.0.2"=>"Blacklisted"}) @dnsbls[name] = codes @dnsbls[name]['domain'] = domain @dnsbls[name]['type'] = type end |
#dnsbls ⇒ Object
returns a list of DNSBL names currently configured
103 104 105 |
# File 'lib/dnsbl/client.rb', line 103 def dnsbls @dnsbls.keys end |
#lookup(item) ⇒ Object
returns an array of DNSBLResult
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/dnsbl/client.rb', line 129 def lookup(item) # if item is an array, use it, otherwise make it one items = item if item.is_a? String items = [item] end # place the results in the results array results = [] # for each ip or hostname items.each do |item| # sent is used to determine when we have all the answers sent = 0 # record the start time @starttime = Time.now.to_f # determine the type of query itemtype = (item =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) ? 'ip' : 'domain' # for each dnsbl that supports our type, create the DNS query packet and send it # rotate across our configured name servers and increment sent @dnsbls.each do |name,config| next if config['disabled'] next unless config['type'] == itemtype begin msg = _encode_query(item,itemtype,config['domain'],config['apikey']) @sockets[@socket_index].send(msg,0) @socket_index += 1 @socket_index %= @sockets.length sent += 1 rescue Exception => e puts e puts e.backtrace.join("\n") end end # while we still expect answers while sent > 0 # wait on the socket for maximally 1.5 seconds r,_,_ = IO.select(@sockets,nil,nil,1.5) # if we time out, break out of the loop break unless r # for each reply, decode it and receive results, decrement the pending answers r.each do |s| begin response = _decode_response(s.recv(4096)) results += response rescue Exception => e puts e puts e.backtrace.join("\n") end sent -= 1 end end end results end |
#nameservers=(ns = Resolv::DNS::Config.new.nameservers) ⇒ Object
sets the nameservers used for performing DNS lookups in round-robin fashion
64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/dnsbl/client.rb', line 64 def nameservers=(ns=Resolv::DNS::Config.new.nameservers) @sockets.each do |s| s.close end @sockets = [] ns.each do |ip,port| sock = UDPSocket.new sock.connect(ip,port) @sockets << sock break # let's just the first nameserver in this version of the library end @socket_index = 0 end |
#normalize(domain) ⇒ Object
Converts a hostname to the domain: e.g., www.google.com => google.com, science.somewhere.co.uk => somewhere.co.uk
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/dnsbl/client.rb', line 79 def normalize(domain) # strip off the protocol (\w{1,20}://), the URI (/), parameters (?), port number (:), and username (.*@) # then split into parts via the . parts = domain.gsub(/^\w{1,20}:\/\//,'').gsub(/[\/\?\:].*/,'').gsub(/.*?\@/,'').split(/\./) # grab the last two parts of the domain dom = parts[-2,2].join(".") # if the dom is in the two_level_tld list, then use three parts if @two_level_tld.index(dom) dom = parts[-3,3].join(".") end if @three_level_tld.index(dom) dom = parts[-4,4].join(".") end dom end |