Изучение Голанга с использованием гопакета в качестве стартера
Я начал изучать Голанг недавно (январь). Я пытаюсь воспроизвести инструмент, который у нас есть, который написан на Python на Go.
Так что у меня есть инструмент, работающий полностью для UDP-декодирования DNS, однако я уже неделю пытаюсь получить декодирование DNS на основе TCP. Моя цель - регистрировать источник, назначение, запрос и ответы DNS для каждого пакета, который попадает на наши DNS-серверы. По аналогии с тем, что делает dnstap, у нас есть внутреннее решение, в настоящее время использующее Python для нашей собственной системы ведения журналов и корреляции событий.
func Listen(h *pcap.Handle, c *Config, logger chan<- *dnslog) {
qType := decodeQuery()
OpCode := decodeOpCode()
parser := gopacket.NewDecodingLayerParser(
layers.LayerTypeEthernet,
ð,
&ip4,
&ip6,
&tcp,
&udp,
&dns,
)
decoded := make([]gopacket.LayerType, 0, 10)
for {
data, _, err := h.ZeroCopyReadPacketData()
if err != nil {
log.Println("Error reading packet data ", err)
continue
}
dnslog := &dnslog{}
err = parser.DecodeLayers(data, &decoded)
for _, layer := range decoded {
switch layer {
case layers.LayerTypeIPv4:
dnslog.Dst = ip4.DstIP.String()
dnslog.Src = ip4.SrcIP.String()
case layers.LayerTypeIPv6:
dnslog.Dst = ip6.DstIP.String()
dnslog.Src = ip6.SrcIP.String()
case layers.LayerTypeTCP:
dnslog.Srcport = fmt.Sprintf("%d", tcp.SrcPort)
dnslog.Dstport = fmt.Sprintf("%d", tcp.DstPort)
case layers.LayerTypeUDP:
dnslog.Srcport = fmt.Sprintf("%d", udp.SrcPort)
dnslog.Dstport = fmt.Sprintf("%d", udp.DstPort)
case layers.LayerTypeDNS:
dnslog.Truncated = dns.TC
for _, q := range dns.Questions {
dnslog.OpCode = OpCode[uint8(dns.OpCode)]
dnslog.QueryCount = dns.QDCount
dnslog.AnswerCount = dns.ANCount
}
}
}
logger <- dnslog
}
Я попытался принудительно установить NextLayerType в Layers/tcp.go в DNS Layertype и т. Д., Чтобы найти то, что мне не хватает. Пока не повезло. Любой совет будет тузом. То, что мы видим с UDP, - это следующий вывод. (вывод pprint в формате json)
[{
"src": "172.10.56.23",
"src_port": "52464",
"dst": "172.10.16.120",
"dst_port": "53",
"bytes": 63,
"transport": "UDP",
"reply_code": "Query",
"query_count": 1,
"answer_count": 0,
"question": ["helposx.apple.com"],
"query_type": "A",
"answer": null,
"truncated": false
}, {
"src": "172.10.16.120",
"src_port": "53",
"dst": "172.10.56.23",
"dst_port": "52464",
"bytes": 156,
"transport": "UDP",
"reply_code": "Query",
"query_count": 1,
"answer_count": 3,
"question": ["helposx.apple.com"],
"query_type": "A",
"answer": [{
"response-name": "helposx.apple.com",
"response-query_type": "CNAME",
"response-ttl": 4607,
"response-bytes": 31,
"response-cname": "helposx.apple.com.edgekey.net",
"response-soa": {},
"response-srv": {},
"response-mx": {}
}, {
"response-name": "helposx.apple.com.edgekey.net",
"response-query_type": "CNAME",
"response-ttl": 33,
"response-bytes": 22,
"response-cname": "e3167.e9.akamaiedge.net",
"response-soa": {},
"response-srv": {},
"response-mx": {}
}, {
"response-name": "e3167.e9.akamaiedge.net",
"response-query_type": "A",
"response-ttl": 13,
"response-bytes": 4,
"response-ip": "104.98.20.77",
"response-soa": {},
"response-srv": {},
"response-mx": {}
}],
"truncated": false
}]
Если теперь я делаю точно такой же запрос, используя dig +tcp (принудительно TCP), я получаю следующий вывод.
[{
"src": "172.10.56.23",
"src_port": "57188",
"dst": "172.10.16.120",
"dst_port": "53",
"bytes": 64,
"transport": "TCP",
"reply_code": "",
"query_count": 0,
"answer_count": 0,
"question": null,
"query_type": "",
"answer": null,
"truncated": false
}, {
"src": "172.10.16.120",
"src_port": "53",
"dst": "172.10.56.23",
"dst_port": "57188",
"bytes": 60,
"transport": "TCP",
"reply_code": "",
"query_count": 0,
"answer_count": 0,
"question": null,
"query_type": "",
"answer": null,
"truncated": false
}, {
"src": "172.10.56.23",
"src_port": "57188",
"dst": "172.10.16.120",
"dst_port": "53",
"bytes": 52,
"transport": "TCP",
"reply_code": "",
"query_count": 0,
"answer_count": 0,
"question": null,
"query_type": "",
"answer": null,
"truncated": false
}, {
"src": "172.10.56.23",
"src_port": "57188",
"dst": "172.10.16.120",
"dst_port": "53",
"bytes": 86,
"transport": "TCP",
"reply_code": "",
"query_count": 0,
"answer_count": 0,
"question": null,
"query_type": "",
"answer": null,
"truncated": false
}, {
"src": "172.10.16.120",
"src_port": "53",
"dst": "172.10.56.23",
"dst_port": "57188",
"bytes": 102,
"transport": "TCP",
"reply_code": "",
"query_count": 0,
"answer_count": 0,
"question": null,
"query_type": "",
"answer": null,
"truncated": false
}, {
"src": "172.10.56.23",
"src_port": "57188",
"dst": "172.10.16.120",
"dst_port": "53",
"bytes": 52,
"transport": "TCP",
"reply_code": "",
"query_count": 0,
"answer_count": 0,
"question": null,
"query_type": "",
"answer": null,
"truncated": false
}]
Посмотрев на те же пакеты в wireshark, я вижу, что эти различные пакеты являются TCP-квитированием, а затем ответом. Который не расшифрован.
Когда я добавляю fmt.Println(layer) после строки _, layer:= range, то получаю следующее.
Ethernet IPv4 TCP<< ВЫХОД JSON ВЫШЕ.
В.С.
Ethernet IPv4 UDP DNS
Как вы можете видеть, никогда не будет следующего декодера для DNS на основе TCP. Это просто останавливается на TCP. Я не уверен в том, что решение. Чтение вышестоящей библиотеки выглядит так, как будто она должна работать. Однако это не так, и я смущен, где я должен искать. Будучи новичком в Go, он отправляет меня в петли.
1 ответ
Я запросил поддержку для поддержки DNS через TCP, но в итоге сам реализовал ее.
Он еще не поддерживает фрагментацию TCP-сегментов, но этого достаточно для моего сценария использования (на данный момент).