The DNS Cache feature allows to tracee build an accurate image of dns and ip relations.
These relations can be queried in signatures through a data source.
Consider for your usecase, how many query trees would you like to store? If you will frequently check only a few addresses, consider lowering the size.
From the data-sources documentation, you'll see that searches use keys. It's a bit like looking up information with a specific tag (or a key=value storage).
The dns data source operates straightforwardly. Using string keys, which represent some network address (a domain or IP), you can fetch map[string]string values as shown below:
Any address found in the cache, and other related addresses, will be returned in the above structure. Particulary useful is the dns_root field, which will store the initial dns query which all other addresses derive from.
During the signature initialization, get the containers data source instance:
typee2eDnsDataSourcestruct{cbdetect.SignatureHandlerdnsDatadetect.DataSource}func(sig*e2eDnsDataSource)Init(ctxdetect.SignatureContext)error{sig.cb=ctx.CallbackdnsData,ok:=ctx.GetDataSource("tracee","dns")if!ok{returnerrors.New("dns data source not registered")}ifdnsData.Version()>1{returnfmt.Errorf("dns data source version not supported, please update this signature")}sig.dnsData=dnsDatareturnnil}
Then, to each event being handled, you will Get(), from the data source, the information needed.
func(sig*e2eDnsDataSource)OnEvent(eventprotocol.Event)error{eventObj,ok:=event.Payload.(trace.Event)if!ok{returnerrors.New("failed to cast event's payload")}switcheventObj.EventName{case"sched_process_exit":ifeventObj.Executable.Path!="/usr/bin/ping"{returnnil// irrelevant code path}dns,err:=sig.dnsData.Get("google.com")iferr!=nil{returnfmt.Errorf("failed to find dns data in data source: %v",err)}ipResults,ok:=dns["ip_addresses"].([]string)if!ok{returnerrors.New("failed to extract ip results")}iflen(ipResults)<1{returnerrors.New("ip results were empty")}dnsResults,ok:=dns["dns_queries"].([]string)if!ok{returnerrors.New("failed to extract dns results")}iflen(dnsResults)<1{returnerrors.New("dns results were empty")}ifdnsResults[0]!="google.com"{returnfmt.Errorf("bad dns query: %s",dnsResults[0])}m,_:=sig.GetMetadata()sig.cb(detect.Finding{SigMetadata:m,Event:event,Data:map[string]interface{}{},})}returnnil}
The above signatures shows usage of the feature in a test signature found in our own e2e tests. The test validates a ping command sent to google.com.