105 lines
1.9 KiB
Ruby
105 lines
1.9 KiB
Ruby
require 'resolv'
|
|
|
|
class DNSXLCheck
|
|
|
|
class Resolver
|
|
def self.search(query)
|
|
begin
|
|
Resolv.getaddress(query)
|
|
true
|
|
rescue Resolv::ResolvError
|
|
false
|
|
end
|
|
end
|
|
end
|
|
|
|
IP_REGEXP = /\A(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\z/
|
|
DEFAULT_THRESHOLD = 0.33
|
|
|
|
def self.create_from_list(list)
|
|
dnsxl_check = DNSXLCheck.new
|
|
|
|
list.each do |entry|
|
|
dnsxl_check.add_list(entry.domain, entry.weight)
|
|
end
|
|
|
|
dnsxl_check
|
|
end
|
|
|
|
def test(ip)
|
|
if use_threshold?
|
|
test_with_threshold(ip)
|
|
else
|
|
test_strict(ip)
|
|
end
|
|
end
|
|
|
|
def test_with_threshold(ip)
|
|
return false if lists.empty?
|
|
|
|
search(ip)
|
|
final_score >= threshold
|
|
end
|
|
|
|
def test_strict(ip)
|
|
return false if lists.empty?
|
|
|
|
search(ip)
|
|
@score > 0
|
|
end
|
|
|
|
def use_threshold=(value)
|
|
@use_threshold = value == true
|
|
end
|
|
|
|
def use_threshold?
|
|
@use_threshold &&= true
|
|
end
|
|
|
|
def threshold=(threshold)
|
|
raise ArgumentError, "'threshold' value must be grather than 0 and less than or equal to 1" unless threshold > 0 && threshold <= 1
|
|
@threshold = threshold
|
|
end
|
|
|
|
def threshold
|
|
@threshold ||= DEFAULT_THRESHOLD
|
|
end
|
|
|
|
def add_list(domain, weight)
|
|
@lists ||= []
|
|
@lists << { domain: domain, weight: weight }
|
|
end
|
|
|
|
def lists
|
|
@lists ||= []
|
|
end
|
|
|
|
private
|
|
|
|
def search(ip)
|
|
raise ArgumentError, "'ip' value must be in #{IP_REGEXP} format" unless ip.match(IP_REGEXP)
|
|
|
|
@score = 0
|
|
|
|
reversed = reverse_ip(ip)
|
|
search_in_rbls(reversed)
|
|
end
|
|
|
|
def reverse_ip(ip)
|
|
ip.split('.').reverse.join('.')
|
|
end
|
|
|
|
def search_in_rbls(reversed_ip)
|
|
lists.each do |rbl|
|
|
query = "#{reversed_ip}.#{rbl[:domain]}"
|
|
@score += rbl[:weight] if Resolver.search(query)
|
|
end
|
|
end
|
|
|
|
def final_score
|
|
weights = lists.map{ |rbl| rbl[:weight] }.reduce(:+).to_i
|
|
return 0 if weights == 0
|
|
|
|
(@score.to_f / weights.to_f).round(2)
|
|
end
|
|
end
|