Skip to content

Commit

Permalink
Add audit backend basic implementation; Add redis audit backend; Upda…
Browse files Browse the repository at this point in the history
…te README
  • Loading branch information
bn0ir committed Apr 15, 2019
1 parent 89cf763 commit 7b469fb
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 1 deletion.
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,33 @@ Domain-specific nameservers configuration, formatting keep compatible with Dnsma
More cases please refererence [dnsmasq-china-list](https://github.com/felixonmars/dnsmasq-china-list)


#### audit

Only redis storage backend is currently implemented.

Audit logs are in format:

```
{ "remoteaddr": "127.0.0.1", "domain": "domain.com", "qtype": "A", "timestamp": "2019-04-15T12:16:21.875492605Z" }
```

Backend uses lists to store logs in redis.

Logs grouped by hour.

Redis keys have format:

```
audit-YYYY-MM-DDTHH:00
```

Example request to get audit logs from redis:

```
LRANGE audit-2019-04-15T00:00 0 -1
```


#### cache

Only the local memory storage backend is currently implemented. The redis backend is in the todo list
Expand Down
77 changes: 77 additions & 0 deletions audit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package main

import (
"encoding/json"
"fmt"
"time"

"github.com/hoisie/redis"
)

const AUDIT_LOG_OUTPUT_BUFFER = 1024

type AuditLogger interface {
Run()
Write(mesg *AuditMesg)
}

type AuditMesg struct {
RemoteAddr string `json:"remoteaddr"`
Domain string `json:"domain"`
QType string `json:"qtype"`
Timestamp time.Time `json:"timestamp"`
}

func NewAuditMessage(remoteAddr string, domain string, qtype string) *AuditMesg {
return &AuditMesg{
RemoteAddr: remoteAddr,
Domain: domain,
QType: qtype,
Timestamp: time.Now(),
}
}

type RedisAuditLogger struct {
backend *redis.Client
mesgs chan *AuditMesg
expire int64
}

func NewRedisAuditLogger(rs RedisSettings, expire int64) AuditLogger {
rc := &redis.Client{Addr: rs.Addr(), Db: rs.DB, Password: rs.Password}
auditLogger := &RedisAuditLogger{
backend: rc,
mesgs: make(chan *AuditMesg, AUDIT_LOG_OUTPUT_BUFFER),
expire: expire,
}
go auditLogger.Run()
return auditLogger
}

func (rl *RedisAuditLogger) Run() {
for {
select {
case mesg := <-rl.mesgs:
jsonMesg, err := json.Marshal(mesg)
if err != nil {
logger.Error("Can't write to redis audit log: %v", err)
continue
}
redisKey := fmt.Sprintf("audit-%s:00", mesg.Timestamp.Format("2006-01-02T15"))
err = rl.backend.Rpush(redisKey, jsonMesg)
if err != nil {
logger.Error("Can't write to redis audit log: %v", err)
continue
}
_, err = rl.backend.Expire(redisKey, rl.expire)
if err != nil {
logger.Error("Can't set expiration for redis audit log: %v", err)
continue
}
}
}
}

func (rl *RedisAuditLogger) Write(mesg *AuditMesg) {
rl.mesgs <- mesg
}
5 changes: 5 additions & 0 deletions etc/godns.conf
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ file = "./godns.log"
level = "INFO" #DEBUG | INFO |NOTICE | WARN | ERROR


# [audit]
# backend option [redis|file]
# file backend not implemented yet
# backend = "redis"
# expire = 864000 # 10 days

[cache]
# backend option [memory|memcache|redis]
Expand Down
15 changes: 14 additions & 1 deletion handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type GODNSHandler struct {
resolver *Resolver
cache, negCache Cache
hosts Hosts
audit AuditLogger
}

func NewHandler() *GODNSHandler {
Expand Down Expand Up @@ -76,7 +77,14 @@ func NewHandler() *GODNSHandler {
hosts = NewHosts(settings.Hosts, settings.Redis)
}

return &GODNSHandler{resolver, cache, negCache, hosts}
var auditLogger AuditLogger

switch settings.Audit.Backend {
case "redis":
auditLogger = NewRedisAuditLogger(settings.Redis, settings.Audit.Expire)
}

return &GODNSHandler{resolver, cache, negCache, hosts, auditLogger}
}

func (h *GODNSHandler) do(Net string, w dns.ResponseWriter, req *dns.Msg) {
Expand All @@ -91,6 +99,11 @@ func (h *GODNSHandler) do(Net string, w dns.ResponseWriter, req *dns.Msg) {
}
logger.Info("%s lookup %s", remote, Q.String())

if h.audit != nil {
auditMesg := NewAuditMessage(remote.String(), Q.qname, Q.qtype)
h.audit.Write(auditMesg)
}

IPQuery := h.isIPQuery(q)

// Query hosts
Expand Down
6 changes: 6 additions & 0 deletions settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Settings struct {
Log LogSettings `toml:"log"`
Cache CacheSettings `toml:"cache"`
Hosts HostsSettings `toml:"hosts"`
Audit AuditSettings `toml:"audit"`
}

type ResolvSettings struct {
Expand Down Expand Up @@ -67,6 +68,11 @@ type LogSettings struct {
Level string
}

type AuditSettings struct {
Expire int64
Backend string
}

func (ls LogSettings) LogLevel() int {
l, ok := LogLevelMap[ls.Level]
if !ok {
Expand Down

0 comments on commit 7b469fb

Please sign in to comment.