Manipulation von Netzwerkpaketen

Die Manipulation von Netzwerkpaketen ist vor allem für Negativprotokolltests vorgesehen und bietet die Möglichkeit, die Pakete vor dem Senden zu modifizieren. Die Besonderheit liegt hierbei darin, dass die Protokollimplementierung samt ihrer spezifizierten Protokollabläufe weiterhin erhalten bleibt. Somit können z. B. gezielt Antworten im richtigen Moment manipuliert und anschließend gesendet werden, um den gewünschten Fehlerfall zu provozieren. Dies ist vom manuellen Senden fehlerhafter Pakete eindeutig abzugrenzen, da man beim manuellen Senden Timing-Verhalten oder dynamisch gesetzte Protokollfelder nur schwer selbst steuern kann.

Verwendung von Manipulationsobjekten

Das Manipulieren von Paketen erfolgt durch Manipulationsobjekte. Ein Manipulationsobjekt kann ein fester ByteStream (statische Manipulation) oder ein Python-Callback (dynamische Manipulation) sein. Callbacks können allgemein Python-Callables, wie z. B. Funktionen oder Objekte mit einer __call__-Methode sein.

Bei einem ByteStream wird anstelle des Pakets der übergebene ByteStream verwendet.

Bei einem Callback erfolgt die Manipulation dynamisch: Das Callback bekommt das zu ursprünglich zu sendende Paketobjekt als Argument hineingereicht und darf dieses verändern. Als Rückgabewert ist das modifizierte Objekt oder eine bloße Byte-Folge (bytes) möglich, welcher anschließend anstelle des ursprünglichen Objektes verwendet wird. Gibt das Callback None zurück, wird kein Netzwerkpaket gesendet.

Hier ein Beispiel:

import ...

class SimpleManipulation:

    def __call__(self, packet: PacketClass) -> Optional[Union[PacketClass, bytes]]:
        packet.SetSomeField(123)
        return packet


def EvenSimplerManipulation(packet: PacketClass) -> Optional[Union[PacketClass, bytes]]:
    return b'that is easy'


def DoNotSendAnything(packet: PacketClass) -> Optional[Union[PacketClass, bytes]]:
    return None

Falls als Manipulationsobjekt ein Callback vewendet wrid, muss dieses in einem Python-Modul in einem definierten Unterverzeichnis der Benutzer-Python-Bibliotheken abgelegt sein.

Nachdem die Manipulation mit einem Manipulationsobjekt gestartet wurde, wirken sich Änderungen am Objekt nicht mehr auf die Manipulation aus, da dieses beim Start kopiert wird. Änderungen können jedoch durch die Kombination der entsprechenden Jobs zum Starten und Stoppen einer Manipulation erwirkt werden.

Um eine prozess- und netzwerkübergreifende Verfügbarkeit des Manipulationsobjektes sicherzustellen, wird dieses mithilfe der Python-Serialisierung pickle kopiert. Bei grenzwertigen Fällen sind die Einschränkungen und Besonderheiten des pickle-Moduls zu beachten.

MKA-Manipulation

  • Jobs zum Starten und Stoppen der MKA-Manipulation: StartMkaManipulation und StopMkaManipulation

  • Paketobjekt: PacketMka

  • Unterverzeichnis: MkaManipulations

  • Beispiel:

from typing import Optional, Union
from tts.lib.ethernet.PacketMka import PacketMka  # api.Ethernet not available here

def MyMkaManipulation(packet: PacketMka) -> Optional[Union[PacketMka, bytes]]:
    packet.SetKeyServerPriority(42)
    packet.SetMemberIdentifier(ByteStream('11:22:33:44:55:66:77:88:99:AA:BB:CC'))
    return packet

IKE-Manipulation

  • Jobs zum Starten und Stoppen der IKE-Manipulation: StartIkeManipulation und StopIkeManipulation

  • Paketobjekt: PacketIke

  • Unterverzeichnis: IkeManipulations

  • Beispiel:

from typing import Optional, Union
from tts.lib.ethernet.PacketIke import PacketIke  # api.Ethernet not available here

def MyIkeManipulation(packet: PacketIke) -> Optional[Union[PacketIke, bytes]]:
    packet.minorVersion = 12
    return packet

SOME/IP-SD-Manipulation

  • Jobs zum Starten und Stoppen der SOME/IP-SD-Manipulation: StartSomeIpSdManipulation und StopSomeIpSdManipulation

  • Paketobjekt: PacketSomeIpSd

  • Unterverzeichnis: SomeIpSdManipulations

  • Beispiel:

from typing import Optional, Union
from tts.lib.ethernet.PacketSomeIpSd import PacketSomeIpSd  # api.Ethernet not available here

def MySomeIpSdManipulation(packet: PacketSomeIpSd) -> Optional[Union[PacketSomeIpSd, bytes]]:
    entries = packet.GetEntryList()
    for entry in entries:
        entry.SetMajorVersion(0xAB)
    return packet

SOME/IP-Manipulation

  • Jobs zum Starten und Stoppen der SOME/IP-Manipulation: StartSomeIpManipulation und StopSomeIpManipulation

  • Paketobjekt: PacketSomeIp

  • Unterverzeichnis: SomeIpManipulations

  • Beispiel:

from typing import Optional, Union
from tts.lib.ethernet.PacketSomeIp import PacketSomeIp  # api.Ethernet not available here

def MySomeIpManipulation(packet: PacketSomeIp) -> Optional[Union[PacketSomeIp, bytes]]:
    if packet.GetMessageId() == 0x35018002:
        packet.SetSessionId(0x0C)
    return packet

Verwendung von Jobs zur Manipulation der Protokoll-Header

Nach dem Start einer Verbindung über den MKA-Port oder IKEv2-Port enthalten zu sendende Pakete wie z.B. UDP-Pakete einen zusätzlichen MACsec- oder IPsec-Authentication-Header, die durch Jobs manipuliert werden können. Die internen Protokollabläufe werden dadurch nicht beeinflusst, aber die zu sendenden Pakete können gezielt verändert werden. Alle zu verändernden Inhalte werden dem Job (z.B. StartMacSecManipulation) als Parameter mitgegeben und sind so lange wirksam bis der zugehörige Stop-Job (z.B. StopMacSecManipulation) aufgerufen wird. Die Änderung pro Paket bleibt bis auf die Änderung von Sequenznummern und des ICV konstant.

Siehe StartMacSecManipulation, StopMacSecManipulation, StartAhManipulation, StopAhManipulation

Hinweis: Der Aufruf der Jobs zum Start und Stop der Manipulation sind aktuell asynchron. Es vergeht etwas Zeit bis die manipulierende Wirkung einsetzt.