Skip to content

Commit

Permalink
rest api: dump full list of clients ip and domains #21
Browse files Browse the repository at this point in the history
  • Loading branch information
dmachard committed Dec 12, 2021
1 parent 4ae0c5f commit 0087683
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 6 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,15 @@ incoming traffics. See [Configuration guide](doc/configuration.md).
- [x] [Use case 2: collect dnstap stream and get statistics usage with Prometheus/Grafana](https://dmachard.github.io/posts/0035-dnscollector-grafana-prometheus/)
- [x] [Use case 3: collect dnstap stream and log dns answers in JSON format](https://dmachard.github.io/posts/0042-dnscollector-dnstap-json-answers/)

## Openmetrics

## Metrics

| Metric | Description |
| ---- | ---- |
| xx | xx |
| dnscollector_qps | Number of queries per second received |
| dnscollector_requesters_total | Number of clients |
| dnscollector_domains_total | Number of domains observed |
| dnscollector_received_bytes_total | Total bytes received |
| dnscollector_sent_bytes_total | Total bytes sent |

## Benchmark

Expand Down
33 changes: 32 additions & 1 deletion doc/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,38 @@ paths:
schema:
type: string
summary: Top suspicious domains list

/dump/requesters:
get:
parameters:
- in: query
name: stream
schema:
type: string
description: stream name
responses:
'200':
description: Return full list of requesters
content:
text/plain:
schema:
type: string
summary: Return full list of requesters
/dump/domains:
get:
parameters:
- in: query
name: stream
schema:
type: string
description: stream name
responses:
'200':
description: Return full list of domains
content:
text/plain:
schema:
type: string
summary: Return full list of domains
security: []
externalDocs:
url: 'https://github.com/dmachard/go-dnscollector'
46 changes: 46 additions & 0 deletions loggers/webserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,48 @@ func (s *Webserver) metricsHandler(w http.ResponseWriter, r *http.Request) {
}
}

func (s *Webserver) dumpRequestersHandler(w http.ResponseWriter, r *http.Request) {
if !s.BasicAuth(w, r) {
http.Error(w, "Not authorized", http.StatusUnauthorized)
return
}

w.Header().Set("Content-Type", "application/json")

switch r.Method {
case http.MethodGet:
stream, ok := r.URL.Query()["stream"]
if !ok || len(stream) < 1 {
stream = []string{"global"}
}
t := s.stats.GetClients(stream[0])
json.NewEncoder(w).Encode(t)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}

func (s *Webserver) dumpDomainsHandler(w http.ResponseWriter, r *http.Request) {
if !s.BasicAuth(w, r) {
http.Error(w, "Not authorized", http.StatusUnauthorized)
return
}

w.Header().Set("Content-Type", "application/json")

switch r.Method {
case http.MethodGet:
stream, ok := r.URL.Query()["stream"]
if !ok || len(stream) < 1 {
stream = []string{"global"}
}
t := s.stats.GetDomains(stream[0])
json.NewEncoder(w).Encode(t)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}

func (s *Webserver) topRequestersHandler(w http.ResponseWriter, r *http.Request) {
if !s.BasicAuth(w, r) {
http.Error(w, "Not authorized", http.StatusUnauthorized)
Expand Down Expand Up @@ -527,6 +569,7 @@ func (s *Webserver) ListenAndServe() {
mux := http.NewServeMux()
mux.HandleFunc("/metrics", s.metricsHandler)
mux.HandleFunc("/reset", s.resetHandler)

mux.HandleFunc("/top/requesters", s.topRequestersHandler)
mux.HandleFunc("/top/requesters/suspicious", s.topSuspiciousClientsHandler)
mux.HandleFunc("/top/firstleveldomains", s.topAllFirstLevelDomainsHandler)
Expand All @@ -535,6 +578,9 @@ func (s *Webserver) ListenAndServe() {
mux.HandleFunc("/top/domains/slow", s.topSlowDomainsHandler)
mux.HandleFunc("/top/domains/suspicious", s.topSuspiciousDomainsHandler)

mux.HandleFunc("/dump/requesters", s.dumpRequestersHandler)
mux.HandleFunc("/dump/domains", s.dumpDomainsHandler)

var err error
var listener net.Listener
addrlisten := s.config.Loggers.WebServer.ListenIP + ":" + strconv.Itoa(s.config.Loggers.WebServer.ListenPort)
Expand Down
24 changes: 24 additions & 0 deletions subprocessors/statistics.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,27 @@ func (c *StatsStreams) GetTopIpProto(identity string) (ret []topmap.TopMapItem)

return v.GetTopIpProto()
}

func (c *StatsStreams) GetClients(identity string) (ret map[string]int) {
c.RLock()
defer c.RUnlock()

v, found := c.streams[identity]
if !found {
return map[string]int{}
}

return v.GetClients()
}

func (c *StatsStreams) GetDomains(identity string) (ret map[string]int) {
c.RLock()
defer c.RUnlock()

v, found := c.streams[identity]
if !found {
return map[string]int{}
}

return v.GetDomains()
}
30 changes: 28 additions & 2 deletions subprocessors/statsperstream.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ type Counters struct {
type StatsPerStream struct {
config *dnsutils.Config

total Counters
total Counters

firstleveldomains map[string]int
firstleveldomainstop *topmap.TopMap
qnames map[string]int
Expand All @@ -87,7 +88,8 @@ type StatsPerStream struct {
transportstop *topmap.TopMap
ipproto map[string]int
ipprototop *topmap.TopMap
commonQtypes map[string]bool

commonQtypes map[string]bool
sync.RWMutex
}

Expand Down Expand Up @@ -634,3 +636,27 @@ func (c *StatsPerStream) GetTopIpProto() (ret []topmap.TopMapItem) {

return c.ipprototop.Get()
}

func (c *StatsPerStream) GetClients() (ret map[string]int) {
c.RLock()
defer c.RUnlock()

retMap := map[string]int{}
for k, v := range c.clients {
retMap[k] = v
}

return retMap
}

func (c *StatsPerStream) GetDomains() (ret map[string]int) {
c.RLock()
defer c.RUnlock()

retMap := map[string]int{}
for k, v := range c.qnames {
retMap[k] = v
}

return retMap
}

0 comments on commit 0087683

Please sign in to comment.