Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start playing with dnstap #55

Open
wants to merge 45 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
13049cd
start playing with dnstap within go-audit
alanhlam Sep 27, 2018
0777fd7
make this way simpler
alanhlam Sep 28, 2018
2d6f70a
wip
alanhlam Sep 28, 2018
abcee0c
get message response ip and name
alanhlam Sep 28, 2018
9598dec
add a simple cache
alanhlam Sep 28, 2018
86b6f04
remove duplicate return
alanhlam Sep 28, 2018
dbaa55c
make go-audit run again
alanhlam Sep 28, 2018
32b986a
add dns map
alanhlam Sep 30, 2018
403172f
wip and now working
alanhlam Oct 1, 2018
faf25c4
exited prior
alanhlam Oct 2, 2018
5143465
remove fatals
alanhlam Oct 2, 2018
ae25aa6
minor change to error return and print
alanhlam Oct 2, 2018
a209fc2
remove trailing .
alanhlam Oct 2, 2018
433d3ef
check saddr if type ipv4
alanhlam Oct 2, 2018
c72a6db
minor
alanhlam Oct 2, 2018
601f9f7
some refactoring
alanhlam Oct 5, 2018
65ac373
try at 180ms delay on audit type message 1306
alanhlam Oct 5, 2018
588946b
make current tests work with dnstap
alanhlam Oct 10, 2018
fc1f10b
this may work, maybe
alanhlam Oct 11, 2018
ba3909f
remove the sleep
alanhlam Oct 11, 2018
3056711
defer listener close and check if dnstap is configured
alanhlam Oct 11, 2018
e8e9d84
add constants and address some comments
alanhlam Oct 11, 2018
b7006c9
remove the fmt and use net.IP
alanhlam Oct 11, 2018
c1832ce
typo
alanhlam Oct 11, 2018
f858ff9
replace with bigcache
alanhlam Oct 12, 2018
8ee9694
add dbg messages
alanhlam Oct 12, 2018
64f1850
maybe this is better
alanhlam Oct 15, 2018
3f4c0e8
put this back to how it was
alanhlam Oct 15, 2018
c13de03
update vendor.json
alanhlam Oct 15, 2018
2109185
update external dep
alanhlam Oct 15, 2018
640e726
just run complete when eoe and no lookups are waiting
alanhlam Oct 16, 2018
cf5e647
refactor, maybe this is better
alanhlam Oct 16, 2018
8d466ee
change cache settings
alanhlam Oct 20, 2018
e84a593
refactor more
alanhlam Oct 24, 2018
969ef23
extend marshaller
alanhlam Oct 24, 2018
9e61017
why does this not get the first lookup
alanhlam Oct 27, 2018
24e49b2
working with removed 1320
alanhlam Oct 28, 2018
35d5c8f
don't add msg if its eoe
alanhlam Oct 29, 2018
900a101
get rid of port, back to ip-->host map
alanhlam Nov 6, 2018
4f05b80
add options for cache and dnstap enabled
alanhlam Nov 6, 2018
827394e
update go-audit config
alanhlam Nov 6, 2018
ca0d5c6
set option for socket owner
alanhlam Nov 7, 2018
6e60639
minor refactoring
alanhlam Nov 26, 2018
a81587f
ugh, return err
alanhlam Nov 26, 2018
0c8907a
minor changes
alanhlam Nov 26, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"errors"
"flag"
"fmt"
"github.com/allegro/bigcache"
"github.com/spf13/viper"
"log"
"log/syslog"
"os"
Expand All @@ -14,8 +16,6 @@ import (
"strconv"
"strings"
"syscall"

"github.com/spf13/viper"
)

var l = log.New(os.Stdout, "", 0)
Expand Down Expand Up @@ -339,10 +339,13 @@ func main() {
}

nlClient, err := NewNetlinkClient(config.GetInt("socket_buffer.receive"))

if err != nil {
el.Fatal(err)
}

dnstapEnabled := config.GetBool("dnstap.enabled")

marshaller := NewAuditMarshaller(
writer,
uint16(config.GetInt("events.min")),
Expand All @@ -355,6 +358,27 @@ func main() {

l.Printf("Started processing events in the range [%d, %d]\n", config.GetInt("events.min"), config.GetInt("events.max"))

var dnstapClient *DnsTapClient

if dnstapEnabled {
cacheCfg := bigcache.Config{
LifeWindow: config.GetDuration("dnstap.record_ttl"),
HardMaxCacheSize: config.GetInt("dnstap.max_cache_size"),
MaxEntrySize: 96,
MaxEntriesInWindow: 1024,
Shards: 256,
}

DnsMarshaller := NewDnsAuditMarshaller(marshaller, cacheCfg)

dnstapClient, err = NewDnsTapClient(config, DnsMarshaller)
if err != nil {
el.Fatal(err)
}

go dnstapClient.Receive()
}

//Main loop. Get data from netlink and send it to the json lib for processing
for {
msg, err := nlClient.Receive()
Expand All @@ -367,6 +391,11 @@ func main() {
continue
}

marshaller.Consume(msg)
if dnstapClient != nil {
dnstapClient.DnsAuditMarshaller.Consume(msg)
} else {
marshaller.Consume(msg)
}

}
}
2 changes: 1 addition & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"sync/atomic"
"syscall"
"time"
"fmt"
)

// Endianness is an alias for what we assume is the current machine endianness
Expand Down
154 changes: 154 additions & 0 deletions ext_dnstap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package main

import (
"fmt"
"net"
"os"
"os/user"
"strconv"
"strings"

"github.com/dnstap/golang-dnstap"
"github.com/farsightsec/golang-framestream"
"github.com/golang/protobuf/proto"
"github.com/miekg/dns"
"github.com/spf13/viper"
)

type DnsTapClient struct {
Listener net.Listener
DnsAuditMarshaller *DnsAuditMarshaller
}

func NewDnsTapClient(config *viper.Viper, am *DnsAuditMarshaller) (*DnsTapClient, error) {
socket := config.GetString("dnstap.socket")
os.Remove(socket)

listener, err := net.Listen("unix", socket)
if err != nil {
return nil, fmt.Errorf("Listen error: %s", err)
}

socketOwner := config.GetString("dnstap.socket_owner")

err = chown(socketOwner, socket)

if err != nil {
el.Fatal(err)
}

d := &DnsTapClient{
Listener: listener,
DnsAuditMarshaller: am,
}
el.Printf("Started dnstap listener, opened input socket: %s", socket)
return d, nil
}

func chown(socketOwner string, socket string) error {
u, err := user.Lookup(socketOwner)
if err != nil {
return fmt.Errorf("Could not find uid for user %s. Error: %s", socketOwner, err)
}

uid, err := strconv.ParseInt(u.Uid, 10, 32)
if err != nil {
return fmt.Errorf("Found uid could not be parsed. Error: %s", err)
}

g, err := user.LookupGroup(socketOwner)
if err != nil {
return fmt.Errorf("Could not find gid for group %s. Error: %s", socketOwner, err)
}

gid, err := strconv.ParseInt(g.Gid, 10, 32)
if err != nil {
return fmt.Errorf("Found gid could not be parsed. Error: %s", err)
}

if err = os.Chown(socket, int(uid), int(gid)); err != nil {
return fmt.Errorf("Could not chown output file. Error: %s", err)
}
return nil
}

func (d *DnsTapClient) Receive() {
defer d.Listener.Close()
for {
conn, err := d.Listener.Accept()
if err != nil {
el.Printf("net.Listener.Accept() failed: %s\n", err)
continue
}
go d.Decode(conn)
}
}

func (d *DnsTapClient) Decode(conn net.Conn) {
decoderOptions := &framestream.DecoderOptions{
ContentType: []byte("protobuf:dnstap.Dnstap"),
Bidirectional: true,
}
dec, err := framestream.NewDecoder(conn, decoderOptions)
if err != nil {
el.Printf("framestream.NewDecoder failed: %s\n", err)
}
for {
frame, err := dec.Decode()
if err != nil {
el.Printf("framestream.Decoder.Decode() failed: %s\n", err)
break
}
dt := &dnstap.Dnstap{}
if err := proto.Unmarshal(frame, dt); err != nil {
el.Printf("dnstap.DnsOutput: proto.Unmarshal() failed: %s\n", err)
break
}
if dt.Message.ResponseMessage != nil {
d.cache(dt)
}
}
}

func (d *DnsTapClient) cache(dt *dnstap.Dnstap) {
m := new(dns.Msg)
err := m.Unpack(dt.Message.ResponseMessage)
if err != nil {
el.Printf("msg.Unpack() failed: %s \n", err)
} else {
for i, r := range m.Answer {
host := strings.TrimRight(r.Header().Name, ".")
var record string
switch m.Answer[i].Header().Rrtype {
case dns.TypeA:
record = m.Answer[i].(*dns.A).A.String()
d.DnsAuditMarshaller.cache.Set(record, []byte(host))
case dns.TypeAAAA:
record = m.Answer[i].(*dns.AAAA).AAAA.String()
d.DnsAuditMarshaller.cache.Set(record, []byte(host))
case dns.TypeCNAME:
record := m.Answer[i].(*dns.CNAME).Target
d.DnsAuditMarshaller.cache.Set(record, []byte(host))
}
if seq, ok := d.DnsAuditMarshaller.waitingForDNS[record]; ok {
if msg, ok := d.DnsAuditMarshaller.msgs[seq]; ok {
if !d.DnsAuditMarshaller.GotDNS[seq] && d.DnsAuditMarshaller.GotSaddr[seq] {
d.DnsAuditMarshaller.getDNS(msg)
}
d.DnsAuditMarshaller.completeMessage(seq)
}
delete(d.DnsAuditMarshaller.waitingForDNS, record)
}

}
}
}

func (dnsAm *DnsAuditMarshaller) getDNS(val *AuditMessageGroup) (ip string, host []byte) {
for _, msg := range val.Msgs {
if msg.Type == SOCKADDR {
ip, host = dnsAm.mapDns(msg)
}
}
return ip, host
}
Loading