added support to resolve rdns from adguard (#14)

This commit is contained in:
Rahul Somasundaram 2021-09-09 10:55:02 +05:30 committed by GitHub
parent 07f558a92c
commit e75108942e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 72 additions and 20 deletions

View File

@ -24,6 +24,7 @@ type Config struct {
ServerPort string `config:"server_port"` ServerPort string `config:"server_port"`
Interval time.Duration `config:"interval"` Interval time.Duration `config:"interval"`
LogLimit string `config:"log_limit"` LogLimit string `config:"log_limit"`
RDnsEnabled bool `config:"rdns_enabled"`
} }
func getDefaultConfig() *Config { func getDefaultConfig() *Config {
@ -36,6 +37,7 @@ func getDefaultConfig() *Config {
ServerPort: "9617", ServerPort: "9617",
Interval: 10 * time.Second, Interval: 10 * time.Second,
LogLimit: "1000", LogLimit: "1000",
RDnsEnabled: true,
} }
} }

View File

@ -6,8 +6,10 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"net"
"net/http" "net/http"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/ebrianne/adguard-exporter/internal/metrics" "github.com/ebrianne/adguard-exporter/internal/metrics"
@ -15,28 +17,30 @@ import (
) )
var ( var (
port uint16 port uint16
statusURLPattern = "%s://%s:%d/control/status" statusURLPattern = "%s://%s:%d/control/status"
statsURLPattern = "%s://%s:%d/control/stats" statsURLPattern = "%s://%s:%d/control/stats"
logstatsURLPattern = "%s://%s:%d/control/querylog?limit=%s&response_status=\"all\"" logstatsURLPattern = "%s://%s:%d/control/querylog?limit=%s&response_status=\"all\""
m map[string]int resolveRDNSURLPattern = "%s://%s:%d/control/clients/find?%s"
m map[string]int
) )
// Client struct is a AdGuard client to request an instance of a AdGuard ad blocker. // Client struct is a AdGuard client to request an instance of a AdGuard ad blocker.
type Client struct { type Client struct {
httpClient http.Client httpClient http.Client
interval time.Duration interval time.Duration
logLimit string logLimit string
protocol string protocol string
hostname string hostname string
port uint16 port uint16
username string username string
password string password string
rdnsenabled bool
} }
// NewClient method initializes a new AdGuard client. // NewClient method initializes a new AdGuard client.
func NewClient(protocol, hostname, username, password, adport string, interval time.Duration, logLimit string) *Client { func NewClient(protocol, hostname, username, password, adport string, interval time.Duration, logLimit string, rdnsenabled bool) *Client {
temp, err := strconv.Atoi(adport) temp, err := strconv.Atoi(adport)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@ -57,6 +61,7 @@ func NewClient(protocol, hostname, username, password, adport string, interval t
return http.ErrUseLastResponse return http.ErrUseLastResponse
}, },
}, },
rdnsenabled: rdnsenabled,
} }
} }
@ -67,14 +72,14 @@ func (c *Client) Scrape() {
allstats := c.getStatistics() allstats := c.getStatistics()
//Set the metrics //Set the metrics
c.setMetrics(allstats.status, allstats.stats, allstats.logStats) c.setMetrics(allstats.status, allstats.stats, allstats.logStats, allstats.rdns)
log.Printf("New tick of statistics: %s", allstats.stats.ToString()) log.Printf("New tick of statistics: %s", allstats.stats.ToString())
} }
} }
// Function to set the prometheus metrics // Function to set the prometheus metrics
func (c *Client) setMetrics(status *Status, stats *Stats, logstats *LogStats) { func (c *Client) setMetrics(status *Status, stats *Stats, logstats *LogStats, rdns map[string]string) {
//Status //Status
var isRunning int = 0 var isRunning int = 0
if status.Running == true { if status.Running == true {
@ -110,7 +115,15 @@ func (c *Client) setMetrics(status *Status, stats *Stats, logstats *LogStats) {
for l := range stats.TopClients { for l := range stats.TopClients {
for source, value := range stats.TopClients[l] { for source, value := range stats.TopClients[l] {
if c.rdnsenabled && isValidIp(source) {
hostName, exists := rdns[source]
if exists {
metrics.TopClients.WithLabelValues(c.hostname, hostName).Set(float64(value))
continue
}
}
metrics.TopClients.WithLabelValues(c.hostname, source).Set(float64(value)) metrics.TopClients.WithLabelValues(c.hostname, source).Set(float64(value))
} }
} }
@ -181,6 +194,34 @@ func (c *Client) getStatistics() *AllStats {
allstats.stats = &stats allstats.stats = &stats
allstats.logStats = &logstats allstats.logStats = &logstats
if c.rdnsenabled {
var sb strings.Builder
for l := range stats.TopClients {
for source, _ := range stats.TopClients[l] {
sb.WriteString(fmt.Sprintf("ip%d=%s", l, source))
if l < len(stats.TopClients)-1 {
sb.WriteString("&")
}
}
}
rdnsURL := fmt.Sprintf(resolveRDNSURLPattern, c.protocol, c.hostname, c.port, sb.String())
body = c.MakeRequest(rdnsURL)
var results []map[string]interface{}
err = json.Unmarshal(body, &results)
if err != nil {
log.Println("Unable to unmarshal Reverse DNS", err)
}
rdnsData := make(map[string]string)
for _, result := range results {
for key := range result {
data := result[key].(map[string]interface{})
rdnsData[key] = data["name"].(string)
}
}
allstats.rdns = rdnsData
}
return &allstats return &allstats
} }
@ -227,3 +268,11 @@ func GetTlsConfig() *tls.Config {
InsecureSkipVerify: true, InsecureSkipVerify: true,
} }
} }
func isValidIp(ip string) bool {
if net.ParseIP(ip) == nil {
return false
} else {
return true
}
}

View File

@ -7,6 +7,7 @@ type AllStats struct {
status *Status status *Status
stats *Stats stats *Stats
logStats *LogStats logStats *LogStats
rdns map[string]string
} }
// Status struct is the Adguard statistics JSON API corresponding model. // Status struct is the Adguard statistics JSON API corresponding model.

View File

@ -26,14 +26,14 @@ func main() {
metrics.Init() metrics.Init()
initAdguardClient(conf.AdguardProtocol, conf.AdguardHostname, conf.AdguardUsername, conf.AdguardPassword, conf.AdguardPort, conf.Interval, conf.LogLimit) initAdguardClient(conf.AdguardProtocol, conf.AdguardHostname, conf.AdguardUsername, conf.AdguardPassword, conf.AdguardPort, conf.Interval, conf.LogLimit, conf.RDnsEnabled)
initHttpServer(conf.ServerPort) initHttpServer(conf.ServerPort)
handleExitSignal() handleExitSignal()
} }
func initAdguardClient(protocol, hostname, username, password, port string, interval time.Duration, logLimit string) { func initAdguardClient(protocol, hostname, username, password, port string, interval time.Duration, logLimit string, rdnsenabled bool) {
client := adguard.NewClient(protocol, hostname, username, password, port, interval, logLimit) client := adguard.NewClient(protocol, hostname, username, password, port, interval, logLimit, rdnsenabled)
go client.Scrape() go client.Scrape()
} }