2016-06-10 2 views
0

Ich habe angefangen zu lernen Golan kürzlich (Januar). Ich versuche, ein Tool intern zu reproduzieren, das in Python in Go geschrieben ist.Lernen Golang mit Gopacket als Starter

So habe ich das Tool vollständig für die UDP-Decodierung von DNS arbeiten, aber ich habe seit einer Woche kämpfen, um TCP-basierte DNS-Decodierung zu bekommen. Mein Ziel ist es, DNS-Quelle, Ziel, Abfrage und Antworten für jedes Paket, das unsere DNS-Server trifft, zu protokollieren. Ähnlich wie bei dnstap haben wir jedoch eine interne Lösung, die Python derzeit für unser internes System zur benutzerdefinierten Protokollierung und Ereigniskorrelation verwendet.

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 
    } 

Ich habe versucht, die NextLayerType zu zwingen, in Schichten/tcp.go an den DNS-Layertype usw. in einem Versuch, zu finden, was mir fehlt. Bis jetzt kein Glück. Jeder Rat wäre ace. Was wir mit UDP sehen, ist die folgende Ausgabe. (Pprint json codierte Ausgabe)

[{ "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 }]

Wenn ich jetzt tun genau die gleiche Abfrage mit dig + tcp (Kräfte TCP) ich die folgende Ausgabe.

[{ "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 }] Aus dem Blick auf die gleichen Pakete in Wireshark kann ich sehen, dass diese verschiedenen Pakete sind der TCP-Handshake, dann eine Antwort. Was nicht dekodiert wird.

Wenn ich eine fmt.Println (Schicht) nach der for _, layer: = Bereich dekodierte Zeile hinzufügen, bekomme ich Folgendes.

Ethernet IPv4 TCP < < JSON OUTPUT OBEN.

VS

Ethernet IPv4 UDP DNS

Wie Sie sehen nie ein nächstes Decoder für die TCP-basierten DNS ist. Es stoppt nur bei TCP. Ich bin unsicher, was die Lösung ist. Das Lesen der Upstream-Bibliothek scheint zu funktionieren. Aber es ist nicht und ich bin verwirrt, wo ich hinschauen sollte. Als Neuling von Go schickt es mich in Schleifen.

+0

Schwierig/unmöglich ohne weitere Daten zu beantworten. Schlagen Sie vor, ein _brief_-Beispiel (so klein wie möglich) zu verfassen und zu veröffentlichen, das Ihr genaues Problem aufzeigt - einschließlich der Daten, die Sie zu diesem Zeitpunkt erwarten (z. B. fmt.Printf ("DAS SOLLTE X WERDEN, ABER DRUCKEN J:% ... "); sowie wie Sie die Eingabe in das Programm bekommen - nur von einer" Dig "oder was? Geben Sie die genaue Befehlszeile.) Bitte lesen Sie auch dies, wenn Sie nicht bereits: http://StackOverflow.com/help/mcve –

+0

Haben Sie das geschafft? Und ... ist Ihre Lösung zufällig eine Opensource? Ich muss ein sehr ähnliches Problem lösen und würde gerne Ihre Lösung wiederverwenden. – fons

Antwort