Klasse-C-Netzwerke per Shell-Skript aufteilen

Aus LinuxUser 10/2023

Klasse-C-Netzwerke per Shell-Skript aufteilen

© David Jancik / 123RF.com

Teilen und Herrschen

Das Aufsplitten eines LANs in mehrere Subnetze erleichtert das Monitoring. Allerdings gestaltet sich die Mathematik dahinter nicht eben intuitiv. Ein kleines Shell-Skript übernimmt die nötige Kalkulation.

In einem Klasse-C-Netzwerk [1], wie es typischerweise in Heimnetzen zum Einsatz kommt, ist die Netzmaske [2] immer die 255.255.255.0. Der PC sieht die Maske der Klasse C als eine Folge von 24 Einsen (für die Netzwerkadresse) und 8 Nullen im Binärformat. Daher rührt auch die typische Notation wie beispielsweise 192.168.178.0/24. Innerhalb dieses Netzwerks mit seiner 24-Bit-Adresse gibt es dann 28-1 gleich 255 mögliche Geräteadressen.

Aus Sicht eines Programmierers ist 255.255.255.0 dasselbe wie (255 << 24) + (255 << 16) + (255 << 8) + 0. Binär sieht das dann so aus: (11111111 << 24) + (11111111 << 16) + (11111111 << 8) + 0. Die vier sogenannten Oktetts [3] bedeuten nichts anderes als (192 << 24) + (168 << 16) + (178 << 8) + 0.

Für Menschen wäre eine solche 32-stellige Folge von Einsen und Nullen schlicht unleserlich. Genauso wenig würde es Sinn ergeben, eine IP-Adresse immer mit einer Folge von vier Oktetts darzustellen, die man dann noch shiften und addieren müsste. Deswegen bedient man sich einer leserlichen Abkürzung wie 192.168.178.0/24, die aber trotzdem oft Kopfschmerzen bereitet: Man muss ja doch irgendwie Bescheid wissen, wie ein System so eine IP-Adresse sieht und was man nun genau tun muss, um ein Klasse-C-Netzwerk zu unterteilen. Ein Computersystem erhöht dann die Bits der Netzwerkadresse von 24 auf 25 oder mehr Einsen.

Auch die Grenze zwischen Netzwerk- und Host-Anteil gibt dem Menschen immer wieder Anlass zum Stirnrunzeln. Der Rechner sieht einfach in der Maske nach, wo die Einsen enden und die Nullen anfangen. Er benötigt einfach nur zwei Folgen von Nullen und Einsen, die wir Menschen Netzmaske respektive IP-Adresse nennen. Das System vergleicht dann beide Bitfolgen und prüft, wo in beiden Fällen Bits gesetzt sind. Dann weiß es, auf welchem Weg es den Zielrechner erreichen kann. Dieser eigentlich simple Prozess bereitet Menschen geradezu Magenschmerzen, da die gewohnte Mathematik und das Bits-und-Bytes-Kung-Fu des Systems nicht gut harmonieren. Unsereins shiftet eine Reihe von Bits nicht mal eben um 24 Stellen nach links und weiß dann Bescheid.

Abbildung 1 zeigt, wie ein Computersystem “denkt” und wie es dann für uns Menschen IP-Adressen leserlicher und verständlicher darstellt. Im Download-Bereich finden Sie das für diese Darstellung verwendete Shell-Skript ip_tools.sh. Es enthält einige Funktionen mit Beispielen, die veranschaulichen sollen, wie man IP-Adressen zwischen Mensch und Rechner übersetzt. Eine erweiterte Fassung des Skripts können Sie außerdem über das Github-Repo [4] des Autors beziehen.

Abbildung 1: Das Skript stellt eine Netzmaske in unterschiedlicher Form dar.

Abbildung 1: Das Skript stellt eine Netzmaske in unterschiedlicher Form dar.

Ein Klasse-C-Netzwerk lässt sich grundsätzlich in 2, 4, 8, 16, 32, 64 oder auch 128 kleinere Netzwerke unterteilen. Letzteres ergibt allerdings wenig Sinn, weil es dann in den 128 Teilnetzen jeweils nur eine IP-Adresse für Geräte und Broadcasts [5] gäbe. Jeder Administrator wird dann sicherlich schnell erkennen, dass das keine sinnvolle Netzwerkkonfiguration ist. Realistisch erscheint schon eher, dass es beispielsweise dann 2 bis 8 Abteilungen gibt, deren Geräte sich dann jeweils in verschiedenen Subnetzen befinden sollen. Ein Skript zum Splitten von Klasse-C-Netzwerkadressen zu schreiben, ist gar nicht so schwer. Im Folgenden zeigen wir eine Möglichkeit, ein solches Tool zu skripten. Sie müssen nur ein wenig binär denken.

Argumente prüfen

Es gibt kaum ein Skript, das nicht auch Argumente entgegennehmen soll. In unserem Fall handelt es sich dabei um eine IP- oder Netzwerk-Adresse, die der Code dann auf Ihre Richtigkeit hin kontrollieren soll. Listing 1 zeigt die entsprechende Funktion, die die Plausibilität einer IP-Adresse prüft. Dazu kommt eine Case-Routine zum Einsatz, also eine Fallunterscheidung.

Listing 1

Assoziatives Array für Oktetts und Subnetze

function check_ip(){
  local reg_for_ip='([0-9]{1,3}\.){3}[0-9]{1,3}'
  grep -E -q $reg_for_ip <<<$1 && true || false
}
function show_ip_error(){
  echo "not a regular network or ip address. It must be something like that: 200.200.200.0"
}
case $# in
  0) true ;;
  1) check_ip $1 ||
    {
      show_ip_error
      exit 1
    }
    ;;
  *) echo "Too much arguments provided. Only 1 will be used."
    check_ip $1 || { show_ip_error ; exit 1 ; }
    ;;
esac
HOMENET=$( ip route show | grep "/24" | gawk -F "( |/)+" '{ print $2}' )
declare -A Networks
NWA=${1:-$HOMENET}

Übergibt der Aufrufer kein Argument, geht das auch in Ordnung. Jedes moderne Linux-System verfügt über den Befehl ip, der mit der Option route show dann die Routing-Tabelle ausgibt. In einem Klasse-C-Netzwerk reicht es aus, darin nach einem /24 zu suchen. Auf diese Weise finden Sie dann die Zeile mit der Angabe, in welchem Netzwerk sich der Rechner gerade befindet. Mit ein wenig Gawk [6] filtern Sie dann die Netzwerkadresse heraus. Danach wird dann ein assoziatives Array [7] deklariert, das später zum Abspeichern der Subnetze dient.

Letztes Oktett separieren

In Listing 2 sehen Sie, wie der Code die ersten drei Oktetts ermittelt und in der Variablen three abspeichert. Diese drei Oktetts entsprechen der Netzwerkadresse und werden dann später dem letzten Oktett, also der Host-Adresse, vorangestellt. Die Werte sind mit Absicht im Binärformat eingetragen, damit Sie sich ein Bild davon machen können, wie das System damit arbeitet. Im Übrigen können Sie sich bei einem Klasse-C-Netzwerk beim Aufteilen auf das letzte Oktett konzentrieren.

Listing 2

Die Sache mit den Oktetts

octets=( $(echo $NWA | tr "." " ") )
three=$(sed 's/ /./g' <<<${octets[*]:0:3})
dividers=(
  [2]=$(( 2#10000000 ))
  [4]=$(( 2#11000000 ))
  [8]=$(( 2#11100000 ))
  [16]=$(( 2#11110000 ))
  [32]=$(( 2#11111000 ))
  [64]=$(( 2#11111100 ))
)
echo "how many pieces?"
echo ${!dividers[@]}
read divider
case $divider in
  2|4|8|16|32|64)
    divider=${dividers[$divider]}
    ;;
  *)
    echo "Error occured. Please use only suggested dividers."
    exit 1
    ;;
esac

Als Nächstes fragt das Skript den Benutzer, in wie viele Teile er das Netzwerk unterteilen will. Auch hier stellt das Skript sicher, dass der User nicht etwa eine falsche Angabe gemacht hat, die den weiteren Ablauf gefährden könnte.

In Listing 3 sehen Sie, wie das System dann die IP-Adressen in Subnetze verteilt. Würden Sie sich etwa dafür entscheiden, das Netzwerk in zwei Segmente zu unterteilen, dann wäre das letzte Oktett 10000000. Das System würde jetzt alle Adressen von 00000000 bis 11111111 (0 bis 255) durchgehen und prüfen, wo ein binäres UND zustande kommt. Zum Beispiel gehört die IP-Adresse 00000011 ins Subnetz 00000000, die Adresse 10000011 dagegen in das Subnetz 10000000 (da ganz links ein binäres UND greift). Je nach binärer UND-Verknüpfung entsteht im Skript ein Schlüssel für das assoziative Array, wobei die so ermittelten IPs durch String-Konkatenation in die zum Subnetz gehörenden Schlüssel geschrieben werden.

Listing 3

Adressen verteilen

function collect(){
  for ip in {0..255}
  do
    key="${three}."$(( $ip & $divider))
    Networks[$key]+="${three}.$ip "
  done
}

Listing 4 zeigt die Funktion, die für die Ausgabe der einzelnen Subnetzwerke zuständig ist. Dabei gilt es zu bedenken, dass bei der Aufteilung von Netzwerken potenzielle Host-IPs verloren gehen: Jedes Netzwerk braucht ja auch eine eigene Basis- und Broadcast-Adresse. Die Funktion extrahiert beide Werte, um sie separat auszugeben. Die restlichen Werte bleiben dann als User-IPs für Mitarbeiter oder Kollegen übrig, die dann auch hoffentlich fleißig arbeiten.

Listing 4

Ausgabefunktion

function short_output(){
  local first=$1
  local members=( $( sed -r 's/[^ ]+$//' <<<${@:2} ) )
  local first_member=$members
  local last_member=${members[@]: -1}
  local last=${@: -1}
  echo
  printf "%-22s %s\n" "base address:" "$first"
  printf "%-22s %s\n" "broadcast address:" "$last"
  printf "%-22s %s\n" "user addresses:" "$first_member - $last_member"
}

Im Skript aus dem Download-Bereich zu diesem Artikel gibt es neben der Standard-Ausgabe (Abbildung 2) noch eine weitere Funktion, die für einen ausführlicheren Output sorgt (Abbildung 3). Es bleibt Ihnen überlassen, wie Sie nun die Ausgabe gestalten wollen. Generell hätten Sie auch die Möglichkeit, die Ausgabe gezielt nach Ihren Wünschen anzupassen.

Abbildung 2: Sie k&ouml;nnen die Ausgabe der IP-Adressen auf eine Kurzausgabe beschr&auml;nken &hellip;

Abbildung 2: Sie können die Ausgabe der IP-Adressen auf eine Kurzausgabe beschränken …


Abbildung 3: &hellip; oder stattdessen eine l&auml;ngere und auch ausf&uuml;hrlichere Ausgabeform w&auml;hlen.

Abbildung 3: … oder stattdessen eine längere und auch ausführlichere Ausgabeform wählen.

Fazit

Hat man sich die binäre Funktionsweise von IP-Adressen erst einmal vor Augen geführt, dann ist die Logik der Netzwerkaufteilung gar nicht so schwer zu verstehen. Zugegeben, das Hantieren mit einer 32-stelligen Binärfolge ist für den Menschen nicht eben intuitiv und erfordert einen gedanklichen Sprung. Das Skript ip_tools.sh, das Sie in voller Länge im Download-Bereich zu diesem Artikel finden, bietet aber eine gute Möglichkeit, den Sprung von der binären zur menschlichen Denke nachzuvollziehen und auch zu veranschaulichen.

Tatsächlich wäre es auch kein allzu schwieriges Unterfangen, das Skript dann dahingehend zu erweitern, dass Sie damit auch Netzwerke der Klassen A und B unterteilen können. Die Netzmasken würden dann 8 beziehungsweise 16 Einsen umfassen, den Rest der 32 Bits müssten Sie mit Nullen auffüllen. Das Separieren der einzelnen Oktetts wäre auch nicht unbedingt erforderlich, um das jeweilige binäre UND fürs Subnetz zu finden. Nur sollten Sie die Ausgabe in jedem Fall in eine für Menschen lesbare Form bringen. (jlu)

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDF
LinuxUser 10/2023 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

2 Kommentare
Älteste
Neuste Beste Bewertung
Thomas Schäfer
2 Jahre her

1993 lässt grüßen.

buliwyf
2 Jahre her

Hey liebe Linux-Community 30 Jahre nach der Abschaffung von Netzklassen sprecht ihr noch von Netzklassen? Das ist echt armselig.

Nach oben