Skip to content
On this page

Versuch IP, BASH, Python auf Layer 2

Ziel dieses Versuches ist selber Frames auf Layer 2 zu senden und zu empfangen. Dabei verwenden wir zum einen das Raspberry Pi unter der Verwendung von Ethernet und der Python socket API, sowie Wireshark auf Hostseite um Frames empfangen und untersuchen zu können.

Lektüre

Fakultativ (zum Nachschlagen) finden Sie Informationen zum Thema Physical Layer im Buch auf dem Active Directory unter Physical Layer.pdf.

  • 2.2.2 Twisted-Pair Kabel
  • 2.2.5 Glasfaserleiter
  • 2.6.1 Aufbau des Telefonsystems
  • 2.6.5 Vermittlung
  • 2.8 Kabelfernsehen (2.8.4: optional)

BASH Scripts

Ein Vorteil von konsolenbasierten Programme gegenüber GUI ist deren Fähigkeit automatisiert aufgerufen zu werden. Unter Linux kommen BASH Scripts zum Einsatz. Hier handelt es sich um Files, welche in Sequenz Unterprogramme aufrufen. Zum Beispiel zur konfiguration einer IP Adresse:

bash
#!/bin/bash

echo "Configuring interface eth0"
sudo ifconfig eth0 192.168.50.10 netmask 255.255.255.0
echo "current configuration:"
ifconfig eth0

Erstellen Sie dieses Script unter dem Namen config.sh via Samba im Homeverzeichnis Ihres Targets. Rufen Sie das Script auf dem Target auf via:

bash
cd
bash ./config.sh

Putty stürzt ab

Wenn Sie die IP ändern und über Putty via SSH verbunden sind, dann wird die Session "gekappt" und Sie müssen sich neu verbinden (ggf. über die neue IP).

Files ausführbar machen

Idealerweise könnten wir config.sh einfach so, ohne ein bash im Vorfeld aufrufen. Hierzu muss allerdings config.sh ausführbar gemacht werden.

bash
chmod a+x config.sh
ls -al config.sh

Im Terminal wird config.sh nun grün angezeit, dies deutet darauf hin, dass das File ausführbar ist.

bash
./config.sh

bash config.sh

Lokaler Pfad als Prefix

Der Pfad: ./ Bezeichnet immer das lokale Directory.

Ethernet

Auf Layer 2 ist Ethernet neben WLAN heute weit verbreitet und hat speziell im LAN selten Konkurrenz. In diesem Versuch wird gezeigt wie ein Frame auf Layer 2 zusammengebaut und via Ethernet übertragen werden kann.

Setup

  • Raspbery Pi via eth0 192.168.50.1/24
  • Host System via eth0 192.168.50.2/24
  • Direkte Verbindung via Host und Target mit Ethernetkabel

Setup für den Versuch

Ethernet Frames

Die Einheit über welche Ethernet Daten austauscht heisst ein "Frame". Ein Ethnernet II Frame setzt sich folgendermassen zusammen.

BezeichnungLänge (Byte)Default
Präambel7
Start of Frame1
Destination MAC6
Source MAC6
Ether Type20x0800
Payload46 - 1500
CRC4

Während Ethernet als Träger für Protokolle wie ARP, ICMP, IPv4, IPv6 verwendet wird, könne auch "handgeschmiedete" Frames erstellt werden. Hierzu eignen sich vor allem Hardwarenahe APIs. Unter Linux findet man die socket API, diese wird für den Zugriff aufs Netzwerk von Kernel und Userspace Applikationen verwendet.

Lektüre

Lesen Sie an dieser Stelle entweder mit man 2 socket auf dem Target oder http://man7.org/linux/man-pages/man2/socket.2.html wie man socket verwendet.

Lesen Sie auch man packet oder http://man7.org/linux/man-pages/man7/packet.7.html.

Die häufigste Anwendung für Sockets sind die types SOCK_STREAM und SOCK_DGRAM welche TCP und UDP entsprechen. Während wir in späteren Übungen mit beiden Protokollen arbeiten werden, ist für diesen Versuch im Speziellen SOCK_RAW interessant.

Aus dem MAN Eintrag von packet entnehmen Sie folgendes:

Packets auf Devicelevel: SOCK_RAW

SOCK_RAW packets are passed to and from the device driver without any changes in the packet data. When receiving a packet, the address is still parsed and passed in a standard sockaddr_ll address structure. When transmitting a packet, the user-supplied buffer should contain the physical-layer header. That packet is then queued unmodified to the network driver of the interface defined by the destination address. Some device drivers always add other headers. SOCK_RAW is similar to but not compatible with the obsolete AF_INET/SOCK_PACKET of Linux 2.0.

Frage

Für welche Programmiersprache sind die MAN Einträge? Finden Sie ein Beispiel für Socket?

Packets oder Frames?

Zwar wird im MAN Eintrag von Packets geredet, in Tat und Wahrheit handelt es sich hier aber aus einer Perspektive des Netzwerks um Frames

Netzwerk für Host und Target

Wie im letzten mal beschrieben setzen wir auf der Hostmaschine die IP Adresse vom Ethernetinterface von Hand in den Windows Versuch: Tools .

Auf dem Target, welches über z.B. UART (alternativ SSH) angeschlossen ist, konfigurieren wir das Ethernetinterface eth0 via Commandline

bash
ifconfig eth0 192.168.50.1/24

Beide Maschinen sind somit im gleichen Netz (192.168.50.0) (natürlich ist eine physikalische Verbindung mit Ethernetkabel an dieser Stelle vorausgesetzt).

Verifizieren Sie, dass die Maschinen erreichbar sind, vom Target aus:

bash
ping 192.168.50.2

Ping antwortet nicht

Es ist gut möglich, dass das Hostsystem nicht auf den Ping antwortet. Das hat mit der Firewall von Windows zu tun. Stellen Sie in dem Fall sicher, dass Sie umgekehrt von Windows das Target anpingen können, dies sollte in jedem Fall funktionieren.

Code Editor

Im Versuch: Tools haben Sie bereits einen Texteditor und das Target via Netzlaufwerk eingebunden. Dies vereinfacht vorallem das bearbeiten von Text oder Sourcecode.

Erstellen Sie im Home Verzeichnis vom Target einen neuen Order link-layer. Erstellen Sie ein file hello.py und editieren Sie es anschliessen mit dem Texteditor.

Fügen Sie folgendes Pythonscript ein:

py
def main():
    print("hello world!")
    

if __name__ == '__main__':
    main()

Hello World auf dem Target

Auf dem Target wechseln sie in das soeben erstellte Directory.

cd ~/link-layer/

Jetzt führen Sie den Code aus

python hello.py
hello world!

Auf dem Target können Sie so selber Python Programme ausführen.

Python

Python ist eine sehr schlanke Programmiersprache und hat eine vielseitige Standardlibray. Gerade für Proof of Concept eignet sich die Umgebung ausgezeichnet. Während Python zwar bis zu einem gewissen Grad objektorientierte Programmierung unterstütz ist die Sprache nicht wirklich dafür geschaffen und hinkt bei komplexen Anforderungen Sprachen wie Java, Go oder C# / C++ etwas nach.

Gerade aber bei den native interfaces, den Schnittstellen zu Sprachen wie C/C++ mach Python niemand so schnell etwas vor. Im Gegensatz zu C vefügt die Sprache allerdings über eine flachere Lernkurve, da gerade Memorymanagement eine untergeordnete Rolle spielt.

Python ist eine Interpretersprache, während C Programme kompiliert und für die entsprechende Architektur übersetzt werden muss können Sie Pyhton ähnlich wie Java plattformunabhänging ausführen. D.h. gerade bei ARM erspart dies den Umweg über einen Crosscompiler um Code aus x86 in armv7 zu übersetzen.

Layer 2 Frames auf dem Target

Erstellen Sie eine neue Datei rawsocket.py mit folgendem Inhalt.

py
#!/usr/bin/python3
from socket import socket, SOCK_RAW, AF_PACKET

sock = None

message = b"""
Dear Receiver of this message

I am happy to announce the successful departure
of a layer 2 frame.

While none of the required headers are set
and thus this packet may never pass either 
a single- nor a multiport bridge, you on the other
hand will receive this message regardless of
convetions and contracts.

Thank you for the interest you are taking
in reading this string of information and
farewell.

Yours truly
Sender
"""


def main():
    print("welcome to the second layer")
    sock = socket(AF_PACKET, SOCK_RAW)

    # ethernet interface hier waehlen
    # entweder eth0 / eth1
    sock.bind(("eth0", 0))
    sock.send(message)


if __name__ == '__main__':
    main()

Führen Sie das Programm auf dem Target aus.

sudo python rawsocket.py

Aufzeichnen der Frames

Auf Hostseite könne nun die Layer 2 Frames inspiziert werden. Dazu verwenden wir den bereits installierten Wireshark.

Aufgaben

  1. Öffnen Sie Wireshark auf ihrem Hostsystem und höhren Sie das Ethernetinterface ab, während Sie das Skript Ausführen
  2. Was können Sie aus dem Frame schliessen, wenn sie es mit anderen Frames in Wireshark vergleichen
  3. Erstellen Sie in Wireshark einen Filter für das von Ihnen gesendete RAW packet.

Blinky Ping

Ping ist ein Tool, welches auf Layer 3 ein ICMP Packet sendet. Mit einer minimalen Python Applikation hören wir auf ICMP Requests und lassen ein LED kurz blinken, sobald ein solches Paket eintrifft.

Hardware Setup

Verwenden Sie die beim Raspi-Kit mitgegebne LED und schliessen Sie diese wiefolgt an:

PINLED Modul
4 (5V PWR)VCC
14 (GND)GND
12 (GPIO 18)IN

ACHTUNG Pins nicht verwechseln!

Bitte überprüfen Sie vor dem Anschliessen, ob die Pins richtig verbunden sind, da es sonst zu einem Kurzschluss kommen kann.

LED Ping

Erstellen Sie folgendes Python Script:

python
#!/usr/bin/python3

from gpiozero import LED
from time import sleep
import socket


def main():

    sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
    sock.bind(("0.0.0.0", 0))

    print("ping receiver")

    led = LED(18)

    while True:
        (data, addr) = sock.recvfrom(1024)

        print(f"data {data}")
        print(f"from: {addr}")

        led.on()
        sleep(0.1)
        led.off()


if __name__ == "__main__":
    main()

Speichern Sie das Script im gleichen Verzeichnis wie vorhin unter dem namen ping.py. Um das File ausführbar zu machen, navigieren Sie mit der BASH / Console ins entsprechende Verzeichnis und führen aus chmod a+x ping.py.

Starten Sie das Script nun mit sudo ./ping.py.

Testen

Von Ihrem Hostsystem pingen Sie nun das Target und beobachten ob die LED kurz aufblinkt.

ICMP

ICMP steht für Internet Control Message Protocol und wird für das Austauschen von Information auf Layer 3 verwendet. Ein Feature von ICMP ist der ECHO request, welcher dazu dient ein eingehendes Echo Paket mit einem ausgehenden zu beantworten.

gpiozero

gpiozero (https://gpiozero.readthedocs.io/en/stable/index.html) ist eine Python Library fürs Raspberry Pi, welche Zugriff auf die Peripherie vom Userspace her ermöglicht. Neben LED und Buttons, können so auch devices via I2C oder SPI verwendet werden.