github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/enforcer/dnsproxy/dns_windows.go (about) 1 // +build windows 2 3 package dnsproxy 4 5 import ( 6 "context" 7 "errors" 8 "net" 9 "sync" 10 "syscall" 11 12 "github.com/miekg/dns" 13 "go.aporeto.io/enforcerd/trireme-lib/collector" 14 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/flowtracking" 15 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/ipsetmanager" 16 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/pucontext" 17 "go.aporeto.io/enforcerd/trireme-lib/policy" 18 "go.aporeto.io/enforcerd/trireme-lib/utils/cache" 19 "go.uber.org/zap" 20 ) 21 22 var clearWindowsDNSCacheFunc = clearWindowsDNSCache 23 24 // Proxy struct represents the object for dns proxy 25 type Proxy struct { 26 puFromID cache.DataStore 27 collector collector.EventCollector 28 contextIDs map[string]struct{} 29 chreports chan dnsReport 30 sync.RWMutex 31 } 32 33 // New creates an instance of the dns proxy 34 func New(ctx context.Context, puFromID cache.DataStore, conntrack flowtracking.FlowClient, c collector.EventCollector) *Proxy { 35 ch := make(chan dnsReport) 36 p := &Proxy{chreports: ch, puFromID: puFromID, collector: c, contextIDs: make(map[string]struct{})} 37 go p.reportDNSRequests(ctx, ch) 38 return p 39 } 40 41 // StartDNSServer starts the dns server on the port provided for contextID 42 func (p *Proxy) StartDNSServer(ctx context.Context, contextID, port string) error { 43 p.Lock() 44 defer p.Unlock() 45 p.contextIDs[contextID] = struct{}{} 46 return nil 47 } 48 49 // ShutdownDNS shuts down the dns server for contextID 50 func (p *Proxy) ShutdownDNS(contextID string) { 51 p.Lock() 52 defer p.Unlock() 53 delete(p.contextIDs, contextID) 54 } 55 56 // SyncWithPlatformCache is called on policy change. 57 // Clear the Windows DNS cache in order to guarantee proxying. 58 func (p *Proxy) SyncWithPlatformCache(ctx context.Context, pctx *pucontext.PUContext) error { 59 60 if pctx.UsesFQDN() { 61 return clearWindowsDNSCacheFunc() 62 } 63 return nil 64 } 65 66 // HandleDNSResponsePacket parses the DNS response and forwards the information to each PU based on policy 67 func (p *Proxy) HandleDNSResponsePacket(dnsPacketData []byte, sourceIP net.IP, sourcePort uint16, destIP net.IP, destPort uint16, puFromContextID func(string) (*pucontext.PUContext, error)) error { 68 69 // parse dns 70 msg := &dns.Msg{} 71 err := msg.Unpack(dnsPacketData) 72 if err != nil { 73 return err 74 } 75 76 // Make sure we have a question 77 if len(msg.Question) <= 0 { 78 return nil 79 } 80 81 var ips []string 82 for _, ans := range msg.Answer { 83 if ans.Header().Rrtype == dns.TypeA { 84 t, _ := ans.(*dns.A) 85 ips = append(ips, t.A.String()) 86 } 87 88 if ans.Header().Rrtype == dns.TypeAAAA { 89 t, _ := ans.(*dns.AAAA) 90 ips = append(ips, t.AAAA.String()) 91 } 92 } 93 94 // let each pu handle it 95 pus := make([]*pucontext.PUContext, 0, len(p.contextIDs)) 96 p.Lock() 97 for id := range p.contextIDs { 98 puCtx, err := puFromContextID(id) 99 if err != nil { 100 zap.L().Error("dnsproxy: DNS Proxy failed to get PUContext", zap.Error(err)) 101 continue 102 } 103 pus = append(pus, puCtx) 104 } 105 p.Unlock() 106 107 for _, puCtx := range pus { 108 ppps, _, err := puCtx.GetPolicyFromFQDN(msg.Question[0].Name) 109 if err == nil { 110 for _, ppp := range ppps { 111 ipsetmanager.V4().UpdateACLIPsets(ips, ppp.Policy.ServiceID) 112 ipsetmanager.V6().UpdateACLIPsets(ips, ppp.Policy.ServiceID) 113 if err = puCtx.UpdateApplicationACLs(policy.IPRuleList{{Addresses: ips, 114 Ports: ppp.Ports, 115 Protocols: ppp.Protocols, 116 Policy: ppp.Policy, 117 }}); err != nil { 118 zap.L().Error("dnsproxy: adding IP rule returned error", zap.Error(err)) 119 } 120 } 121 } 122 123 // source and destination is swapped because we are looking at response packet 124 p.reportDNSLookup(msg.Question[0].Name, puCtx, destIP, destPort, sourceIP, sourcePort, ips, "") 125 126 configureDependentServices(puCtx, msg.Question[0].Name, ips) 127 } 128 129 return nil 130 } 131 132 func clearWindowsDNSCache() error { 133 dnsAPIDll := syscall.NewLazyDLL("dnsapi.dll") 134 flushDNSCacheProc := dnsAPIDll.NewProc("DnsFlushResolverCache") 135 ret, _, err := flushDNSCacheProc.Call() 136 if err != syscall.Errno(0) { 137 return err 138 } 139 if ret == 0 { 140 return errors.New("DnsFlushResolverCache failed") 141 } 142 return nil 143 } 144 145 // Enforce starts enforcing policies for the given policy.PUInfo. 146 func (p *Proxy) Enforce(ctx context.Context, contextID string, puInfo *policy.PUInfo) error { 147 return nil 148 } 149 150 // Unenforce stops enforcing policy for the given IP. 151 func (p *Proxy) Unenforce(_ context.Context, contextID string) error { 152 return nil 153 }