Skip to content

Commit a173c9a

Browse files
committed
Initial code-dump!
0.1.0 - release - hello world! - dnsrbl-exporter - supports monitoring servers and if they get listed in DNBLs/RBLs
0 parents  commit a173c9a

File tree

13 files changed

+804
-0
lines changed

13 files changed

+804
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dist

.goreleaser.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# This is an example goreleaser.yaml file with some sane defaults.
2+
# Make sure to check the documentation at http://goreleaser.com
3+
project_name: dnsbl_exporter
4+
5+
before:
6+
hooks:
7+
# you may remove this if you don't use vgo
8+
- go mod tidy
9+
# you may remove this if you don't need go generate
10+
- go generate ./...
11+
builds:
12+
- main: ./main.go
13+
binary: dnsbl-exporter
14+
ldflags: -s -w -X main.exporterVersion={{.Version}}
15+
goos:
16+
- darwin
17+
- freebsd
18+
- linux
19+
- windows
20+
env:
21+
- CGO_ENABLED=0
22+
archives:
23+
- files:
24+
- none*
25+
replacements:
26+
darwin: Darwin
27+
linux: Linux
28+
windows: Windows
29+
386: i386
30+
amd64: x86_64
31+
checksum:
32+
name_template: 'checksums.txt'
33+
snapshot:
34+
name_template: "{{ .Tag }}-next"
35+
changelog:
36+
sort: asc
37+
filters:
38+
exclude:
39+
- '^docs:'
40+
- '^test:'

LICENSE

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright 2019 Luzilla Capital GmbH
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.PHONY: build
2+
build:
3+
goreleaser --snapshot --rm-dist

README.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# dnsbl-exporter
2+
3+
This is a server which checks the configured hosts against various DNSBL (sometimes refered to as RBLs).
4+
5+
The idea is to scrape `/metrics` using Prometheus to create graphs, alerts, and so on.
6+
7+
**This is an early release. We accept all kinds of feedback - bug reports, PRs, code, docs, ... :)**
8+
9+
## Using
10+
11+
### Configuration
12+
13+
See `rbls.ini` and `targets.ini` files in this repository.
14+
15+
Otherwise:
16+
17+
```
18+
$ dnsbl-exporter -h
19+
...
20+
--config.dns-resolver value IP address of the resolver to use. (default: "127.0.0.1")
21+
--config.rbls value Configuration file which contains RBLs (default: "./rbls.ini")
22+
--config.targets value Configuration file which contains the targets to check. (default: "./targets.ini")
23+
--web.listen-address value Address to listen on for web interface and telemetry. (default: ":9211")
24+
--web.telemetry-path value Path under which to expose metrics. (default: "/metrics")
25+
--debug Enable more output (stdout)
26+
--help, -h show help
27+
--version, -V Print the version information.
28+
```
29+
30+
### Running
31+
32+
1. Go to [release](https://github.com/Luzilla/dnsbl_exporter/releases) and grab a release for your platform.
33+
1. Get `rbls.ini` and put it next to the binary.
34+
1. Get `targets.ini`, and customize. Or use the defaults.
35+
1. `./dnsrbl-exporter`
36+
37+
Go to http://127.0.0.1:9211/ in your browser.
38+
39+
### Caveat
40+
41+
In order to use this, a _proper_ DNS resolver is needed. Proper means: not Google, not Cloudflare, OpenDNS, etc..
42+
Instead use a resolver like Unbound.
43+
44+
To test on OSX, follow these steps:
45+
46+
```
47+
$ brew install unbound
48+
...
49+
$ sudo unbound -d -vvvv
50+
```
51+
(And leave the Terminal open — there will be ample queries and data for you to see and learn from.)
52+
53+
Verify Unbound is working and resolution is working:
54+
55+
```
56+
$ dig +short @127.0.0.1 spamhaus.org
57+
192.42.118.104
58+
```

collector/collector.go

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package collector
2+
3+
import (
4+
"github.com/prometheus/client_golang/prometheus"
5+
"github.com/prometheus/common/log"
6+
)
7+
8+
const namespace = "luzilla"
9+
const subsystem = "rbls"
10+
11+
// RblCollector object as a bridge to prometheus
12+
type RblCollector struct {
13+
configuredMetric *prometheus.Desc
14+
blacklistedMetric *prometheus.Desc
15+
errorsMetrics *prometheus.Desc
16+
listedMetric *prometheus.Desc
17+
rbls []string
18+
resolver string
19+
targets []string
20+
}
21+
22+
func buildFQName(metric string) string {
23+
return prometheus.BuildFQName(namespace, subsystem, metric)
24+
}
25+
26+
// NewRblCollector ... creates the collector
27+
func NewRblCollector(rbls []string, targets []string, resolver string) *RblCollector {
28+
return &RblCollector{
29+
configuredMetric: prometheus.NewDesc(
30+
buildFQName("used"),
31+
"The number of RBLs to check IPs against (configured via rbls.ini)",
32+
nil,
33+
nil,
34+
),
35+
blacklistedMetric: prometheus.NewDesc(
36+
buildFQName("ips_blacklisted"),
37+
"Blacklisted IPs",
38+
[]string{"rbl", "ip", "hostname"},
39+
nil,
40+
),
41+
errorsMetrics: prometheus.NewDesc(
42+
buildFQName("errors"),
43+
"The number of errors which occurred testing the RBLs",
44+
[]string{"rbl"},
45+
nil,
46+
),
47+
listedMetric: prometheus.NewDesc(
48+
buildFQName("listed"),
49+
"The number of listings in RBLs (this is bad)",
50+
[]string{"rbl"},
51+
nil,
52+
),
53+
rbls: rbls,
54+
resolver: resolver,
55+
targets: targets,
56+
}
57+
}
58+
59+
// Describe ...
60+
func (c *RblCollector) Describe(ch chan<- *prometheus.Desc) {
61+
ch <- c.configuredMetric
62+
ch <- c.blacklistedMetric
63+
}
64+
65+
// Collect ...
66+
func (c *RblCollector) Collect(ch chan<- prometheus.Metric) {
67+
// these are our targets to check
68+
hosts := c.targets
69+
70+
ch <- prometheus.MustNewConstMetric(
71+
c.configuredMetric,
72+
prometheus.GaugeValue,
73+
float64(len(c.rbls)),
74+
)
75+
76+
// this should be a map of blacklist and a counter
77+
listed := 0
78+
79+
for _, host := range hosts {
80+
81+
log.Debugln("Checking ...", host)
82+
83+
rbl := NewRbl(c.resolver)
84+
rbl.Update(host, c.rbls)
85+
86+
for _, result := range rbl.Results {
87+
// this is an "error" from the RBL
88+
if result.Error {
89+
log.Errorln(result.Text)
90+
}
91+
92+
metricValue := 0
93+
94+
if result.Listed {
95+
metricValue = 1
96+
listed = +1
97+
}
98+
99+
labelValues := []string{result.Rbl, result.Address, host}
100+
101+
if result.Error {
102+
ch <- prometheus.MustNewConstMetric(
103+
c.errorsMetrics,
104+
prometheus.GaugeValue,
105+
1,
106+
[]string{result.Rbl}...,
107+
)
108+
}
109+
110+
ch <- prometheus.MustNewConstMetric(
111+
c.blacklistedMetric,
112+
prometheus.GaugeValue,
113+
float64(metricValue),
114+
labelValues...,
115+
)
116+
}
117+
}
118+
119+
ch <- prometheus.MustNewConstMetric(
120+
c.listedMetric,
121+
prometheus.GaugeValue,
122+
float64(listed),
123+
[]string{"foo"}...,
124+
)
125+
}

0 commit comments

Comments
 (0)