first working implementation
This commit is contained in:
commit
e008df4527
6
Gemfile
Normal file
6
Gemfile
Normal file
|
@ -0,0 +1,6 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'net-dns'
|
||||
gem 'prometheus-client'
|
||||
gem 'rack'
|
||||
gem 'puma'
|
21
Gemfile.lock
Normal file
21
Gemfile.lock
Normal file
|
@ -0,0 +1,21 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
net-dns (0.9.0)
|
||||
prometheus-client (0.8.0)
|
||||
quantile (~> 0.2.1)
|
||||
puma (3.12.0)
|
||||
quantile (0.2.1)
|
||||
rack (2.0.6)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
net-dns
|
||||
prometheus-client
|
||||
puma
|
||||
rack
|
||||
|
||||
BUNDLED WITH
|
||||
1.13.6
|
28
config.ru
Normal file
28
config.ru
Normal file
|
@ -0,0 +1,28 @@
|
|||
require 'rack'
|
||||
require './dnsbl_exporter'
|
||||
|
||||
|
||||
run lambda {|env|
|
||||
begin
|
||||
req = Rack::Request.new env
|
||||
case req.path
|
||||
when '/metrics'
|
||||
collector = DnsblCollector.new
|
||||
target =
|
||||
begin
|
||||
target = IPAddr.new req.params['target']
|
||||
rescue IPAddr::AddressFamilyError
|
||||
return [400, {"Content-Type" => "text/plain"}, ["Valid target-IP-Address expected.\n"]]
|
||||
end
|
||||
collector.collect target
|
||||
[200, {"Content-Type" => "text/plain"}, [
|
||||
Prometheus::Client::Formats::Text.marshal( collector.prometheus)
|
||||
]]
|
||||
else
|
||||
[404, {"Content-Type" => "text/plain"}, ["Not found.\nYou want to try /metrics?\n"]]
|
||||
end
|
||||
rescue
|
||||
STDERR.puts "#$! (#{$!.class})", $!.backtrace
|
||||
[500, {"Content-Type" => "text/plain"}, ["Server-error.\n"]]
|
||||
end
|
||||
}
|
62
config.yml
Normal file
62
config.yml
Normal file
|
@ -0,0 +1,62 @@
|
|||
# vim: set et sw=2 ts=2 sts=2:
|
||||
---
|
||||
resolver:
|
||||
nameservers: 8.8.8.8
|
||||
blacklists:
|
||||
- all.s5h.net
|
||||
- b.barracudacentral.org
|
||||
- bl.emailbasura.org
|
||||
- bl.spamcannibal.org
|
||||
- bl.spamcop.net
|
||||
- blacklist.woody.ch
|
||||
- bogons.cymru.com
|
||||
- cbl.abuseat.org
|
||||
- cdl.anti-spam.org.cn
|
||||
- combined.abuse.ch
|
||||
- db.wpbl.info
|
||||
- dnsbl-1.uceprotect.net
|
||||
- dnsbl-2.uceprotect.net
|
||||
- dnsbl-3.uceprotect.net
|
||||
- dnsbl.anticaptcha.net
|
||||
- dnsbl.dronebl.org
|
||||
- dnsbl.inps.de
|
||||
- dnsbl.sorbs.net
|
||||
- dnsbl.spfbl.net
|
||||
- drone.abuse.ch
|
||||
- duinv.aupads.org
|
||||
- dul.dnsbl.sorbs.net
|
||||
- dyna.spamrats.com
|
||||
- dynip.rothen.com
|
||||
- http.dnsbl.sorbs.net
|
||||
- ips.backscatterer.org
|
||||
- ix.dnsbl.manitu.net
|
||||
- korea.services.net
|
||||
- misc.dnsbl.sorbs.net
|
||||
- noptr.spamrats.com
|
||||
- orvedb.aupads.org
|
||||
- pbl.spamhaus.org
|
||||
- proxy.bl.gweep.ca
|
||||
- psbl.surriel.com
|
||||
- relays.bl.gweep.ca
|
||||
- relays.nether.net
|
||||
- sbl.spamhaus.org
|
||||
- short.rbl.jp
|
||||
- singular.ttk.pte.hu
|
||||
- smtp.dnsbl.sorbs.net
|
||||
- socks.dnsbl.sorbs.net
|
||||
- spam.abuse.ch
|
||||
- spam.dnsbl.anonmails.de
|
||||
- spam.dnsbl.sorbs.net
|
||||
- spam.spamrats.com
|
||||
- spambot.bls.digibase.ca
|
||||
- spamrbl.imp.ch
|
||||
- spamsources.fabel.dk
|
||||
- ubl.lashback.com
|
||||
- ubl.unsubscore.com
|
||||
- virus.rbl.jp
|
||||
- web.dnsbl.sorbs.net
|
||||
- wormrbl.imp.ch
|
||||
- xbl.spamhaus.org
|
||||
- z.mailspike.net
|
||||
- zen.spamhaus.org
|
||||
- zombie.dnsbl.sorbs.net
|
54
dnsbl_exporter.rb
Normal file
54
dnsbl_exporter.rb
Normal file
|
@ -0,0 +1,54 @@
|
|||
require 'prometheus/client'
|
||||
require 'prometheus/client/formats/text'
|
||||
require 'net/dns'
|
||||
require 'yaml'
|
||||
|
||||
class DnsblCollector
|
||||
attr_reader :lists, :prometheus, :configfile, :resolver, :metrics
|
||||
|
||||
def initialize prometheus: nil, configfile: nil
|
||||
@configfile = configfile || 'config.yml'
|
||||
@prometheus = prometheus || Prometheus::Client.registry
|
||||
%i[dnsbl_listed dnsbl_query_error].each {|m| @prometheus.unregister m }
|
||||
@metrics = {
|
||||
dnsbl_listed: @prometheus.gauge( :dnsbl_listed, 'IP listed currently on Blacklist'),
|
||||
dnsbl_query_error: @prometheus.counter( :dnsbl_query_error, 'Errors while query for blacklist'),
|
||||
}
|
||||
load_config
|
||||
end
|
||||
|
||||
def load_config
|
||||
config = YAML.load_file @configfile
|
||||
@resolver = config['resolver']
|
||||
@lists =
|
||||
config['blacklists'].map do |bl|
|
||||
case bl
|
||||
when String then {blacklist: bl}
|
||||
when Hash then bl
|
||||
else raise ConfigError, "Unexpected Element in blacklists: #{bl}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def collect ip
|
||||
prefix = ip.send :_reverse
|
||||
ip = ip.to_s
|
||||
dns = Net::DNS::Resolver.new @resolver
|
||||
todo = @lists.sort{|_|rand}
|
||||
durs = {}
|
||||
10.times.map do
|
||||
Thread.new do
|
||||
while bl = @lists.pop
|
||||
b = Time.now
|
||||
begin
|
||||
r = dns.search( "#{prefix}.#{bl[:blacklist]}", Net::DNS::A).answer.empty?
|
||||
@metrics[:dnsbl_listed].set( {blacklist: bl[:blacklist], target: ip}, r ? 0 : 1)
|
||||
rescue Net::DNS::Resolver::NoResponseError
|
||||
@metrics[:dnsbl_query_error].increment( {blacklist: bl[:blacklist], target: ip})
|
||||
end
|
||||
durs[bl[:blacklist]] = Time.now-b
|
||||
end
|
||||
end
|
||||
end.each &:join
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue