2014-11-30 9 views
6

Chciałbym stworzyć pakiety TCP custome za pomocą gopacket, a następnie wysłać je za pomocą nieprzetworzonych gniazd.Jak używać Golanga do komponowania surowego pakietu TCP (używając gopacket) i wysyłania go przez surowe gniazdo

Oto krótki i czytelny przykład pójść program pokazuje, co chciałbym zrobić:

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") 
} 

uruchomiony ten program nie działa na ... SerializeLayer nie jednak. Oto panika:

panika: nieprawidłowy src IP 127.0.0.1

goroutine 16 [bieg]: runtime.panic (0x5bb020, 0xc2090723e0) /home/human/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 [finalizer wait]: runtime.park (0x413cc0, 0x7bc6c0, 0x7bb189) /home/human/golang-empire/go/src/pkg/runt/proc.c:13 69 + 0x89 runtime.parkunlock (0x7bc6c0, 0x7bb189) /home/human/golang-empire/go/src/pkg/runt/proc.c:1385 + 0x3b runfinq() /home/human/golang-imperium/go /src/pkg/runtime/mgc0.c:2644 + 0xcf runtime.goexit() /home/human/golang-empire/go/src/pkg/runtime/proc.c:1445

+0

OK ... Naprawiłem błąd "invalid src ip" ... spowodowany przez niepoprawny typ ParseIP ... musiał zostać przekonwertowany za pomocą metody .To4() ;-) –

+0

Obecnie moje proste zwięzłym przykładem jest wysłanie spreparowanego pakietu TCP/IP ... jednak numery portów i inne sekcje są zniekształcone. Być może "endian-ness" portów TCP są źle ustawione? Prosty zwięzły przykład tutaj: https://github.com/david415/HoneyBadger/blob/bd81a0132a2ccd880eee210acf2c965a37b457e3/packetSendTest.go –

+0

Ten nowy popełnić pokazuje, że otrzymany pakiet TCP/IP jest niepoprawny porównując srcPort i dstPort do oczekiwanych wartości po pakiecie rozbiór: https://github.com/david415/HoneyBadger/blob/c136e5cd58dddfdd5b97b7c4b65e338f41d0b09d/packetSendTest.go –

Odpowiedz

8

ty pytanie mówi "pakiety custome [sic] TCP", ale twój kod jasno pokazuje, że chcesz także tworzyć niestandardowe nagłówki warstwy 3 IP i istnieje różnica między tymi dwoma. Nie wspominasz również o IPv4 vs IPv6, ale znowu Twój kod wydaje się specyficzny dla IPv4.

Biorąc pod uwagę przykładowy kod, zakładam, że chcesz ustawić pełny nagłówek IPv4.

Od wersji 1.3.3 i wkrótce do wydania Go 1.4 nie można robić, co się chce, za pomocą pakietów Core Go. Aby osiągnąć to, czego potrzebujesz, musisz zrobić dwie rzeczy:

  1. Musisz utworzyć surowe gniazdo w Go. W przeciwieństwie do innych nieprawidłowych odpowiedzi na tej stronie, możesz utworzyć surowe gniazdo w Go za pomocą jednego z następujących: net.ListenPacket, net.DialIP lub lub lub lub .

Na przykład

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

tworzy gniazdo surowego.

  1. Jeśli chcesz ustawić własny nagłówek warstwy 3 IPv4, musisz ustawić opcję gniazda, aby włączyć funkcjonalność.

Twoje pytanie nie określa, z jakiego systemu operacyjnego i architektury korzystasz. Na moim laptopie z systemem 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 jest również dostępny w systemie Linux. Niestety, Core Go nie ma możliwości ustawienia opcji gniazda IP_HDRINCL ani nie ma sposobu na ustawienie innych opcji gniazda IP, takich jak IP_TTL.Mam zestaw prywatnych poprawek, które umożliwiają tę funkcjonalność w Core Go, ale to ci nie pomoże.

Wierzę, że następujący pakiet ma wszystkie funkcje, które są ci potrzebne, ipv4. Pamiętaj, że jest to duży pakiet i sam go nie użyłem. Zrobiłem grep i obsługuje on IP_HDRINCL na wielu platformach. Aby utworzyć nieprzetworzone połączenie, należy wywołać NewRawConn, a ta funkcja tworzy surowe gniazdo i ustawia opcję gniazda IP_HDRINCL.

Zobacz także tutaj: i kod, który tutaj napisał: latency, aby poczuć znacznie prostsze podejście, które może odpowiadać twoim potrzebom, jeśli chcesz ustawić nagłówki TCP. Należy jednak pamiętać, że ten kod nie pozwala ustawić adresów IP w nagłówku IPv4, co do którego podejrzewam, że chcesz to zrobić.

+0

Dzięki! Tak ... to działało idealnie. Działa to w tym zatwierdzeniu: https: //github.com/david415/HoneyBadger/blob/021246788e58cedf88dee75ac5dbf7ae60e12514/packetSendTest.go –

+0

Poniżej zamieszczono informacje na temat postu, który został przez Ciebie połączony, który przechodzi do poziomu nagłówka IP: http: // www.darkcoding.net/software/raw-sockets-in-go-link-layer/ –

Powiązane problemy