Golang отправка ICMP-пакетов - PullRequest
       100

Golang отправка ICMP-пакетов

0 голосов
/ 30 января 2020

В настоящее время я работаю на Go маршрутизаторе для образовательных целей.

При попытке сериализации пакета ICMP, который я пересылаю с хоста, выясняется, что функция .SerializeTo структуры gopacket.ICMPv4 очищает часть полезной нагрузки ICMP и включает только тип, код, контрольную сумму, идентификатор, и последовательность в байтовом массиве, которую он возвращает в буфер.

Ниже приведен код, который я использую для отправки моего уровня eth, ip и icmp из моего интерфейса WAN. Единственное, что я изменил в этих слоях после того, как получил их от своего интерфейса локальной сети, - это ICMP ID, Ethe rnet src / dst и IP sr c.

opts := gopacket.SerializeOptions{FixLengths: true, ComputeChecksums: true}
buff := gopacket.NewSerializeBuffer()
_ = gopacket.SerializeLayers(buff, opts, ethLayer, ipLayer, icmpLayer)

Уровень ICMP перед отправкой, показывающий, что у него есть часть полезной нагрузки:

icmpLayer = & {BaseLayer: {Содержание: [8 0 65 238 7 109 0 1] Полезная нагрузка : [122 238 50 94 15 84 7 0 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55]} TypeCode: EchoRequest Контрольная сумма: 53486 Id: 10000 Seq: 1}

PCAP LAN сторона клиента, отправляющая ICMP-запрос на сервер. PCAP host to server

PCAP WAN сторона запроса пересылки сервера к месту назначения. PCAP server to WAN

Если потребуется какая-либо дополнительная информация, пожалуйста, дайте мне знать, я попытался предоставить как можно больше контекста.

1 Ответ

0 голосов
/ 03 февраля 2020

Я обнаружил, что класс ICMP SerializeTo fun c отбрасывал полезную нагрузку, когда он помещал свое представление байтового массива в буфер. Для тестирования я смог изменить функцию, чтобы использовать следующий код для динамического выделения большего пространства, если пакет имеет часть полезной нагрузки, а затем добавить полезную нагрузку в буфер. Будет публиковать это как ошибку на git, чтобы либо решить, либо указать, почему этот вариант использования является крайним случаем.

// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (i *ICMPv4) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
    bytes, err := b.PrependBytes(len(i.Payload)+8)//8)
    if err != nil {
        return err
    }
    i.TypeCode.SerializeTo(bytes)
    binary.BigEndian.PutUint16(bytes[4:], i.Id)
    binary.BigEndian.PutUint16(bytes[6:], i.Seq)

    startIndex := 8
    for _, element := range i.Payload {
        bytes[startIndex] = byte(uint16(element))
        startIndex+= 1
    }

    if opts.ComputeChecksums {
        bytes[2] = 0
        bytes[3] = 0
        i.Checksum = tcpipChecksum(b.Bytes(), 0)
    }
    binary.BigEndian.PutUint16(bytes[2:], i.Checksum)

    return nil
}
...