class PassiveDNS::Provider::CIRCL

Queries CIRCL.LU's passive DNS database Circl is aliased by CIRCL

Attributes

debug[RW]

:debug enables verbose logging to standard output

Public Class Methods

config_section_name() click to toggle source

Sets the configuration section name to “circl”

# File lib/passivedns/client/provider/circl.rb, line 18
def self.config_section_name
  "circl"
end
name() click to toggle source

Sets the modules self-reported name to “CIRCL”

# File lib/passivedns/client/provider/circl.rb, line 14
def self.name
  "CIRCL"
end
new(options={}) click to toggle source

You should either have a username+password or an authorization token to use this service

Example Instantiation

options = {
  :debug => true,
  "USERNAME" => "circl_user",
  "PASSWORD" => "circl_pass",
  "URL" => "https://www.circl.lu/pdns/query"
}

PassiveDNS::Provider::CIRCL.new(options)
# File lib/passivedns/client/provider/circl.rb, line 48
def initialize(options={})
  @debug = options[:debug] || false
  @timeout = options[:timeout] || 20
  @username = options["USERNAME"]
  @password = options["PASSWORD"]
  @auth_token = options["AUTH_TOKEN"]
  @url = options["URL"] || "https://www.circl.lu/pdns/query"
end
option_letter() click to toggle source

Sets the command line database argument to “c”

# File lib/passivedns/client/provider/circl.rb, line 22
def self.option_letter
  "c"
end

Public Instance Methods

lookup(label, limit=nil) click to toggle source

Takes a label (either a domain or an IP address) and returns an array of PassiveDNS::PDNSResult instances with the answers to the query

# File lib/passivedns/client/provider/circl.rb, line 59
def lookup(label, limit=nil)
  $stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
  recs = []
  Timeout::timeout(@timeout) {
    url = @url+"/"+label
    $stderr.puts "DEBUG: #{self.class.name} url = #{url}" if @debug
    begin
      url = URI.parse url
    rescue URI::InvalidURIError
      $stderr.puts "ERROR: Invalid address: #{url}"
      return recs
    end
    http = Net::HTTP.new(url.host, url.port)
    http.use_ssl = (url.scheme == 'https')
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
    http.verify_depth = 5
    request = Net::HTTP::Get.new(url.request_uri)
    request.add_field("User-Agent", "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}")
    if @username
      request.basic_auth(@username, @password)
    end
    if @auth_token
      request.add_field("Authorization", @auth_token)
    end
    t1 = Time.now
    0.upto(9) do
      response = http.request(request)
      body = response.body
      if body == "Rate Limit Exceeded"
        $stderr.puts "DEBUG: Rate Limit Exceeded. Retrying #{label}" if @debug
      else
        t2 = Time.now
        recs  = parse_json(response.body, label, t2-t1)
        break
      end
    end
    if limit
      recs[0,limit]
    else
      recs
    end
  }
rescue Timeout::Error
  $stderr.puts "#{self.class.name} lookup timed out: #{label}"
  recs
end

Private Instance Methods

parse_json(page,query,response_time=0) click to toggle source

parses the response of circl's JSON reply to generate an array of PDNSResult

# File lib/passivedns/client/provider/circl.rb, line 109
def parse_json(page,query,response_time=0)
   res = []
  page.split(/\n/).each do |line|
    row = JSON.parse(line)
    firstseen = Time.at(row['time_first'].to_i)
    lastseen = Time.at(row['time_last'].to_i)
    res << PDNSResult.new(self.class.name,response_time,
      row['rrname'], row['rdata'], row['rrtype'], 0, 
      firstseen, lastseen, row['count'], 'yellow')
  end
  res
rescue Exception => e
  $stderr.puts "#{self.class.name} Exception: #{e}"
  raise e
end