Изучение Голанга с использованием гопакета в качестве стартера

Я начал изучать Голанг недавно (январь). Я пытаюсь воспроизвести инструмент, который у нас есть, который написан на 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,
            &eth,
            &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-сегментов, но этого достаточно для моего сценария использования (на данный момент).

Другие вопросы по тегам