2014-11-30 16 views
6

Vorrei creare pacchetti TCP custome usando gopacket e quindi inviare utilizzando socket raw.Come utilizzare Golang per comporre pacchetti TCP non elaborati (usando gopacket) e inviarli tramite socket raw

Ecco un esempio breve e leggibile andare programma che dimostra quello che mi piacerebbe fare:

package main 

import (
    "code.google.com/p/gopacket" 
    "code.google.com/p/gopacket/examples/util" 
    "code.google.com/p/gopacket/layers" 
    "log" 
    "net" 
) 

func main() { 
    defer util.Run()() 

    // XXX create tcp/ip packet 
    srcIP := net.ParseIP("127.0.0.1") 
    dstIP := net.ParseIP("192.168.0.1") 
    //srcIPaddr := net.IPAddr{ 
    // IP: srcIP, 
    //} 
    dstIPaddr := net.IPAddr{ 
     IP: dstIP, 
    } 
    ipLayer := layers.IPv4{ 
     SrcIP: srcIP, 
     DstIP: dstIP, 
     Protocol: layers.IPProtocolTCP, 
    } 
    tcpLayer := layers.TCP{ 
     SrcPort: layers.TCPPort(666), 
     DstPort: layers.TCPPort(22), 
     SYN:  true, 
    } 
    tcpLayer.SetNetworkLayerForChecksum(&ipLayer) 
    buf := gopacket.NewSerializeBuffer() 
    opts := gopacket.SerializeOptions{ 
     FixLengths:  true, 
     ComputeChecksums: true, 
    } 
    err := gopacket.SerializeLayers(buf, opts, &ipLayer, &tcpLayer) 
    if err != nil { 
     panic(err) 
    } 
    // XXX end of packet creation 

    // XXX send packet 
    ipConn, err := net.ListenPacket("ip4:tcp", "0.0.0.0") 
    if err != nil { 
     panic(err) 
    } 
    _, err = ipConn.WriteTo(buf.Bytes(), &dstIPaddr) 
    if err != nil { 
     panic(err) 
    } 
    log.Print("packet sent!\n") 
} 

Tuttavia l'esecuzione di questo programma non funziona ... il SerializeLayer fallisce. Ecco il panico:

panico: 127.0.0.1 IP non valido src

goroutine 16 [esecuzione]: runtime.panic (0x5bb020, 0xc2090723e0) /home/uomo/golang-empire/go/src /pkg/runtime/panic.c:279 + 0xf5 main.main() /home/human/golang-empire/gopkg/src/github.com/david415/HoneyBadger/packetSendTest.go:41 + 0x464

goroutine 19 [finalizzatore wait]: runtime.park (0x413cc0, 0x7bc6c0, 0x7bb189) /home/human/golang-empire/go/src/pkg/runtime/proc.c:13 69 + 0x89 runtime.parkunlock (0x7bc6c0, 0x7bb189) /home/human/golang-empire/go/src/pkg/runtime/proc.c:1385 + 0x3b runfinq() /home/umano/golang-impero/vai /src/pkg/runtime/mgc0.c:2644 + 0xcf runtime.goexit() /home/human/golang-empire/go/src/pkg/runtime/proc.c:1445

+0

OK ... Ho corretto l'errore "src ip non valido" ... era dovuto a ParseIP che restituiva il tipo sbagliato ... doveva essere convertito con il suo metodo .To4() ;-) –

+0

Attualmente il mio semplice un esempio conciso è l'invio del pacchetto TCP/IP predisposto ... tuttavia i numeri di porta e le altre sezioni non sono corretti. Forse le "endianità" delle porte TCP sono impostate in modo errato? Semplice esempio conciso qui: https://github.com/david415/HoneyBadger/blob/bd81a0132a2ccd880eee210acf2c965a37b457e3/packetSendTest.go –

+0

Questo nuovo commit dimostra che il pacchetto TCP/IP risultante non è corretto confrontando srcPort e dstPort con i valori previsti dopo il pacchetto dissezione: https://github.com/david415/HoneyBadger/blob/c136e5cd58dddfdd5b97b7c4b65e338f41d0b09d/packetSendTest.go –

risposta

8

È questione dice "craft custome [sic] pacchetti TCP" ma il tuo codice ti rende chiaro che vuoi anche creare intestazioni personalizzate di livello 3 di IP e c'è una differenza tra i due. Inoltre, non si menziona IPv4 vs IPv6, ma di nuovo il codice sembra specifico per IPv4.

Dato il codice di esempio presumo che si desideri impostare l'intestazione completa IPv4.

A partire da Go 1.3.3 e presto Go 1.4 non è possibile eseguire ciò che si desidera utilizzando i pacchetti Core Go. Per realizzare ciò che desideri devi fare due cose:

  1. È necessario creare un socket non elaborato in Go. A differenza di altre risposte errate su questo sito Web, è possibile creare una socket non elaborata in Go utilizzando uno dei numeri net.ListenPacket, net.DialIP o net.ListenIP.

Ad esempio:

conn, err := net.ListenIP("ip4:tcp", netaddr) 
if err != nil { 
    log.Fatalf("ListenIP: %s\n", err) 
} 

crea un raw socket.

  1. Se si desidera impostare la propria intestazione di livello 3 IPv4, sarà necessario impostare un'opzione di socket per abilitare la funzionalità.

La domanda non indica quale sistema operativo e architettura si sta utilizzando. Sul mio computer portatile con Mac OS X:

% man ip 
. . . 
Outgoing packets automatically have an IP header prepended to them 
(based on the destination address and the protocol number the socket is created with), 
unless the IP_HDRINCL option has been set. 

IP_HDRINCL è disponibile su Linux anche. Sfortunatamente, Core Go non ha un modo per impostare l'opzione socket IP_HDRINCL né ha un modo per impostare altre opzioni di socket IP come IP_TTL.Ho un set di patch private che abilitano questa funzionalità con Core Go ma che non ti aiuterà.

Credo che il seguente pacchetto abbia tutte le funzionalità desiderate ipv4. Si prega di notare che è un grande pacchetto e non l'ho usato da solo. Ho fatto grep e supporta IP_HDRINCL su più piattaforme. Si desidera chiamare NewRawConn per creare una connessione non elaborata e questa funzione crea un socket non elaborato e imposta l'opzione socket IP_HDRINCL.

Vedere anche qui: raw-sockets-in-go e il codice che ha scritto qui latency per avere un'idea di un approccio molto più semplice che potrebbe soddisfare le proprie esigenze se si desidera semplicemente impostare le intestazioni TCP. Tuttavia, tieni presente che questo codice non ti consente di impostare gli indirizzi IP nell'intestazione IPv4 IP che sospetto tu voglia fare.

+0

Grazie! Sì .. ha funzionato perfettamente. Funziona in questo commit: https: //github.com/david415/HoneyBadger/blob/021246788e58cedf88dee75ac5dbf7ae60e12514/packetSendTest.go –

+0

Ecco il seguito del post sul blog che hai collegato, che scende al livello di intestazione IP: http: // www.darkcoding.net/software/raw-sockets-in-go-link-layer/ –