2021-05-09 14:39:21 +02:00
|
|
|
# vim: set noet sw=2 ts=2 sts=2:
|
2018-12-14 14:58:11 +01:00
|
|
|
require 'prometheus/client'
|
|
|
|
require 'prometheus/client/formats/text'
|
|
|
|
require 'net/dns'
|
2021-05-09 14:39:21 +02:00
|
|
|
require 'ostruct'
|
|
|
|
|
|
|
|
class DnsblCollector
|
|
|
|
class <<self
|
|
|
|
attr_reader :blacklists, :resolver, :registry
|
|
|
|
|
|
|
|
def load_config file = nil
|
|
|
|
config = YAML.load_file file || './config.yml'
|
|
|
|
self.blacklists = config['blacklists']
|
|
|
|
self.resolver = config['resolver']
|
|
|
|
end
|
2018-12-14 14:58:11 +01:00
|
|
|
|
2021-05-09 14:39:21 +02:00
|
|
|
def blacklists= lists
|
|
|
|
@blacklists =
|
|
|
|
lists.map do |bl|
|
|
|
|
case bl
|
|
|
|
when String then {blacklist: bl}
|
|
|
|
when Hash then bl
|
|
|
|
else raise ConfigError, "Unexpected Element in blacklists: #{bl}"
|
|
|
|
end
|
2018-12-14 14:58:11 +01:00
|
|
|
end
|
2021-05-09 14:39:21 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
def resolver= resolver_cnf
|
|
|
|
@resolver =
|
|
|
|
case resolver_cnf
|
|
|
|
when Net::DNS::Resolver then resolver_cnf
|
|
|
|
when Hash then Net::DNS::Resolver.new resolver_cnf
|
|
|
|
else
|
|
|
|
raise ConfigError, "DnsblCollector.resolver= expects a Net::DNS::Resolver or a resolver-config as Hash"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def registry= registry
|
|
|
|
@registry = registry
|
2021-05-09 17:24:01 +02:00
|
|
|
@registry.counter :dnsbl_query_error_count, docstring: 'Errors while query for blacklist', labels: %i[blacklist]
|
2021-05-09 14:39:21 +02:00
|
|
|
@registry.counter :dnsbl_query_blacklist_duration_sum, docstring: 'Total duration for querieng this blacklist', labels: %i[blacklist]
|
|
|
|
@registry.counter :dnsbl_query_blacklist_count, docstring: 'Total count of queries this blacklist', labels: %i[blacklist]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-05-09 20:38:37 +02:00
|
|
|
# The general Registry for the process.
|
|
|
|
# It stores not request-related metrices.
|
2021-05-09 14:39:21 +02:00
|
|
|
self.registry = Prometheus::Client::Registry.new
|
|
|
|
|
2021-05-09 20:38:37 +02:00
|
|
|
# @registry stores only request-related metrices.
|
2021-05-09 14:39:21 +02:00
|
|
|
attr_reader :lists, :registry, :configfile, :resolver, :metrics
|
|
|
|
|
|
|
|
def initialize registry: nil
|
|
|
|
@registry = registry || Prometheus::Client::Registry.new
|
2021-05-09 17:24:01 +02:00
|
|
|
@registry.gauge :dnsbl_listed, docstring: 'IP listed currently on Blacklist', labels: %i[blacklist]
|
2021-05-09 14:39:21 +02:00
|
|
|
@metrics = OpenStruct.new @registry.instance_variable_get( :@metrics).merge( self.class.registry.instance_variable_get( :@metrics))
|
2018-12-14 14:58:11 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def collect ip
|
|
|
|
prefix = ip.send :_reverse
|
|
|
|
ip = ip.to_s
|
2021-05-09 14:39:21 +02:00
|
|
|
todo = self.class.blacklists.sort{|_|rand}
|
|
|
|
resolver = self.class.resolver
|
2018-12-14 14:58:11 +01:00
|
|
|
10.times.map do
|
|
|
|
Thread.new do
|
2021-05-09 14:39:21 +02:00
|
|
|
while bl = todo.pop
|
|
|
|
name, b = bl[:blacklist], Time.now
|
2018-12-14 14:58:11 +01:00
|
|
|
begin
|
2021-05-09 14:39:21 +02:00
|
|
|
r = resolver.search( "#{prefix}.#{name}", Net::DNS::A).answer.empty?
|
2021-05-09 17:24:01 +02:00
|
|
|
@metrics.dnsbl_listed.set r ? 0 : 1, labels: {blacklist: name}
|
2018-12-14 14:58:11 +01:00
|
|
|
rescue Net::DNS::Resolver::NoResponseError
|
2021-05-09 17:24:01 +02:00
|
|
|
@metrics.dnsbl_query_error_count.increment labels: {blacklist: name}
|
2018-12-14 14:58:11 +01:00
|
|
|
end
|
2021-05-09 14:39:21 +02:00
|
|
|
dur = Time.now-b
|
|
|
|
@metrics.dnsbl_query_blacklist_duration_sum.increment by: dur, labels: {blacklist: name}
|
|
|
|
@metrics.dnsbl_query_blacklist_count.increment labels: {blacklist: name}
|
2018-12-14 14:58:11 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end.each &:join
|
|
|
|
end
|
|
|
|
end
|