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