-
Notifications
You must be signed in to change notification settings - Fork 51
/
dns_report.go
102 lines (93 loc) · 2.36 KB
/
dns_report.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// +build linux windows
package dnsproxy
import (
"context"
"fmt"
"net"
"time"
"go.aporeto.io/enforcerd/trireme-lib/collector"
"go.aporeto.io/enforcerd/trireme-lib/controller/pkg/pucontext"
)
var (
waitTimeBeforeReport = 5 * time.Minute
)
type dnsReport struct {
key string
contextID string
nameLookup string
error string
source collector.EndPoint
dest collector.EndPoint
namespace string
ips []string
}
func (p *Proxy) sendToCollector(report dnsReport, count int) {
r := &collector.DNSRequestReport{
ContextID: report.contextID,
NameLookup: report.nameLookup,
Source: &report.source,
Destination: &report.dest,
Namespace: report.namespace,
Error: report.error,
Count: count,
Ts: time.Now(),
IPs: report.ips,
}
p.collector.CollectDNSRequests(r)
}
func (p *Proxy) reportDNSRequests(ctx context.Context, chreport chan dnsReport) {
dnsReports := map[string]int{}
sendReport := make(chan dnsReport)
deleteReport := make(chan dnsReport)
for {
select {
case r := <-chreport:
dnsReports[r.key]++
switch dnsReports[r.key] {
case 1:
// dispatch immediately
p.sendToCollector(r, 1)
go func(r dnsReport) {
<-time.After(waitTimeBeforeReport)
deleteReport <- r
}(r)
case 2:
go func(r dnsReport) {
<-time.After(waitTimeBeforeReport)
sendReport <- r
}(r)
}
case r := <-sendReport:
p.sendToCollector(r, dnsReports[r.key]-1)
delete(dnsReports, r.key)
case r := <-deleteReport:
if dnsReports[r.key] == 1 {
delete(dnsReports, r.key)
}
case <-ctx.Done():
return
}
}
}
func (p *Proxy) reportDNSLookup(name string, pucontext *pucontext.PUContext, srcIP net.IP, srcPort uint16, dnsIP net.IP, dnsPort uint16, ips []string, err string) {
p.chreports <- dnsReport{
contextID: pucontext.ID(),
nameLookup: name,
error: err,
namespace: pucontext.ManagementNamespace(),
source: collector.EndPoint{
IP: srcIP.String(),
Port: srcPort,
ID: pucontext.ManagementID(),
Type: collector.EndPointTypePU,
},
dest: collector.EndPoint{
IP: dnsIP.String(),
Port: dnsPort,
ID: pucontext.ManagementID(),
Type: collector.EndPointTypePU,
},
ips: ips,
key: fmt.Sprintf("%s:%s:%s:%s:%s:%s", pucontext.ID(), name, err, pucontext.ManagementNamespace(), srcIP.String(), pucontext.ManagementID()),
}
}