From 6f95d05c59f748566aef792a025164f2490fa80f Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Fri, 23 Sep 2016 12:41:32 +0000 Subject: [PATCH 1/2] Add support for snooping DNS over TCP --- probe/endpoint/dns_snooper_linux_amd64.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/probe/endpoint/dns_snooper_linux_amd64.go b/probe/endpoint/dns_snooper_linux_amd64.go index 2c5b9dc760..8effef4ce9 100644 --- a/probe/endpoint/dns_snooper_linux_amd64.go +++ b/probe/endpoint/dns_snooper_linux_amd64.go @@ -111,12 +111,29 @@ func (s *DNSSnooper) Stop() { } } +// Gopacket doesn't provide direct support for DNS over TCP, see https://github.com/google/gopacket/issues/236 +type tcpWithDNSSupport struct { + tcp layers.TCP +} + +func (m *tcpWithDNSSupport) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { + return m.tcp.DecodeFromBytes(data, df) +} +func (m *tcpWithDNSSupport) CanDecode() gopacket.LayerClass { return m.tcp.CanDecode() } +func (m *tcpWithDNSSupport) NextLayerType() gopacket.LayerType { + if m.tcp.SrcPort == 53 || m.tcp.DstPort == 53 { + return layers.LayerTypeDNS + } + return m.tcp.NextLayerType() +} +func (m *tcpWithDNSSupport) LayerPayload() []byte { return m.tcp.LayerPayload() } + func (s *DNSSnooper) run() { var ( decodedLayers []gopacket.LayerType dns layers.DNS udp layers.UDP - tcp layers.TCP + tcp tcpWithDNSSupport ip4 layers.IPv4 ip6 layers.IPv6 eth layers.Ethernet From 326208c395166920ecd1424e42ec8dbfcac87377 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Fri, 23 Sep 2016 13:51:19 +0000 Subject: [PATCH 2/2] Skip DNS length field (only included over TCP) --- probe/endpoint/dns_snooper_linux_amd64.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/probe/endpoint/dns_snooper_linux_amd64.go b/probe/endpoint/dns_snooper_linux_amd64.go index 8effef4ce9..f642585ab4 100644 --- a/probe/endpoint/dns_snooper_linux_amd64.go +++ b/probe/endpoint/dns_snooper_linux_amd64.go @@ -112,6 +112,7 @@ func (s *DNSSnooper) Stop() { } // Gopacket doesn't provide direct support for DNS over TCP, see https://github.com/google/gopacket/issues/236 +// TODO: deal with TCP fragmentation and out-of-order segments type tcpWithDNSSupport struct { tcp layers.TCP } @@ -126,7 +127,15 @@ func (m *tcpWithDNSSupport) NextLayerType() gopacket.LayerType { } return m.tcp.NextLayerType() } -func (m *tcpWithDNSSupport) LayerPayload() []byte { return m.tcp.LayerPayload() } +func (m *tcpWithDNSSupport) LayerPayload() []byte { + payload := m.tcp.LayerPayload() + // Omit the DNS length field, only included + // in TCP, in order to reuse the DNS UDP parser + if len(payload) > 1 && (m.tcp.SrcPort == 53 || m.tcp.DstPort == 53) { + payload = payload[2:] + } + return payload +} func (s *DNSSnooper) run() { var (