github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/enforcer/dnsproxy/dns_report.go (about)

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