Easier way to dnstap? (#1496)
* Easier way to dnstap? * Remove unnecessary function parameter from Tapper * golint * golint 2 * Proxy dnstap tests * README.md & doc * net.IP * Proxy test was incorrect * Small changes * Update README.md * Was not reporting dnstap errors + test * Wasn't working at all, now it's ok * Thanks Travis
This commit is contained in:
parent
f697b33283
commit
6bb08ffee4
12 changed files with 274 additions and 255 deletions
|
@ -1,157 +1,153 @@
|
|||
// Package msg helps to build a dnstap Message.
|
||||
package msg
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
tap "github.com/dnstap/golang-dnstap"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// Builder helps to build Data by being aware of the dnstap plugin configuration.
|
||||
// Builder helps to build a Dnstap message.
|
||||
type Builder struct {
|
||||
Full bool
|
||||
Data
|
||||
}
|
||||
|
||||
// AddrMsg parses the info of net.Addr and dns.Msg.
|
||||
func (b *Builder) AddrMsg(a net.Addr, m *dns.Msg) (err error) {
|
||||
err = b.RemoteAddr(a)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return b.Msg(m)
|
||||
}
|
||||
|
||||
// Msg parses the info of dns.Msg.
|
||||
func (b *Builder) Msg(m *dns.Msg) (err error) {
|
||||
if b.Full {
|
||||
err = b.Pack(m)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Data helps to build a dnstap Message.
|
||||
// It can be transformed into the actual Message using this package.
|
||||
type Data struct {
|
||||
Packed []byte
|
||||
SocketProto tap.SocketProtocol
|
||||
SocketFam tap.SocketFamily
|
||||
Address []byte
|
||||
Address net.IP
|
||||
Port uint32
|
||||
TimeSec uint64
|
||||
|
||||
err error
|
||||
}
|
||||
|
||||
// HostPort decodes into Data any string returned by dnsutil.ParseHostPortOrFile.
|
||||
func (d *Data) HostPort(addr string) error {
|
||||
// New returns a new Builder
|
||||
func New() *Builder {
|
||||
return &Builder{}
|
||||
}
|
||||
|
||||
// Addr adds the remote address to the message.
|
||||
func (b *Builder) Addr(remote net.Addr) *Builder {
|
||||
if b.err != nil {
|
||||
return b
|
||||
}
|
||||
|
||||
switch addr := remote.(type) {
|
||||
case *net.TCPAddr:
|
||||
b.Address = addr.IP
|
||||
b.Port = uint32(addr.Port)
|
||||
b.SocketProto = tap.SocketProtocol_TCP
|
||||
case *net.UDPAddr:
|
||||
b.Address = addr.IP
|
||||
b.Port = uint32(addr.Port)
|
||||
b.SocketProto = tap.SocketProtocol_UDP
|
||||
default:
|
||||
b.err = errors.New("unknown remote address type")
|
||||
return b
|
||||
}
|
||||
|
||||
if b.Address.To4() != nil {
|
||||
b.SocketFam = tap.SocketFamily_INET
|
||||
} else {
|
||||
b.SocketFam = tap.SocketFamily_INET6
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// Msg adds the raw DNS message to the dnstap message.
|
||||
func (b *Builder) Msg(m *dns.Msg) *Builder {
|
||||
if b.err != nil {
|
||||
return b
|
||||
}
|
||||
|
||||
b.Packed, b.err = m.Pack()
|
||||
return b
|
||||
}
|
||||
|
||||
// HostPort adds the remote address as encoded by dnsutil.ParseHostPortOrFile to the message.
|
||||
func (b *Builder) HostPort(addr string) *Builder {
|
||||
ip, port, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
b.err = err
|
||||
return b
|
||||
}
|
||||
p, err := strconv.ParseUint(port, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
b.err = err
|
||||
return b
|
||||
}
|
||||
d.Port = uint32(p)
|
||||
b.Port = uint32(p)
|
||||
|
||||
if ip := net.ParseIP(ip); ip != nil {
|
||||
d.Address = []byte(ip)
|
||||
b.Address = []byte(ip)
|
||||
if ip := ip.To4(); ip != nil {
|
||||
d.SocketFam = tap.SocketFamily_INET
|
||||
b.SocketFam = tap.SocketFamily_INET
|
||||
} else {
|
||||
d.SocketFam = tap.SocketFamily_INET6
|
||||
b.SocketFam = tap.SocketFamily_INET6
|
||||
}
|
||||
return nil
|
||||
return b
|
||||
}
|
||||
return errors.New("not an ip address")
|
||||
b.err = errors.New("not an ip address")
|
||||
return b
|
||||
}
|
||||
|
||||
// RemoteAddr parses the information about the remote address into Data.
|
||||
func (d *Data) RemoteAddr(remote net.Addr) error {
|
||||
switch addr := remote.(type) {
|
||||
case *net.TCPAddr:
|
||||
d.Address = addr.IP
|
||||
d.Port = uint32(addr.Port)
|
||||
d.SocketProto = tap.SocketProtocol_TCP
|
||||
case *net.UDPAddr:
|
||||
d.Address = addr.IP
|
||||
d.Port = uint32(addr.Port)
|
||||
d.SocketProto = tap.SocketProtocol_UDP
|
||||
default:
|
||||
return errors.New("unknown remote address type")
|
||||
}
|
||||
|
||||
if a := net.IP(d.Address); a.To4() != nil {
|
||||
d.SocketFam = tap.SocketFamily_INET
|
||||
} else {
|
||||
d.SocketFam = tap.SocketFamily_INET6
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Pack encodes the DNS message into Data.
|
||||
func (d *Data) Pack(m *dns.Msg) error {
|
||||
packed, err := m.Pack()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.Packed = packed
|
||||
return nil
|
||||
// Time adds the timestamp to the message.
|
||||
func (b *Builder) Time(ts time.Time) *Builder {
|
||||
b.TimeSec = uint64(ts.Unix())
|
||||
return b
|
||||
}
|
||||
|
||||
// ToClientResponse transforms Data into a client response message.
|
||||
func (d *Data) ToClientResponse() *tap.Message {
|
||||
func (b *Builder) ToClientResponse() (*tap.Message, error) {
|
||||
t := tap.Message_CLIENT_RESPONSE
|
||||
return &tap.Message{
|
||||
Type: &t,
|
||||
SocketFamily: &d.SocketFam,
|
||||
SocketProtocol: &d.SocketProto,
|
||||
ResponseTimeSec: &d.TimeSec,
|
||||
ResponseMessage: d.Packed,
|
||||
QueryAddress: d.Address,
|
||||
QueryPort: &d.Port,
|
||||
}
|
||||
SocketFamily: &b.SocketFam,
|
||||
SocketProtocol: &b.SocketProto,
|
||||
ResponseTimeSec: &b.TimeSec,
|
||||
ResponseMessage: b.Packed,
|
||||
QueryAddress: b.Address,
|
||||
QueryPort: &b.Port,
|
||||
}, b.err
|
||||
}
|
||||
|
||||
// ToClientQuery transforms Data into a client query message.
|
||||
func (d *Data) ToClientQuery() *tap.Message {
|
||||
func (b *Builder) ToClientQuery() (*tap.Message, error) {
|
||||
t := tap.Message_CLIENT_QUERY
|
||||
return &tap.Message{
|
||||
Type: &t,
|
||||
SocketFamily: &d.SocketFam,
|
||||
SocketProtocol: &d.SocketProto,
|
||||
QueryTimeSec: &d.TimeSec,
|
||||
QueryMessage: d.Packed,
|
||||
QueryAddress: d.Address,
|
||||
QueryPort: &d.Port,
|
||||
}
|
||||
SocketFamily: &b.SocketFam,
|
||||
SocketProtocol: &b.SocketProto,
|
||||
QueryTimeSec: &b.TimeSec,
|
||||
QueryMessage: b.Packed,
|
||||
QueryAddress: b.Address,
|
||||
QueryPort: &b.Port,
|
||||
}, b.err
|
||||
}
|
||||
|
||||
// ToOutsideQuery transforms the data into a forwarder or resolver query message.
|
||||
func (d *Data) ToOutsideQuery(t tap.Message_Type) *tap.Message {
|
||||
func (b *Builder) ToOutsideQuery(t tap.Message_Type) (*tap.Message, error) {
|
||||
return &tap.Message{
|
||||
Type: &t,
|
||||
SocketFamily: &d.SocketFam,
|
||||
SocketProtocol: &d.SocketProto,
|
||||
QueryTimeSec: &d.TimeSec,
|
||||
QueryMessage: d.Packed,
|
||||
ResponseAddress: d.Address,
|
||||
ResponsePort: &d.Port,
|
||||
}
|
||||
SocketFamily: &b.SocketFam,
|
||||
SocketProtocol: &b.SocketProto,
|
||||
QueryTimeSec: &b.TimeSec,
|
||||
QueryMessage: b.Packed,
|
||||
ResponseAddress: b.Address,
|
||||
ResponsePort: &b.Port,
|
||||
}, b.err
|
||||
}
|
||||
|
||||
// ToOutsideResponse transforms the data into a forwarder or resolver response message.
|
||||
func (d *Data) ToOutsideResponse(t tap.Message_Type) *tap.Message {
|
||||
func (b *Builder) ToOutsideResponse(t tap.Message_Type) (*tap.Message, error) {
|
||||
return &tap.Message{
|
||||
Type: &t,
|
||||
SocketFamily: &d.SocketFam,
|
||||
SocketProtocol: &d.SocketProto,
|
||||
ResponseTimeSec: &d.TimeSec,
|
||||
ResponseMessage: d.Packed,
|
||||
ResponseAddress: d.Address,
|
||||
ResponsePort: &d.Port,
|
||||
}
|
||||
SocketFamily: &b.SocketFam,
|
||||
SocketProtocol: &b.SocketProto,
|
||||
ResponseTimeSec: &b.TimeSec,
|
||||
ResponseMessage: b.Packed,
|
||||
ResponseAddress: b.Address,
|
||||
ResponsePort: &b.Port,
|
||||
}, b.err
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue