Virtualisierte Netze mit KVM / qemu / libvirt – Hinweise und Links zur systematischen Einarbeitung

Ich befasse mich gerade mit einem Artikel zum Aufbau einer virtuellen Übungsumgebung für Penetrations-Tests unter Linux. Es geht dabei nicht um ressourcenschonendes Hosting – sondern um die Darstellung vollständiger Gastsysteme und ihrer Kommunikation in konfigurierbaren virtuellen Netzen. Die virtuellen Gastsysteme müssen zudem auf einfache Weise wieder im Originalzustand hergestellt oder eingespielt werden können. Eine Lösung mit vorgefertigten Containern (Docker, LXC) ist auf einer Workstation oder gar einem Laptop eher uninteressant; ich setze daher auf KVM/qemu für Linux-Gäste (wie Kali 2.0) und VMware WS/Player für Windows-Gäste.

Mir ist beim Schreiben erneut aufgefallen, dass interessierte Einsteiger es wahrlich schwer haben könnten, sich aus dem Sammelsurium an verstreuten Informationen im Internet einen Überblick über die Einrichtung virtueller Netzwerke unter Linux zu verschaffen. Das Niveau der zugehörigen Internet-Artikel ist uneinheitlich, die Verteilung der Information unübersichtlich. Einige Artikel sind allgmeingültig, andere stark distributionslastig. Das gilt auch für KVM/qemu und das Toolset libvirt/virt-manager.

Die oft kontextbezogene und z.T. überlappende bis synonyme Verwendung der Begriffe “Bridge”, “virtueller Switch” oder “virtuelles Netz” in verschiedenen Artikeln verwirrt Einsteiger möglicherweise. Ähnliches gilt für die Abkürzung “vlan” oder “vLAN”,

  • die einerseits die 802.1Q-basierte Kopplung (bonding) mehrerer NIC-Devices zur Erstellung logischer Segmente in physikalischen LANs bezeichnet (s. https://de.wikipedia.org/ wiki/ Virtual_Local_Area_Network),
  • die andererseits in vielen Artikeln kontextbezogen aber lediglich als Bezeichnung “virtuelles LAN” im Sinne eines virtualisierten Netzwerks auf einem Host mit Virtualisierungsumgebung (KVM/qemu, VMware, etc.) verwendet wird; oft genug ist jedoch auch das Bonding virtueller Netzwerk-Interfaces angesprochen.

Der Artikel
https://en.wikipedia.org/ wiki /Virtual_network
versucht eine Abgrenzung; stellt aber richtigerweise fest, dass auch die Kombination der Konzepte – also 802.q1-basierte vNIC-Kopplung in virtualisierten Netzwerken – möglich ist. Wir betrachten in diesem Artikel “virtualisierte Netzwerke” auf Basis virtueller Bridges/Switches (vBridge/vSwitch) und virtueller Netzwerk-Interfaces (vNICs) in Virtualisierungsumgebungen unter Linux.

Zur Verwirrung mag auch beitragen, dass man bei einer Internet-Recherche zwangsläufig auch über Artikel zu relativ speziellen Netzwerk-Konfigurationsmöglichkeiten stolpert. Etwa zu eine Bridge- oder “vepa”-Konfiguration auf Basis von “macvtap/mcvlan”-Devices, bei der eine direkte Kopplung virtueller mit physikalischen Devices des Hosts unter Nutzung spezieller Eigenschaften von Ethernet-Devices ermöglicht wird. Die richtige Einordnung dieser speziellen Varianten und ihrer Konsequenzen in den Gesamt-Kanon von Möglichkeiten zur Netzwerk-Virtualisierungen dürfte am Anfang sicher nicht leicht fallen.

Ich habe in diesem Artikel deshalb ein paar Links zusammengestellt,

  • deren Lektüre meiner Meinung nach eine gestaffelte und in der Komplexität steigende Lernkurve für die Einrichtung virtueller Netze unter KVM/qemu unterstützen kann;
  • die ich selbst in der Vergangenheit verschiedentlich zu Rate gezogen habe.

Leider habe ich nicht die Zeit, eine eigene Einführung in die Thematik virtualisierter Netze zu schreiben. Aber ich möchte die angegebenen Links doch mit ein paar Anmerkungen flankieren, die Schlüsselpunkte für das grundlegende
Verständnis zusammenfassen.

Vorbemerkungen zur Virtualisierung von Netzwerken unter Linux

Folgende Punkte scheinen mir zum Verständnis virtualisierter Netzwerke und ihrer Interaktion mit physikalischen Netzwerken essentiell zu sein:

Bridges
Linux und/oder unter Linux laufende Virtualisierungsumgebungen erlauben die Definition und Erstellung virtueller (Multiport)-Bridges. Solche Bridges können auf einem Linux-Host auch außerhalb und unabhängig vom libvirt- oder KVM/qemu-System kreiert werden. Eine virtuelle Multiport-Bridge unter Linux entspricht dabei in der üblichen Standardkonfiguration recht gut einem virtuellen Switch (vSwitch). Moderne Virtualisierungsumgebungen wie KVM/qemu erzeugen optimierte vBridges/vSwitches, die eng mit dem Kernel verzahnt sind

Virtuelle Netze
Ein virtueller Switch (z.B. ein “virbr0” unter KVM/qemu) realisiert in Kombination mit einem lokalen DHCP-Dienst die Grundlage für ein entsprechendes “virtuelles Netzwerk” (“vLAN”; hier nicht im Sinne von 802.Q1 verwendet). Ein solches virtuelles Netzwerk

  • kann auf dem Linux-Host ganz unabhängig vom physikalischen Netz existieren,
  • kann einen eigenen, für die angeschlossenen (virtuellen) Systeme gültigen IP-Adressbereich abdecken,
  • kann für den Host selbst über eine (ggf. spezielle) virtuelle Netzwerk-Schnittstelle zugänglich gemacht werden,
  • kann über verschiedene Methoden mit den physikalischen Netzen der Host-Umgebung verbunden oder von ihnen isoliert werden.

Es gibt somit unterschiedliche Varianten der Anbindung an oder der Isolierung virtueller Switches und ihrer zugehörigen virtuellen LANs vom Gastsystem und physikalischen Netzen.

Virtuelle Netzwerkdevices (vNICs)
Man kann einer (virtuellen) Linux-Bridge (bzw. einem virtuellen Switch)

  • rein virtuelle Netzwerk-Devices (vNics) von vitualisierten Gastsystemen,
  • ein virtuelles Netzwerk-Interface des Hosts selbst (“tap”-Device)
  • oder in speziellen Konfigurationen auch ein physikalisches Netzwerk-Interface (pNICs)

zuordnen. Virtuelle NICs für Gastsysteme und für den Virtualisierungs-Host werden über die jeweilige Virtualisierungsumgebung (z.B. KVM/qemu in optimierter Form) oder aber aber auch durch elementare Systemkommandos (wie etwa “tunctl”) bereitgestellt.

Die Bereitstellung virtualisierter vNICs (“tap”-devices) für den Host selbst dient dazu, die Kommunikation des Hosts mit virtuellen Switches und den daran angeschlossenen virtualisierten Systemen zu ermöglichen. So können z.B. Gastsysteme, die hinter einer KVM/qemu-Bridge “virbr0” liegen, vom Host aus über ein artifizielles Device “virbr0-nic”, das an einen Port der Bridge angeschlossen ist, angesprochen werden. Die Erstellung eines solchen vNICs für den Host muss aber (je nach Virtualisierungsumgebung) über spezielle Kommandos herbeigeführt werden.

Unterschiedliche Isolierungsgrade und virtuelle Netzwerk-Modelle
Virtuelle Netze und angeschlossene Gäste können je nach Zuordnung von vNICs und pNICS einen unterschiedlichen Grad der Isolierung gegenüber anderen virtuellen Netzen auf demselben Host, gegenüber dem Host selbst und seinen physikalischen Devices bzw. physikalischen Netzen
einnehmen. Je nach Auslegung des virtuellen Netzes spricht man auch von unterschiedlichen vLAN-Modellen oder vLAN-Varianten.

Anbindung virtueller Netze an physikalische Netze
Methoden zur Anbindung virtueller Netze eines Hosts an physikalische Netze sind u.a.:

  • das Routing zwischen virtuellen und physikalischen NICs auf dem Host,
  • das sog. “direkte Bridging” virtueller Devices von virtualisierten Gastsystemen zu und mit physikalischen Devices des Hosts,
  • die Bereitstellung besonderer virtueller Devices wie “macvtap” (zum direkten Teilen der Ressourcen eines physikalischen Netzwerk-Devices).

Virtuelle Devices von Virtualisierungsgästen werden im Falle der letzten beiden Verfahren direkt im physikalischen Netzsegment adressier- und ansprechbar und teilen sich Ressourcen mit einem vorhandenen physikalischen Interface (wie etwa eth0 oder enp8s0 unter Opensuse).

Im Falle des erstgenannten Verfahrens leitet der Host dagegen Netzwerkpakete, die von virtuellen Systemen und einem vSwitch-Port einer vBridge kommen, über sein eigenes virtuelles vNIC als Router/Gateway zu physikalischen pNICs und physikalischen Netzwerken weiter.
 
Hinzu kommen weitere Spezialverfahren, die z.T. die Definition besonderer virtueller Netzwerk-Devices erfordern.

Routing
Natürlich kann der Host Netzwerkpakete eines Virtualisierungsgastes vG1, der etwa in einem vLAN hinter einer vBridge “virbr0” lokalisiert sein mag, prinzipiell auch zu einem Gast vGx in einem anderen vLAN hinter einer vBridge “virbrx” weiterleiten, wenn er denn (virtuelle) Interfaces zu beiden vBridges besitzt. Natürlich müssen aber entsprechende Routing-Regeln definiert sein und durch paktefilter/Firewalls auch zugelassen werden.
Virtuelle Devices des Hosts (sog. “tap”-Devices), die in virtuelle Switches integriert werden, können einem Routing des Hosts unterworfen werden, müssen es aber nicht. Beispielsweise kann man Routing zwischen virtuellen LANs erlauben, Routing über physikalische Devices nach außen aber unterbinden. Entsprechende Route-Definitionen sind einerseits in die Routing-Tabellen des Hosts aufzunehmen und durch Skripts permanent zu machen, andererseits aber auch in den Paketfilter/Firewall-Einstellungen zu berücksichtigen. Paketfilter-Einstellungen (z.B. über netfilter-iptables/ebtables) können allgemeinere Routing-Regeln des Hosts dabei feingranularer eingrenzen oder bei Bedarf gänzlich aufheben.

“Direktes Bridging” zu einem physikalischen Device des Hosts
Eine besondere Variante des Bridgings ist das weiter oben bereits erwähnte “direkte Bridgen” virtueller Devices von virtualisierten Gastsystemen zu und mit einem physikalischen Device des Hosts. Die virtuellen Devices teilen sich dann das physikalische Device mit dem Host und erscheinen bei entsprechender IP-Adress-Zuordnung direkt im physikalischen Netz.

In manchen Artikeln wird eine entsprechende Bridge auch als eine “Public Bridge” bezeichnet. Leider sprechen einige Internet-Artikel salopp von “Bridging”, wenn sie eigentlich diese spezielle Variante des Aufbaues einer virtuellen Bridge meinen; andere Artikel beziehen “Bridging” dagegegen auf das generelle Verfahren der Erstellung einer virtuellen Bridge als Basis eines virtuellen Netzwerkes. Der Leser muss sich die richtige Interpretation manchmal etwas mühsam aus dem Kontext des Artikels herleiten.

Virtualisierungs-Toolsets
Virtualisierungstools wie “libvirt/virt-manager” unterstützen nicht nur
die Erstellung von Gastsystemen unter verschiedenen Virtualisierungsumgebungen (genauer Hypervisoren wie etwa “KVM/qemu”), sondern auch die Erstellung von (optimierten) virtuellen Bridges, von zugehörigen (optimierten) virtuellen Gast- und Host-Netzwerk-Devices (vNICs), DHCP-Diensten und damit insgesamt von virtuellen Netzen.

Paketfilterung und Firewalling ist auf verschiedenen Ebenen erforderlich
Virtuelle Devices des Host wie auch der virtualisierten Gastsysteme (!) können/müssen ebenso in iptables/ebtables-Regeln einer “netfilter”-basierten Firewall ebenso eingebunden werden wie die vorhandenen physikalischen Devices des Hosts auch. Es kommen u.U. aber spezielle Definitionen und Regeln zum Einsatz. Der Netfilter/iptables-Interpreter des Kernels “versteht” dabei u.a. auch spezielle Anweisungen zur Steuerung (direkt) gebridgter virtueller Devices hinter einem virtuellen Switch, die Signale über das virtuelle Host-Device in die Host-Umgebung senden oder aus dieser empfangen. Ein Präzisierung der iptables/ebtables-Regeln bzgl. der Weiterleitung der Signale von und zu direkt gebridgten Gast-Devices über die jeweilige virtuelle Bridge des Hostes Bridge ist in vielen Fällen dennoch unumgänglich (s. auch den folgenden Punkt). Besonders zu beachten ist, dass KVM/qemu – je nach Konfiguration – initial eigene Default-iptables/ebtables-Regeln etabliert. Diese werden bei Aktivierung eigener Firewall-Systeme durch andere Tools aber u.U. überschrieben. Eine Untersuchung und ein manueller Ausgleich sind oft erforderlich.

Sicherheitsrisiken bei (mehreren) direkten Bridges zu physikalischen Devices
Die “iptables”-Komponente von “netfilter” kümmert sich lediglich um den Pakettransport auf den Ebenen 3/4 des TCP-IP-Protokolls. “iptables” beachtet jedoch nicht den Level 2 (Ethernet, MAC-Adressen) des OSI- oder TCP/IP-Schichtenmodells. Virtuelle Switches können aber durch dieselben Angriffsmuster manipuliert werden, wie reale Switches. ARP Spoofing und ARP-Flooding sind hier zwei Stichworte. Angreifer können mit diesen Methoden die eindeutige Zuordnung von IP-Adressen zu MAC-Adressen bzw. von MAC-Adressen zu Switch-Ports aushebeln. Dadurch ist die Isolierung von Gastsystemen gegeneinander u.U. gefährdet und kann durchbrochen werden.

Sichere Konfigurationen erfordern deshalb neben dem Einsatz von iptables-Regeln auch noch zwingend den Einsatz von ebtables-Regelsätzen. Dies gilt im Besonderen auf Hosts mit direktem Bridging und ggf. mehreren “direkten Bridges” sowie aktiviertem “conntrack” in den iptables-Regeln. Eine saubere Trennung der ankommenden Pakete nach dem Ursprung, der die Verbindung initiierenden Adresse ist u.U. nicht mehr möglich, wenn Angreifer im gleichen LAN-Segment legale und illegale Pakete an dasselbe Target senden.
U.u. können selbst mehrere “direkte Bridges” auf ein und demselben Virtualisierungshost ohne ebtables-Regeln nicht zuverlässig gegeneinander abgeschottet werden. Bestimmte Angriffsverfahren, die virtuelle Bridges/Switches in einen “HUB Modus” zwingen, führen zur Möglichkeit des Mitlesens von Traffic durch einen Gast auf einer anderen Bridge als der, der der Gast zugeordnet ist. “Direkte virtuelle Bridges” sind auf produktiven Hosting-Systemen daher durchaus als potentiell problematisch einzustufen.

Ich hoffe, dem Leser mit diesen Statements ein paar Leitplanken zum besseren Einstieg in die Artikel hinter den nachfolgenden Links gegeben zu haben. Während die grundlegende Einrichtung geeigneter virtueller Bridges/Switches mit dem Gespann “libvirt/virt-manager” sehr schnell und sehr bequem gelingt, erfordern die zuletzt angesprochenen iptables/ebtables-Themen doch eine intensive Beschäftigung mit grundlegenden Netzwerk-Techniken und -Protokollen, netfilter-Regeln und dem ARP-Protokoll. Gerade dieses Feld ist aber ein Eldorado für Pen-Test-Übungen.

Ein paar grundlegende Definitionen zu (virtuellen) Bridges

Es schadet nicht, zu Beginn einer Einarbeitung in virtuelle Netze ein paar grundlegende Dinge zu Bridges/Switches und deren “Abgrenzung” zu rekapitulieren:

 
Wichtig ist zu verstehen, dass ein Switch im Kern einer Multiport-Bridge entspricht.
Es sollte nach der Lektüre der obigen Artikel klar sein, dass auch die Definition virtueller Netzwerke, die im Endeffekt über (virtuelle) Switches gesteuert werden, die Darstellung von virtuellen Multiport-Bridges und zugehöriger Regeln über den Kernel bzw. über vermittelnde und optimierende Virtualisierungs-SW erfordern wird.

Aufsetzen von Bridges unter Linux

An dieser Stelle ist es dann sinnvoll nachzulesen, wie man unter Linux (und spezifischen Linux-Distributionen) ganz allgemein virtuelle Bridges einrichten kann:

 
Ich empfehle hier dringend, sich mit dem Schlüsselkommando “brctl” und seinen Subkommandos auseinanderzusetzen (s. http://linux.die.net/ man/8/ brctl). Um eine Übersicht über angelegte Bridges/Switches und zugeordnete Interface auf einem Host zu erhalten, nutzt man “brctl show”. Dieses Kommando zeigt auch vBridges, zugehörige aktive Host- und Gastinterfaces an, die z.B. direkt mit Hilfe von KVM/qemu oder VMware und nicht manuell mit “brctl” erzeugt wurden.

Erwähnt sei an dieser Stelle auch, dass man ein HUB-ähnliches Verhalten der Bridge erzwingen kann:
http://www.linuxquestions.org/ questions/ linux-networking-3/can-a-bridge-be-configured-to-act-as-hub-not-a-switch-817170/
http://adamdoupe.com/ blog/ 2010/10/22/ configuring-linux-bridge-to-act-as-a-hub/
Dies its für Experimente nützlich zu wissen; ein solches HUB-Verhalten ist aber auf Virtualisierungshosts, auf denen Gäste und ihr Netzwerkverkehr gegeneinander abgeschirmt werden sollen, natürlich zu vermeiden.

libvirt/virt-manager als Interfaces und Tools für die Verwaltung virtueller Netzwerke (verschiedener Hypervisoren)

Der nächste Schritt besteht darin, sich darüber zu informieren, wie man unter Linux die Einrichtung ganzer virtueller Netzwerke auf (relativ) bequeme Weise steuern kann. Man wird zu recht vermuten, dass die Definition virtueller Bridges durch die Bereitstellung von Netzwerk-Schnittstellen für virtuelle Gastsysteme des eingesetzten Hypervisors und auch für den Host ergänzt werden muss. Hinzu kommen Basisdienste wie DHCP für das virtuelle Netzwerk. Das Gespann “libvirt/virt-manager” sind für diese Aufgaben unter Linux die erste Adresse. Das libvirt-Toolset unterstützt mehrere Hypervisoren. Eine “KVM/qemu”-basierte Virtualisierungsumgebung wird dabei zuverlässig unterstützt.

virt-manager liefert ein grafisches Interface zu libvirt, mit dem sich Gastsysteme und Netzwerke (relativ) bequem einrichten lassen. Die Gäste können zudem auf einer elementaren Ebene überwacht, an/ab-geschaltet oder “suspended” werden.

Einführung in libvirt:
https://de.wikipedia.org/ wiki/Libvirt
http://libvirt.org/
Eine Übersicht über die Hypervisoren, die libvirt unterstützt, ist hier zu finden:

https://libvirt.org/ drivers.html

Das erfolgreiche Nutzen von libvirt erfordert das Starten eines Daemons – libvirtd. Ein entsprechender “libvirtd.service” ist auf aktuellen Distributionen in die Target/Unit-Startreihenfolge von “systemd” zu integrieren. Zumindest bei Opensuse 13.2 geschieht dies mit der Installation der Virtualisierungsumgebung unter
“YaST2 >> Virtualisierung >> Install Hypervisor and Tools”
automatisch.

Graphischer Aufsatz “virt-manager” für KVM/qemu, Xen und LXC:

“virt-manager” unterstützt neben der Einrichtung von Gästen vor allem auch die Möglichkeit, komplette virtuelle Netze zu konfigurieren. Hierzu befasse man sich in einem gestarteten “virt-manager”-Fenster mit den Optionen, die man unter dem Menüpunkt
Edit >> Connection Details >> “Virtual Networks”
findet.

Ein weiterer wichtiger Punkt ist, dass “virt-manager” Konfigurationsdateien im XML-Format anlegt. Dies wiederum nutzen weitere libvirt-Programme zur Umsetzung der Virtualisierungsvorgaben über elementare Kommandostrukturen, die an den jeweiligen Hypervisor und seine Kernelintegration angepasst sind. Die XML-Konfigurationsdateien für Gastsysteme bzw. virtuelle Netze sind für KVM/qemu-Umgebungen (meist) in den Verzeichnissen
“/etc/libvirt”, “/etc/libvirt/qemu/” bzw. “/etc/libvirt/qemu/networks”
zu finden.

Neben “virt-manager” gibt es auch CLI-Interface zu libvirt namens “virsh”. Wir kommen weiter unten darauf zurück. Zunächst will ich aber ein paar Links zu einem Hauptthema für die Einarbeitung – nämlich unterschiedlichen virtuellen Netzwerk-Varianten – angeben.

Grundlegende Varianten virtueller Switches und deren Anbindung an physikalische Netze unter libvirt – Schlüsselartikel zur Übersicht

Bei der Auseinandersetzung mit Tools und ihren Möglichkeiten gerät man in Gefahr, vor lauter Bäumen den Wald nicht mehr zu sehen. Bei der Planung virtueller Netze ist es aber vor allem wichtig, sich mit den verfügbaren Varianten für die eigenen Einsatzzwecke auseinanderzusetzen. Dies gilt im besonderen für den Aufbau von Pen-Test-Umgebungen.

Der folgende Schlüssel-Artikel aus dem “libvirt WIKI” fokussiert auf verschiedene grundlegende virtuelle Netzwerkkonfigurationen und die Anbindung zugehörige virtuelle Switches an die physikalische Hostumgebung und physikalische Netze:

http://wiki.libvirt.org/ page/ VirtualNetworking
 
Weitere Strukturdiagramme zur Positionierung der virtuellen LANs findet man hier
http://www.libvirt.org/ archnetwork.html

Zu unterscheiden ist zwischen Konfigurationen, bei denen die Gastsysteme offiziell registrierte IP-Adressen erhalten und solchen, bei denen private Adressen verwendet werden.

In gerouteten Varianten über ein oder mehrere physikalische Interfaces des Hostes nach außen wird oft ein virtuelles (!) Device des Hosts, das wiederum mit einem virtuellen Switch verbunden ist, in geeignete Routing-Definitionen des Hostes eingebunden – mit und ohne NAT. Das ermöglicht Konfigurationen, bei denen die virtuellen Gäste hinter dem virtuellen Switch Zugriff auf das Internet oder aber andere virtuelle Netzwerke des Hostes erlangen können. Durch NAT-Einsatz kann dabei der direkte Zugriff von außen auf einen spezifischen Gast unterbunden werden. Es ist zu beachten, dass NAT auf IP-Ebene iptables-Regeln erfordert. Will man NAT auf MAC-Ebene realisieren, so ist der Einsatz von ebtables notwendig.

Für den Spezialfall einer direkten Bridge zu einem physikalischen Device findet man eine anschauliche Erläuterung grundlegender Prinzipien in folgenden zusammenhängenden Artikeln :
http://www.innervoice.in/ blogs/ 2013/12/02/ linux-bridge-virtual-networking/

http://www.innervoice.in/ blogs/ 2013/12/08/ tap-interfaces-linux-bridge/

Man beachte, dass der Autor nur den genannten Spezialfall genauer beschreibt. Einige der Aussagen gelten jedoch generell, und ich finde die Skizze im zweiten Artikel sehr instruktiv.

XML-Konfigurationsdateien für virtuelle Netzwerke unter libvirt/virt-manager

Die Konfiguration von virtuellen Netzwerken in Form von XML-Dateien, die für KVM/qemu dann unter “/etc/libvirt/qemu/networks” abgelegt werden, ist unter folgendem Link genauer behandelt:

https://libvirt.org/ formatnetwork.html

libvirt nutzt diese Dateien zur Umsetzung der Netzwerk-Konfiguration; virt-manager bietet, wie gesagt, nur ein grafisches Interface zur Erzeugung dieser Dateien.

Es lohnt sich, den genannten Artikel in Gänze durchzulesen:
Durch die beschriebenen Konfigurationsoptionen werden nämlich die unterschiedlichen virtuellen Netzwerk-Varianten noch einmal verdeutlicht (
siehe speziell die Optionen zum Konfigurationsparameter “forward”). Der Leser wird feststellen, dass es neben dem direkten Bridging noch weitere Möglichkeiten gibt, eine Kopplung von virtuellen Netzen an physikalische Host-Devices vorzunehmen – z.B. über mcvtap-Devices. Solche Netze erfordern jedoch Zusatzmaßnahmen, um den Host direkt mit Gästen hinter der Bridge kommunizieren zu lassen. Als Einsteiger würde ich mich deshalb zunächst mit normalem direkten Bridging vertraut machen, bevor man mit mcvtap-Konfigurationen experimentiert. Links zu diesem Spezialthema folgen weiter unten. Der Einsatz von mcvtaps kann aber aus Performance-Gründen interessant sein.

“virsh”-Komponente von libvirt für die Kommandozeile

libvirt kann statt über “virt-manager” auch über die Kommandozeile instruiert werden. Dabei kommt der CLI-Kommandointerpreter “virsh” zum Einsatz. Zur Konfiguration von virtuellen Netzwerken über den “virsh”-CLI-Interpreter siehe:

Zwischenstand und Wiederholung

Es sollte nach der bisherigen Lektüre klargeworden sein, dass den virtuellen Netzwerken Multiport-Bridge-Definitionen für den jeweiligen Hypervisor zugrunde liegen. (Die Bridge-Definitionen erfolgen dabei entweder über Linux “brctl”-Kommandos (s.u.) oder “ip”-Kommandos (iproute2) bzw. direkte Kommandos der Virtualisierungsumgebung für optimierte “vbridges” an den Kernel). Einer (Multiport-) “Bridge” können dann virtuelle und ggf. auch physikalische Devices zugeordnet werden. Die Konfiguration von kernel-optimierten “vBridges” und “vNICs” unter KVM/qemu ist am einfachsten mit “virt-manager” möglich.

Auf einer anschaulichen Ebene kann man sich vorstellen, dass virtuelle Netze über einen virtuellen Switch realisiert werden, der die Kommunikation zwischen mehreren Ports steuert.

Die Repräsentanz des virtuellen Netzes im Host kann über ein spezielles sog. “tap0”-Device gewährleistet werden, das eine virtuelle NIC im Host erzeugt, die wie physikalische NICs auch in iptables/ebtables-Regeln eingebunden werden kann. Diese Device “hängt” dann auch am virtuellen Switch und ermöglicht die Kommunikation des Hosts mit dem virtuellen Gästen hinter dem virtuellen Switch. Zur Einführung in Tap-Devices siehe

https://de.wikipedia.org/ wiki/TUN/TAP

http://backreference.org/ 2010/03/26/ tuntap-interface-tutorial/

Es wurde durch die Lektüre zudem deutlich, dass zwischen “direkten Bridges” zu physikalischen NIC-Devices und rein virtuellen Bridges zu unterscheiden ist. Die Repräsentanz einer rein virtuellen Brigde (bzw. Switches) im Host kann – wie gesagt – über ein spezielles tap-Device erfolgen, das zusätzlich zu erstellen ist. Unter dem aktuellen “libvirt/virt-manager”-Gespann ist dies meist eine zu wählende Option beim Einrichten der virtuellen Netze.

Beachte: Bei direktem Bridging erhält die Bridge selbst die IP-Adresse und nicht das physikalische Device (s.u.).

Also: Einer aufgesetzten Bridge (werden dann je nach Isolierungsgrad

  • situationsgerechte virtuelle Devices der Gäste der jeweiligen Virtualisierungsumgebung zugeordnet,
  • spezielle virtuelle Devices, die das virtuelle Netz für den Host zugänglich machen (mit oder ohne Routing auf dem Host)
    zugeordnet
  • oder aber in bestimmten Fällen des direkten Bridgings zur physikalischen Netzwerkumgebung eben auch physikalische Devices zugeordnet (wobei das physikalische Device dann keine IP erhält, sondern die Bridge (z.B. br0)). Die virtuellen NIC-Devices erscheinen dabei direkt im physikalischen Netzbereich des Hosts.

Virtuelle Netzwerkinterfaces (verschiedener Hypervisoren wie von Spezialfällen) für die Gäste und den Host, die an verschiedene Bridge/Switch-Typen angebunden werden können, werden hier behandelt:

http://qemu-buch.de/ de/ index.php?title=QEMU-KVM-Buch/ _Netzwerkoptionen/ _Virtuelle_Netzwerke_konfigurieren

http://libvirt.org/ formatdomain.html# elementsNICS

Performance-Optimierung
Nutzt man “virt-manager” werden einem je nach gewähltem Netzwerk-Typ unterschiedliche Modelle für virtuelle NICs beim Einrichten der Gäste bzw. auch beim Einrichten des Host-Tap-Interfaces angeboten. Man sollte durchaus mit verschiedenen Modellen experimentieren und die Performance testen. Unter Opensuse 13.1/13.2 habe ich durchweg gute Erfahrungen mit “virtio”-Treibern gemacht.

Hochfahren des Netzes und der virtuellen Gastdevices

Das Hochfahren von Netzwerk-Bridges und das Anlegen zugehöriger virtueller Host-Devices (z.B. virbr0) erfolgt unter aktuellen Distributionen meist über den “Autostart”-Mechanismus von “libvirt”. Man werfe bzgl. der automatisch zu startenden virtuellen Netzwerke einen Blick in das Verzeichnis
“/etc/libvirt/qemu/networks/autostart”.

So zeigt in einem Beispiel ein Opensuse-Host, für den mittels “virt-manager”
eine Bridge “br0” unter Einbindung des physikalische Devices
und eine rein virtuelle Bridge mit angeschlossenem Host-Device
definiert wurden, etwa folgendes nach dem Systemstart (inkl. libvirtd.service):

mytux:~ # brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.aabbccddee11       no              enp8s0
virbr0          8000.ccddee112233       yes             virbr0-nic
mytux:~ # ifconfig
br0       Link encap:Ethernet  HWaddr AA:BB:CC:DD:EE:11  
          inet addr:192.168.12.1  Bcast:192.168.12.255  Mask:255.255.255.0
	  ...
enp8s0    Link encap:Ethernet  HWaddr BB:CC:DD:EE:11:AA  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
	  ....	
virbr0    Link encap:Ethernet  HWaddr CC:DD:EE:11:22:33  
          inet addr:192.168.200.1  Bcast:192.168.200.255  Mask:255.255.255.0
	  ....

 
Welche Gastsysteme übrigens beim Systemstart des Hosts automatisch hochgefahren werden sollen, kann man ebenfalls über “virt-manager” festlegen. Das Ganze ist offenbar in den Start des “libvirtd.service” integriert. Siehe unter:
“/etc/libvirt/qemu/autostart”.

Unter “libvirt” und “KVM/qemu” gilt: Die vNICs von virtuellen Gastsystemen werden erst beim Starten und Einrichten dieser Gastsysteme erzeugt und an die Bridge angebunden. Die virtuellen vNIC-Devices der Gastsysteme sind vorher nicht existent, werden danach aber unter ifconfig und “brctl show” sichtbar!

mytux:~ # brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.aabbccddee11       no              enp8s0
                                                        vnet0
virbr0          8000.ccddee112233       yes             virbr0-nic
                                                        vnet1

 
Die erstellten
virtuellen Ethernet-Devices werden unter KVM/qemu mit einem Treibermodell (z.B. virtio) unterlegt und in die startende virtuelle Maschine integriert. Gesteuert wird der gesamte Prozess über entsprechende Start-Kommandos für die virtuellen Maschinen. libvirt/virt-manager überdecken diesen Aufwand netterweise. KVM arbeitet dabei eng mit dem Kernel zusammen.

Manuell könnte man auf Betriebssystem-Ebene einen ähnlichen Vorgang etwa dadurch vollziehen, indem man durch Anwendung des “tunctl”-Befehles (erfordert unter Opensuse die Installation des entsprechenden Paketes!) virtuelle tap-Devices erzeugt, diese einem anschließenden “brctl addif” an die Bridge anbindet und dann dieses Device in einem qemu-Start-Befehl für einen virtuellen Gast benutzt. Das funktioniert auch – nur hat man hierbei keinerlei Optimierungsmöglichkeiten.

Es ist aus meiner Sicht grundsätzlich besser, sich auf die für den Kernel optimierten Devices zu verlassen, die man über die Virtualisierungsumgebung (KVM/qemu) und “virt-manager” als Frontend erzeugt.

Einschub: Pfad der Konfigurationsdateien unter Opensuse

Unter Opensuse findet man die Vorgaben und Startup-Skripts für Bridges (wie br0 etc.) zu physikalischen NIC-Devices unter

/etc/sysconfig/network.

Eine br0-Bridge wird von Opensuse 13.1/13.2 beim Einrichten des Systems als Virtualisierungshost über YaST meist bereits automatisch eingerichtet. Auf diese per “brctl” generierte Bridge kann dann unter “virt-manger” Bezug genommen werden. Dies ist sinnvoll etwa beim Einrichten von Gastsystemen mit einem direkt zum physikalischen Device gebridtem vNIC.

Libvirt bezogene Bridge- und Netzwerk-Definitionen – also solche, bei denen die vBridge direkt über die Virtualisierungsumgebung erzeugt wird – sind unter

/etc/libvirt/

bzw. unter

/etc/libvirt/qemu/networks

zu finden.

Umsetzung virtueller Netze unter “KVM/qemu”

In den Links zu libvirt/virt-manager wurde noch nicht gezeigt, auf was sich “libvirt/virt-manager” bei der Generierung von Netzwerken und zugeordneten virtuellen NICs letztlich stützen. Zudem sollte man sich darüber im klaren sein, dass man über ein wenig Skripting einen “KVM/qemu”-Hypervisor auch direkt ansteuern kann.

KVM ist ein Hypervisor zur Vollvirtualisierung, der als Linux Kernelmodul operiert. Er ist eng mit qemu verzahnt – und stellt eine optimierte Integration der Virtualisierungsumgebung in den Kernel dar. Zu qemu und KVM wird eine erste Einführung hier gegeben:
http://serverfault.com/ questions/208693/ difference-between-kvm-and-qemu

http://www.innervoice.in/ blogs/ 2014/03/10/ kvm-and-qemu/

http://www.linux-kvm.org/ page/Main_Page

Umfangreicher Artikel zur elementaren Konfiguration von qemu-Systemen:

http://qemu-buch.de/ de/index.php? title=QEMU-KVM-Buch/ _Netzwerkoptionen/ _Virtuelle_Netzwerke_konfigurieren

Networking unter KVM/qemu:
http://www.linux-kvm.org/ page/Networking

http://wiki.qemu.org/ Documentation/ Networking

https://en.wikibooks.org/ wiki/QEMU/ Networking

http://wiki.qemu.org/ Documentation/ Networking

https://people.gnome.org/ ~markmc/ qemu-networking.html

Interessant und anregend ist auch ein Studium der praktischen Beispiele, die etwa das Unternehmen Hetzner für seine gehosteten Server-Plattformen diskutiert:
http://wiki.hetzner.de/ index.php/ Kategorie:KVM

Zur Klärung, wie ein qemu-vLan begrifflich zu verstehen ist, siehe:
http://www-01.ibm.com/ support/ knowledgecenter/ linuxonibm/ liaat/ liaatbptap.htm

SLES- und Opensuse-spezifische Informationen zu KVM/qemu gibt es hier:
https://www.suse.com/ documentation/ sles-12/ singlehtml/ book_virt/book_virt.html

https://www.suse.com/ documentation/ sles-12/ singlehtml/ book_virt/ book_virt.html#cha.qemu.running.networking

https://www.suse.com/ documentation/ sles11/ book_kvm/data/ book_kvm.html

https://www.suse.com/ documentation/ sles11/book_kvm/ data/cha_qemu_ running_networking.html

https://activedoc.opensuse.org/ book/ opensuse-virtualization-with-kvm/ chapter-12-running-virtual-machines-with-qemu-kvm

https://activedoc.opensuse.org/ book/ opensuse-virtualization-with-kvm
https://www.howtoforge.com/ virtualization-with-kvm-on-an-opensuse-12.1-server

http://www.vorkon.de/ SU1210.001/ drittanbieter/ Dokumentation/ openSUSE_11.4/manual/ book.kvm.html

Für Debian-spezifische Informationen s. hier:

 
Ubuntu-spezifische Informationen finden sich hier:
https://help.ubuntu.com/ community/ KVMFeisty

NAT-Variante der Anbindung eines virtuellen Netzes an die physikalische Umgebung

Die NAT-Anbindung virtueller Netze an physikalische Netze wird hier diskutiert:
http://wiki.qemu.org/ Documentation/ Networking/NAT

Verschiedene virtuelle Netzwerk-Varianten für Debian-basierte Host-Systeme über die dortige iface-Konfiguration

Debian sammelt die Konfigurationsvorgaben zu Netzwerken und Netzwerk-Devices in einer “iface”-Datei. Siehe zu diesem Thema:

Beispiele für direktes Bridging mit physikalischem Host-Device

http://blog.elastocloud.org/ 2015/07/ qemukvm-bridged-network-with-tap.html
http://www.oneunified.net/ blog/ Virtualization/ BridgeTap.article
http://www.dedoimedo.com/ computers/ kvm-bridged.html
http://hzqtc.github.io/ 2012/02/ kvm-network-bridging.html

Windows-Gastsystem mit direktem Bridging
Artikel für praktische Beispiele mit einem Windows Guest für ein Bridging mit dem physikalischen Host-Device unter Debian-nahen Systemen sind folgende:
http://resources.infosecinstitute.com/ qemu-windows-guest-bridged-networking/

http://resources.infosecinstitute.com/ qemu-windows-guest-networking/

Alternative zum Direct Bridging: Netzwerk mit mcvtap/vepa devices

Leute, die Alternativen zum direkten Bridging suchen, weil sie evtl. Probleme mit der Performance bekommen, werden etvl. mit macvtyp-Devices glücklicher. Hier ein paar Artikel-Links dazu:
http://virt.kernelnewbies.org/ MacVTap

https://libvirt.org/ formatnetwork.html# elementsConnect

https://libvirt.org/ formatnetwork.html# examplesDirect
https://seravo.fi/ 2012/ virtualized-bridged-networking-with-macvtap

https://wiki.math.cmu.edu/ iki/wiki/ tips/ 20140303-kvm-macvtap.html

Netfilter, Firewalling und libvirt

Ich setze hier voraus, dass der Anwender von virtuellen Netzen bereit ist, sich in “netfilter” und seine iptables/ebtables-Komponenten selbst einzuarbeiten. Ich gebe hierzu nur wenige Literaturhinweise an:

https://people.redhat.com/ fcaviggi/ Firewalls.pdf

https://www.frozentux.net/ iptables-tutorial/iptables-tutorial.html
https://wiki.archlinux.org/ index.php/ Iptables

https://wiki.archlinux.org/ index.php/ Simple_stateful_firewall

http://ebtables.netfilter.org/ examples/ basic.html

https://laddumishra.wordpress.com/ 2012/01/19/ mac-filtering-and-bridging-firewalls-in-linuxubuntu/

Grundsätzlich möchte ich Paket-Filterung über eigene iptables/ebtables-Regeln und zugehörige Skripte abgrenzen von den elementaren Möglichkeiten, die “libvirt” bietet. Mein persönlicher Rat ist, sich mit den Möglichkeiten von libvirt zwar auseinanderzusetzen, um Kenntnisse über bestimmte, dort realisierte Standardfilter als
Lehrbeispiele zu erlangen. Sobald man die aber nachvollzogen hat, empfiehlt es sich aus meiner Sicht, diese Regeln in eigene Skripte überzuführen. Gerade beim Aufsetzen von Pen-Testing-Übungsumgebungen hat man dadurch eine wesentlich bessere Kontrolle über das System-Setup. Und was da gilt, kann für Hosting-Umgebungen nicht so falsch sein …

Libvirt bringt bereits eigene elementarste Regeln mit, die je nach Konfiguration der virtuellen Netze bei deren Erstellung mit erzeugt werden. Man überprüfe das mit “iptables -L”.

Wichtig ist zu verstehen, dass diese elementaren Definitionen durch andere Firewall-Tools auf dem eigenen Host abgeschaltet, gelöscht oder überschrieben werden können – auch versehentlich. Auf aktuellen Distributionen ist daher unbedingt die Startreihenfolge von iptables-Tools und die resultierenden Auswirkungen auf physikalische wie virtuelle Netze zu beachten! Für Opensuse-Freunde sind etwa folgende Hinweise angebracht:

Hinweise zur Susefirewall2:
So löscht etwa ein Starten der Susefirewall2 unter Opensuse 13.2/13.1 alle der bei einem vorhergehenden Start des “libvirtd.service” angelegten Regeln. Man beachte auch, dass die Susefirewall2 beim Abschalten Routing auf dem Host automatisch deaktiviert! (Auf diese von Opensuse zur Sicherheit implementiertes Vorgehen, bin ich beim schnellen Aufsetzen von Pentest-Umgebungen schon mehrfach hereingefallen.)

Fakt ist auch, dass die wenigen elementaren Default-Regeln von livirtd das Host-System mit seinen virtualisierten Netzen gegenüber bestimmten Angriffen relativ offen lassen.

Eine erste detailliertere Diskussion von iptables-Regeln für einfache virtuelle Netzwerkkonfigurationen erfolgt hier:
https://libvirt.org/ firewall.html

Dieser Artikel zeigt in seiner Mitte auch, dass es einen ganzen Satz komplexerer, vordefinierter Firewall-Regelsätze gibt, die man einerseits in Netzwerk-Definitionen unter libvirt, ggf. aber auch in eigene iptables/ebtables-Scripts einbeziehen kann. Für letzteres ist ein kleiner Umweg nötig:

Bitte beachtet, dass der Zugriff auf die vordefinierten Regeln unter Opensuse die Installation diverser zusätzlicher (!) Pakete in Ergänzung der Pakete libvirt-daemon, libvirt-client, virt-manager, virt-manager-common erfordert. Am einfachsten ist es jedoch, das Paket “libvirt” zu installieren. Danach “systemctl restart libvirtd.service” und schon funktioniert

mytux:~ # virsh
Welcome to virsh, the virtualization interactive terminal.

Type:  'help' for help with commands
       'quit' to quit

virsh # nwfilter-list
 UUID                                  Name                 
------------------------------------------------------------------
 01c82440-808d-4def-a22f-21848d896cbd  allow-arp           
 154492fb-3198-4de3-8e0c-b0ccbb8f9abc  allow-dhcp          
 60c01c9a-4039-49d9-8ed8-ca55090a6e1a  allow-dhcp-server   
 919ec06f-76bc-4c14-b0dd-5f7cc914edae  allow-incoming-ipv4 
 b3408089-22cf-4b5d-82fa-82769f43a2ed  allow-ipv4          
 c85622ce-1acb-4627-ba5d-cc93476dd5d7  clean-traffic       
 c7865ee0-8dd3-4d2c-98a1-1b3a811322df  no-arp-ip-spoofing  
 81f384b6-5576-4762-a708-33b218868ac6  no-arp-mac-spoofing 
 11fe3e29-2947-45a4-863e-b1e52b923ab2  no-arp-spoofing     
 07123a0e-6b8b-4883-9ef3-49ab88f6cfe2  no-ip-multicast     
 66c36165-89b6-461a-9427-1451b61f697f  no-ip-spoofing      
 ee3e292b-c795-4602-9cd4-3117bbdf36e1  no-mac-broadcast    
 144dd5af-449e-46dd-b9e8-f009d692ce35  no-mac-spoofing     
 ad6e6769-1c8e-40aa-9109-722144841c72  no-other-l2-traffic 
 cfde67c1-aafa-4a0f-8099-34ceb9469197  no-other-rarp-traffic
 18ada8c3-a132-4f89-9999-476f0fa2309e  qemu-announce-self  
 b45e1a74-e5b4-4af1-bd91-1d14bb65f9d8  qemu-announce-self-rarp

virsh # 

r
 
Die zugehörigen XML-Dateien findet man unter “etc/libvirt/nwfilter”.

Um die Sache je nach Blickwinkel noch komplizierter zu machen, erlaubt libvirt das Einbinden dieser Filter und eigener Regel-Sätze in XML-Form in die XML-Konfigurationsdateien zu Netzen/Gästen. Das wird im Detail hier behandelt:
https://libvirt.org/ formatnwfilter.html

Um Zugriff auf die iptables/ebtables-Regeln zu bekommen, kann man kann die Filter dann einfach mal testweise über die Einbindung in libvirt-XML-Dateien zur Anwendung bringen, sich die zugehörigen generierten iptables- und ebtables-Regeln über “iptables -L” und “ebtables -L” anzeigen lassen und später in modifizierter Form in eigene iptables-Scripts integrieren.

Folgender wichtiger Artikel zeigt, wie etwa der wichtige “clean-traffic”-Filter mit Hilfe von ebtables konkret von libvirt implementiert wird (besser im Jahr 2010 wurde):
https://www.redhat.com/ archives/ libvir-list/ 2010-June/ msg00762.html

Security-Themen im Zusammenhang mit virtuellen Netzen

Auch virtuelle Switches können durch dieselben Angriffsmuster manipuliert werden, wie reale Switches. ARP Spoofing und Flooding sind hier die Stichworte. Etliche Probleme der Berücksichtigung von gebridgten Devices bestehen deshalb darin, dass der Layer 2 des OSI-Schichtenmodells von iptables-Regeln ignoriert wird.

http://serverfault.com/ questions/ 457262/ configure-iptables-on-kvm-host-to-block-guest-bridge-traffic

Das führt z.B. bei der Benutzung von conntrack-Regeln unter iptables potentiell zu Schwierigkeiten. Gastsysteme können – z.B. über Ausnutzung des conntrack-Verhaltens und Erzwingen eines HUB- statt Switch-Verhaltens auf der Bridge den eigenen Datenfluss mit dem anderer Gäste mischen.

ARP-Spoofing kann sogar zu Problemen bei 2 getrennten Bridges führen. Siehe hierzu folgende Diskussionen:

http://patchwork.ozlabs.org/ patch/29319/

https://bugzilla.redhat.com/ show_bug.cgi?id=512206

http://serverbugs.com/ Question.aspx? q=-conntrack-tracking-private-TCP-sessions-between-VMs&i=593650
und entsprechende Teile von

http://blog.klauskiwi.com/ wp-content/ uploads/ 2010/08/ KVM-Security_en.pdf

Will man iptables auf direkten Bridges zu physikalischen Devices nutzen, so sind “physdev”-Definitionen erforderlich:
Siehe
http://people.netfilter.org/ kadlec/ ipset/ iptables.man.html
und dort den Abschnitt zu “physdev”.

Siehe auch:

und dort S.504 bis S.517.

Es wurde jedoch aus Sicherheitsgründen vielfach empfohlen, iptables auf direkt gebridten Hosts abzuschalten. Siehe hierzu neben den obigen Artikeln auch die Seiten 3 und 4 des folgenden Artikels:

https://www-01.ibm.com/ support/ knowledgecenter/ linuxonibm/liaat/ liaatsecurity_pdf.pdf
und

https://www-01.ibm.com/ support/ knowledgecenter/ linuxonibm/ liaat/ liaatkvmsecnetfilter.htm

https://wiki.archlinux.org/ index.php/ QEMU#Bridged_networking_ using_qemu-bridge-helper

http://wiki.libvirt.org/ page/ Networking – s. dort den Bereich über (direct) “bridged networking”

http://www.cyberciti.biz/ faq/ debian-ubuntu-linux-kvm-guest-shared-physical-network/

https://docs.fedoraproject.org/ en-US/ Fedora/13/ html/ Virtualization_Guide/ sect-Virtualization-Network_ Configuration-Bridged_ networking_with_libvirt.html

Siehe jedoch als Gegenmeinung :

http://netfilter.vger.kernel.narkive.com/ M0WsSp2h/ security-validity-of-iptables-in-multi-bridge-environment

Was immer ihr davon haltet, ich meine, dass Abhilfe generell durch die zusätzliche Etablierung von restriktiven ebtables-Regeln möglich ist. Die schaden zumindest nicht und helfen auch bzgl. ARP-Spoofing.

Zum Thema des ARP-Spoofings siehe u.a.

https://www.berrange.com/ posts/ 2011/10/03/ guest-mac-spoofing-denial-of-service-and-preventing-it-with-libvirt-and-kvm/

http://www.admin-magazine.com/ Articles/ Arp-Cache-Poisoning-and-Packet-Sniffing

sowie

http://www-01.ibm.com/ support/ knowledgecenter/ linuxonibm/liaat/ liaatkvmsecmac.htm

http://www.linux-magazin.de/ Ausgaben/2004/ 12/ Zugbruecke

http://www.linux-magazin.de/ Ausgaben/2004/12/ Zugbruecke/ %28offset%29/6

Etwas Off-Topic: ARP-Spoofing und Flooding wird übrigens auch als Problem für Docker-Implementierungen diskutiert:

https://nyantec.com/ en/ 2015/03/20/ docker-networking-considered-harmful/

http://arxiv.org/ pdf/1501.02967.pdf

Die Argumente in der letzten Untersuchung gelten meiner Meinung nach für KVM-Systeme analog und belegen, dass es wichtig ist, ebtables-Regeln zu etablieren!

Bridging und ebtables-Regeln sind in genereller Form hier diskutiert:

http://ebtables.netfilter.org/ misc/brnf-faq.html

http://ebtables.netfilter.org/ br_fw_ia/ br_fw_ia.html

http://ebtables.netfilter.org/ documentation/ bridge-nf.html

http://ebtables.netfilter.org/ misc/ brnf-faq.html

Ein kleines Fallbeispiel, dass erneut die Bedeutung von ebtables aufzeigt, ist hier besprochen:
http://serverfault.com/ questions/ 607224/ iptables-matching-packets-for-bridged-interface

Ich hoffe, ich habe mit diesen Lektüre-Hinweisen dem einen oder anderen
einen kleinen Fahrplan für das Erforschen der Tiefen und Untiefen virtueller Netze und Linux und speziell mit KVM/qemu an die Hand gegeben.

 

OpenMP Jobs unter Linux auf eine bestimmte Anzahl von Prozessor-Cores/Threads begrenzen

Manchmal stößt man als Linux-Nutzer auf etwas exotische Themenstellungen. Über eine solche bin ich neulich bei der Vorbereitung eines beauftragten Pentest gestolpert. Für Vor-Ort-Tests schleppt man dann seine Laptops zum Kunden und möchte natürlich vorab wissen, wo die physikalischen Grenzen für die Durchführung des einen oder anderen Test liegen – und für welche Aufgaben man im Nachhinein auf Spezialsysteme zurückgreifen muss.

Viele Programme, die parallele Aufgaben- und Lastverteilung über mehrere Prozessorkerne hinweg unterstützen sollen, nutzen dafür die OpenMP API und lassen sich so gezielt für Multithreading kompilieren.

Siehe hierzu :
https://en.wikipedia.org/wiki/OpenMP
http://www.linux-mag.com/id/4609/

Ein klassisches Beispiel ist das Programm JtR zur Hashanalyse (um es mal freundlich auszudrücken). Dieses Tool ist auf eine hohe Performance des Systems angewiesen, auf der es läuft. Kann man plattformbedingt nicht die GPU für die kontinuierlich durchzuführenden Kryptierungsaufgaben einsetzen, so nutzt man zumindest die für OpenMP kompilierte Variante und mehrere CPU-Threads, um JtR schneller seine Arbeit erledigen zu lassen.

Das hat je nach Verschlüsselungstiefe der zu untersuchenden Hashes gilt natürlich seine Grenzen … Aus Sicht des Security-Beraters gilt aber: Erfolgreiche Hash-Dekodierungen vor Ort helfen enorm, zusammen mit dem Kundenbeauftragten für Sicherheit die Awareness der Angestellten für die Wahl hinreichend guter Passwörter zu schärfen – im Besonderen wenn das Haus-und Hof-Betriebsysteme zur Hasherzeugung nur begrenzte oder eben schnell ausführbare Kryptoalgorithmen verwenden.

Siehe für eine Diskussion der Hash-Algorithmen unter MS Windows etwa
http://security.stackexchange.com/questions/17672/windows-7-password-hash-security
und die dort vorhandenen Kommentare.

Wie bei multi-thread-basierten Programmen generell kann eine maximale Performance bei der Programmausführung ggf. auch Nachteile nach sich ziehen. Wer etwa mal größere PHP-Projekte unter Eclipse Juno bereinigen lassen musste, kann ein Lied davon singen – da gingen auch Workstations mit 16 CPU Threads für einige Zeit in die Knie – wenn hunderte Klassenbibliotheken parallel und auf allen CPU-Cores validiert und indiziert wurden. Ein paralleles Arbeiten etwa mit Libreoffice-Anwendungen wurde dann im fraglichen Zeitraum zur Qual. (Mit Eclipse Mars wurde die Politik der maximalen CPU-Nutzung Gott sei Dank geändert.)

Muss man nun – wie in meinem Fall im Rahmen eines Penetrationstests –

  • vor Ort beim Auftraggeber mit Systemen begrenzter Leistungsfähigkeit arbeiten,
  • eine von Haus aus ressourcenbelastende Virtualisierungsumgebung einsetzen
  • und kann man bestimmte Aufgaben nicht an Remote-Spezialsysteme deligieren,

so wird ein Übermaß an Ressourcenbereitstellung für die Performance eines Programmes wie JtR ggf. zum Verhängnis für andere parallel abzuwickelnde Aufgaben.

JtR in der OpenMP-Variante für Kali z.B. nutzt ohne weitere Parameter automatisch die maximale (!) Anzahl der zur Verfügung stehenden CPUs, die dann auch zu 100% ausgelastet werden. Das gleichzeitige Auslasten vieler Prozessor-Kerne kann schnell zum Engpass für weitere ressourcenintensive Aufgaben werden, die man gleichzeitig und u.U. auf weiteren Virtualisierung-Gastsystemen erledigen will oder muss.

Dies führte mich zur Frage: Wie steuert man eigentlich den Thread-Zugriff eines OpenMP-Programs unter Linux – genauer: Wie legt man die Anzahl der CPU-Threads fest, die das Programm nutzen soll?

Es gibt zwei sehr einfache Antworten:

Steuerung über die
Virtualisierungsumgebung:

Läuft das OpenMP-Programm auf einer virtuellen Maschine (KVM, VMware, Libcontainber, ..) so kann man natürlich die bereitgestellten CPU-Threads über die Grund-Einstellungen zum virtualisierten Gastsystem steuern.

Steuerung über die Shell (u.U. in der virtualisierten Umgebung):
Hier muss man einfach eine Umgebungsvariable für den zu startenden Prozess setzen und exportieren:

mytux:~# export OMP_NUM_THREADS=n

“n” steht für Anzahl der zu nutzenden Threads. Danach startet man den OpenMP-nutzenden Job.

Man muss es – wie so oft – halt nur wissen!

Will man gezielt alle verfügbaren Core für ein OpenMP-Programm einsetzen, so hilft:

export OMP_NUM_THREADS=`grep ‘processor’ /proc/cpuinfo | wc -l `

Viel Spaß bei der gezielten Ressourcenauslastung durch OpenMP-Programme – ob als beauftragter Pentester (natürlich immer [!] mit der expliziten schriftlichen Erlaubnis des Auftraggebers) oder aber auch bei der Entwicklung und dem Einsatz eigener Hochperformance-Programme unter C oder Fortran!

SFTP mit Key-Authentication auf (gehosteten) Linux-Servern für Web-Entwickler mit unterschiedlichen Privilegien – I

Da ich immer mal wieder SSH- und SFTP-Verbindungen für gehostete LAMP-Test- und LAMP-Produktiv-Server unter Linux (genauer: Opensuse) konfigurieren muss, stelle ich in einer Artikelserie mal ein paar Hinweise zu den durchzuführenden Überlegungen und administrativen Schritten zusammen.

Ich setze im nachfolgend beschriebenen Fall nur das interne SSH-Subsystem für SFTP und Dateitransfers auf den Test-/Produktiv-Server ein. Bzgl. eventuell vorzusehender unterschiedlicher Zugriffsrechte der (S)FTP User genügt aus meiner Sicht die Diskussion eines Beispiels mit 2 User-Gruppen und zwei unterschiedlichen (Domain-) Verzeichnissen auf dem Server.

Ich gehe im Folgenden davon aus, dass der Leser bereits über etwas Erfahrung mit der Einrichtung von SSH auf einem Remote-System besitzt. Wenn nicht: Siehe
Strato-V-Server mit Opensuse 12.3 – IV – SSH Key Authentication
und vorhergehende Artikel. Im vorliegenden, ersten Artikel der aktuellen Serie behandle ich grundlegende SSH-Einstellungen nur relativ kurz und diskutiere sie hauptsächlich unter Sicherheitsaspekten. Ein zweiter Artikel befasst sich dann mit der konkreten User-Einrichtung für die SFTP-Nutzung.

Abgrenzung SFTP-Uploads von SVN-Updates über SSH

Wir lassen im diskutierten Kontext die Möglichkeiten von SVN (in Kombination mit SSH) für das systematische Füllen von Domain-Verzeichnissen des (Web-) Test-Servers außer acht – obwohl viele Entwickler dies aus Bequemlichkeit nutzen.

Nach meiner Ansicht hat die Code-Versionsverwaltung in Entwicklungsphasen logisch nur wenig mit dem gezielten Upload konsolidierter Dateien einer bestimmten SW-Test- oder -Produktiv-Version in entsprechende Domainen eines Web-Test- oder -Produktiv-Servers zu tun. Letzteres – also der Upload – entspricht eher Export-Vorgängen (z.B. unter Eclipse) oder eben gezielten FTP-Transfers. Unter diesen Prämissen wie auch unter Sicherheitsaspekten hat SVN auf einem exponierten Test- oder Produktivsystem eigentlich wenig verloren. SVN ist vielmehr Teil der Service-Landschaft der Entwicklungsumgebung im lokalen Netz und dient dort der laufenden Protokollierung von Versionsständen einzelner SW-Files sowie deren Konsolidierung.

Elementare Ziele, Anforderungen und Voraussetzungen

Gehosteter Server
Der Server habe die Adresse “serv@myhoster.net” und sei gehostet. Der reguläre SSH-Zugang zu diesem Server für Verwaltungszwecke erfolge zunächst über einen (unpriviligierten) User “usu” über den (high) Port “xxxxx”. Über den “usu”-Account und die Shell logt man sich dann bei Bedarf als “root” ein.

Authentifizierung über Private/Public SSH-Keys
Ein sicherheitsrelevanter Aspekt ist im Falle gehosteter Server die Authentifizierung der Entwickler mittels

  • eines privaten SSH-Keys auf dem Client
  • sowie dessen Gegenstück, nämlich eines auf dem Server hinterlegten Public Keys,

anstelle von User IDs und Passwörtern. Ich gehe im ersten Beitrag auf die wichtigsten zugehörigen Anweisungen in der SSHD Konfigurationsdatei ein. Durch Key-Authentication lassen sich Brute Force Angriffe auf den SSH-Zugang eindämmen; als Admin sollte man aber nicht übersehen, dass durch ein solches Verfahren auch die Anforderungen an die sichere Verwahrung der Schlüssel auf den Clients steigen.

Passwortschutz des private Keys auf dem Client – ?
Eine “Private Key”-Datei auf einem Client-System stellt eine potentielle Gefahrenquelle dar:

  • Mobile Clients können gestohlen werden.
  • n

  • Desktops wie mobile SSH/SFTP-Clients können gehackt werden.

Ein Passwortschutz des privaten Keys ist deshalb eine Mindestanforderung an die Sicherheit – wenngleich auch das nicht gegen implantierte Key-Logger schützt. Eine interessante Frage ist deshalb:

Was gilt im Zshg. mit Key-Passwortschutz eigentlich für gängige SFTP-Clients?

Welcher SFTP-Client unterstützt den Umgang mit Private Keys, wenn diese im Sinne einer durchgehenden Sicherheit auf den Client-Systemen passwort-geschützt hinterlegt werden sollen? Ich gehe in einem der nachfolgenden Artikel deshalb kurz auf diese Frage ein.

Kein SSH-Shell-Zugang
Die User – hier Entwickler – sollen das SSH-basierte SFTP nur für File-Transfers nutzen; sie sollen auf dem Server jedoch keinen Shell-Zugang über SSH erhalten. Administrative Aufgaben auf Test- oder Produktiv-Servern remote durchzuführen, bleibt in unserem Szenario ausschließlich Server-Administratoren vorbehalten.

Verzeichnisse, Entwicklergruppen und Rechte
Während die Einrichtung des SFTP-Servers für eine Key-Authentifizierung nur wenig von Vorgehensweisen abweichen dürfte, die bereits an anderer Stelle im Internet beschrieben sind, ist in unserem Beispiel ein zusätzlicher Punkt folgender:

In Web-Entwicklungsprojekten ist es sinnvoll, definierte Gruppenrechte und manchmal auch User-Rechte auf bestimmten SFTP-Verzeichnissen des Servers – die dort in der Regel Web-Domain-Verzeichnisse umfassen – zu erzwingen. Warum?

  • Einerseits will man die User (Entwickler) womöglich in Log-Dateien unterscheiden können. Man wird Ihnen (genauer: ihren UIDs) deshalb in jedem Fall unterschiedliche Authentifizierungs-Keys zuordnen. Ferner sollen die Entwickler ggf. aber auch gruppenübergreifend kollaborieren. Deshalb braucht man abgestimmte Lese- und Schreib-Rechte auf Verzeichnissen für eine (oder mehrere) definierte Gruppe(n). Für die Darstellung besonderer Privilegien können auch user-bezogene Rechte erforderlich werden. Das Schreibrecht wird man auf einem exponierten Web-Server in jedem Fall so gut wie nie “others” zuordnen.
  • Zudem ist zu gewährleisten, dass der Webserverprozess selbst transferierte Directories und Files lesen und im Falle der Bereitstellung von dynamisch geschriebenen Download-Dateien auch beschreiben kann. Der User, unter dem der Webserver-Prozess läuft, muss auch dann wieder Teil einer Gruppe werden, wenn man “others” keine Schreibrechte zuordnen will.
  • Es ist durchaus normal, dass unterschiedliche Privilegien des Zugriffs auf Verzeichnisse in ein und derselben Verzeichnis-Hierarchie für die Mitglieder unterschiedlicher Entwicklergruppen gefordert werden. Der Zugang zu bestimmten Verzeichnissen und Subverzeichnissen soll in unserem Beispiel per SFTP Chroot und durch das Setzen von Zugriffsrechten auf bestimmte Verzeichnisse limitiert werden. Die Entwickler sollen in unserem Beispiel in 2 Gruppen mit unterschiedlichen Zugriffsrechten auf die Verzeichnishierarchie unterteilt werden.

Wir lassen ferner Zugriffe nur auf Web-Domain-verzeichnisse zu; wir erlauben den Entwicklern keinen Zugriff auf private Home-Verzeichnisse.

Zwei Entwickler-Gruppen mit unterschiedlichen Privilegien
Wir diskutieren in unserem Beispiel den abgestuften Zugriff zweier unterschiedlich privilegierter Entwicklergruppen auf Verzeichnisse unterhalb eines Chroot-Jails “/srv/www/htdocs/webs/project”.

/srv/www/htdocs/webs/project
|
— test
|
— adm
|
— rc

Die Subverzeichnisse entsprechen z.B. verschiedenen Web-Domainen oder Entwicklungsprojekten mit jeweils weiteren Sub-Sub-Verzeichnissen. Da unterschiedliche Berechtigungen für die Domain-Verzeichnisse gegeben sein sollen, werden im Beispiel zwei
Usergruppen devgrp1 und devgrp2 eingerichtet.

Zusätzlich wird der Zugriff der Gruppe “devgrp2” auf Inhalte eines weiteren Chroot-Verzeichnis – hier “test” – eingeschränkt. Die Mitglieder der “devgrp1” dürfen dagegen auf alle definierten Domain-Verzeichnisse zugreifen. Sie sind deshalb zugleich sekundäre Mitglieder der “devgrp2”.

Als Beispiel-User wählen wir hier die User “alpha” (Mitglied von “devgrp1” und “devgrp2”) und “beta” (Mitglied von “devgrp2”). Andere Berechtigungsszenarien lassen sich später aus diesem Beispiel zwanglos ableiten.

  • Mitglieder devgrp1: alpha (Zugriff auf alle Verzeichnisse)
  • Mitglieder devgrp2: beta, alpha (Zugriff nur auf Inhalte von “test”)

Grundlegende Konfiguration und Sicherheitsaspekte der SSH-Einrichtung

Wie man einen Opensuse-Server bei einem Hoster wie Strato grundsätzlich für einen SSH-Zugang mit verschobenem Port und Key-Authentifizierung konfigurieren kann, habe ich bereits in früheren Artikeln in diesem Blog besprochen. Siehe etwa:
Strato-V-Server mit Opensuse 12.3 – IV – SSH Key Authentication
und vorhergehende Artikel.

Ich gehe in diesem Artikel entsprechend davon aus, dass es bereits einen elementar eingerichteten SSH-Service gibt und diskutiere nur einige wichtige Optionen der Konfigurationsdatei “/etc/ssh/sshd_config” des einzurichtenden SSHD-Daemons (s.u.).

Ein paar Hinweise und Warnungen:

Je nachdem, was man an Hosting-Paket (Virtual Server etc.) geordert hat, richtet der Provider eine elementares Linux mit SSH-Zugang ein – meistens ausschließlich für den User root. In der Regel wird man das System in einem ersten Schritt upgraden/updaten und danach auch die SSH-Konfiguration remote und schrittweise abändern. Dabei ist Vorsicht angebracht! Man will sich bei Experimenten mit der SSH-Konfiguration ja schließlich nicht selbst vom Systemzugang ausschließen. Bitte beachten Sie die diesbzgl. Hinweise in den oben genannten Artikeln. Unbedingt sollte man sich beim Provider nach Notfall-Maßnahmen im Falle eines nicht mehr möglichen SSH-Zugangs erkundigen. Meist ist das Booten eines Notfall-Systems mit anschließendem Platten- und Dateizugriff möglich …. Die Notfall-Maßnahmen sollte man auch mal ausprobieren …

Im Zshg. mit SSH- und System-Startup-Modifikationen ist dafür zu sorgen bzw. zu prüfen, dass der SSHD-Daemon bei jedem (automatischen) Systemstart aktiviert wird. Gerade bei gehosteten Servern ist dies ein kritischer Punkt. Provider fahren u.U. die gehosteten Server ohne Rückfrage automatisch rauf und runter, wenn Wartungsmaßnahmen dies erfordern. Nach einem solchen Reboot muss natürlich der SSH-Service auch wieder verfügbar sein.

Jemand der SSH selbst auf einem gehosteten Server konfiguriert, sollte sich deshalb auf Opensuse-, Red Hat- und künftig wohl auch Debian-Systemen mit den entsprechenden Optionen des “systemctl”-Kommandos von “systemd” vertraut machen und überprüfen, dass der SSH(D)-Service für den automatischen Start beim Booten aktiviert ist. Unter Opensuse führt

systemctl enable sshd.service

zur Aktivierung. Den aktuellen Service-Zustand – inkl. Aktvierung – prüft man mit:

mylinux:~ # systemctl status sshd.service
sshd.service – OpenSSH Daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled)
Active: active (running) since Sat 2015-08-08 09:16:50 CEST; 3h 9min ago
Process: 1615 ExecStartPre=/usr/sbin/sshd-gen-keys-start (code=exited, status=0/
SUCCESS)
Main PID: 1650 (sshd)
CGroup: /system.slice/sshd.service
└─1650 /usr/sbin/sshd -D
 
Aug 08 09:16:50 mylinux sshd-gen-keys-start[1615]: Checking for missing server keys in /etc/ssh
Aug 08 09:16:50 mylinux sshd[1650]: Server listening on 0.0.0.0 port xxxxx.
Aug 08 09:16:50 mylinux sshd[1650]: Server listening on :: port xxxxx.

Das korrekte Reboot-Verhalten des gehosteten Servers ist nach Systemeingriffen natürlich nicht nur für SSH/SFTP sondern auch andere Serverdienste zu testen.

Ferner gilt:

Bevor man bestimmte User definitiv vom SSH-Zugang ausschließt, sollte man immer die Zugangsmöglichkeit für einen oder mehrere verbleibende User explizit testen. Mindestens ein verbleibender User sollte immer vorhanden sein.

Ähnliches gilt für die Umstellung auf Key Authentication:

Bevor man eine passwort-basierte Authentisierung für alle User abstellt, sollte man zunächst ausschließlich mit userspezifischen Festlegungen arbeiten und für einzelne User die Funktionstüchtigkeit der Key-Authentifizierung testen. Zur Einrichtung userspezifischer SSHD-Konfiguration dienen die “Match”-Anweisung und zugehörige Blöcke am Ende (!) der SSHD-Konfigurationsdatei. Man lese hierzu unbedingt die ssh-man-Seiten.

Auch der nachfolgende Artikel

SFTP mit Key-Authentication auf (gehosteten) Linux-Servern für Web-Entwickler mit unterschiedlichen Privilegien – II

zeigt beispielhaft, wie man userspezifische Anweisungen anlegt und wie diese aussehen können.

SSH-Zugang für root?
Der direkte SSH-Zugang für root sollte auf einem exponierten System i.d.R. nicht zugelassen werden. Er ist auch überhaupt nicht erforderlich. Erlaubt werden soll und muss der SSH-Zugang im Anfangsstadium dagegen für einen bereits erwähnten, unpriviligierten User “usu”.

Ein solcher unpriviligierter User muss auf dem gehosteten Server erstmal eingerichtet werden. Meist existiert auf gehosteten Servern anfänglich nur der User root. Bevor man den SSH-Zugang für root sperrt, muss der Zugang inkl. Shell-Nutzung für den neuen unpriviligierten User explizit getestet werden. Die Zugangsdaten des unpriviligierten Users sind vom Admin geheimzuhalten. Dieser Account bleibt sein Weg ins System – über den “usu”-Account erfolgt dann indirekt über “su -” der Login als root.

Für den User “usu” sei auf unserem Server bereits ein Public/Private-Key-Paar eingerichtet. Siehe hierzu den oben erwähnten Artikel. Wie man das für andere Accounts macht, zeigt beispielhaft auch der zweite Artikel dieser Serie.

Begrenzung des SSH-Zugangs auf bestimmte IP-Adressen?
Eine spezielle Sperre des Zugangs für allgemeine Host-IP-Adressen bzw. eine Zugangserlaubnis für definierte IP-Adressen gestalte ich normalerweise über eine Firewall und nicht über die SSH-Konfiguration. Die Firewall erlaubt dann für vordefinierte IPs den Zugang zu einem definierten High Port xxxxx für SSH und zu einem definierten Port für HTTPS.

Es sei an dieser Stelle aber ausdrücklich auch darauf hingewiesen, dass die weiter unten benutzte Anweisung

AllowUsers uid

Zusätze der Form

AllowUsers uid@ip.add.re.ss

erlaubt. Gerade bei wenigen SSH/SFTP-Usern, die immer von Clients mit fixer IP-Adresse aus zugreifen, ist das eine gute Möglichkeit, die Nutzung des SSH-Services weiter einzugrenzen.

An dieser Stelle sei auch angemerkt, dass man auf Systemen mit mehreren Netzwerk-Interfaces eingrenzen kann, auf welchem Interface der SSHD angeboten werden soll. Dies geht über die IP-Adresse, die dem Interface zugeordnet ist und der Direktive “ListenAddress”. Für mehr Informationen siehe etwa:
http://www.thegeekstuff.com/2011/
05/openssh-options/

Portverschiebung – Obfuscation
Der Nutzen einer Zuordnung des SSH-Services zu einem selbst definierten Port (hoher Portnummer) wird unterschiedlich diskutiert. Ich persönlich ändere den SSH-Port regelmäßig ab, da zumindest meine Erfahrung zeigt, dass die Anzahl bestimmter Angriffsversuche von Skript-Kiddies danach zurückgeht. Nachfolgend steht “xxxxx” für eine 5-stellige High-Port-Nummer.

Ausschnitte aus der SSHD-Konfigurationsdatei “/etc/ssh/sshd_config”

Nachfolgend ein paar Anweisungen aus einer finalen Konfigurationsdatei für den SSHD als Grundlage von SFTP:

Port xxxxx 
# z.B. Port 64311

AllowUsers usu 
PermitRootLogin no
....
....
RSAAuthentication yes
PubkeyAuthentication yes

# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile   .ssh/authorized_keys

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
#PermitEmptyPasswords no

# Change to no to disable s/key passwords
ChallengeResponseAuthentication no

# Set this to 'yes' to enable PAM authentication, account processing, 
# and session processing. If this is enabled, PAM authentication will 
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  ....
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM yes

AllowAgentForwarding no
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
#X11DisplayOffset 10
#X11UseLocalhost yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
UsePrivilegeSeparation sandbox          # Default for new installations.

# override default of no subsystems
#Subsystem      sftp    /usr/lib/ssh/sftp-server -u 0007
Subsystem       sftp    internal-sftp

# This enables accepting locale enviroment variables LC_* LANG, see sshd_config(5).
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL

MaxSessions 50
MaxAuthTries 20
MaxStartups 20

....
.....

Hinweis zur SFTP-Aktivierung:
Zu beachten ist die Aktivierung des internen SSH SFTP-Subsystems über

Subsystem    sftp    internal-sftp

Das ist zunächst die einzige Stelle, an der SFTP hier überhaupt ins Spiel kommt! Und noch ein Hinweis für für erfahrene Admins: die “-u” Option von internal-sftp wird hier nicht angewendet. Wir kommen darauf im 2-ten Artikel dieser Serie zurück.

Wichtiger Hinweis zum schrittweisen Vorgehen:
Bitte beachten Sie, dass Sie eine solche finale Konfiguration, die den SSH-Port verschiebt sowie root-Zugang und einen passwort-basierten Zugang grundsätzlich ausschließt, im Sinne der obigen Warnungen nur schrittweise etablieren sollten. Sehen Sie hierzu die oben erwähnten anderen Artikel dieses Blogs.

Kommentierung einiger sicherheitsrelevanter Anweisungen in der SSHD-Konfiguration

So absurd sich das anhören mag: Ein grundsätzliches Problem im Zusammenhang mit SFTP ist gerade, dass wir auf dem entsprechenden Server SSH einrichten müssen.

Der Grund für diese Aussage ist: SSH in den Händen gewiefter und böswilliger User stellt ein enormes potentielles Sicherheitsproblem dar. Siehe z.B.:
http://
www.informit.com/articles/article.aspx?p=602977

https://threatpost.com/encrypted-tunnels-enable-users-circumvent-security-controls-060109/72742

Eines der größten Probleme ist, dass User mit Shellzugang SSH dazu benutzen können, um sog. “Reverse Tunnels” zu privaten Systemen durch Firewalls hindurch zu etablieren, und in diesem Zusammenhang sogar eigene Port-Forwarding Tools einsetzen. Die aus meiner Sicht wirksamen Sicherheitsmaßnahmen gegen dieses Gefährdungspotential sind in diesem Zusammenhang:

  1. den Zugang zu SSH auf wenige User einzugrenzen
  2. den Usern, die SSH lediglich als Basis von SFTP oder als Basis von geplanten, verschlüsselten Tunneln zu Applikationen einsetzen dürfen, den Shellzugang zu entziehen.
  3. Massive Strafandrohungen bei Verletzung von Policies, wenn Administratoren Shell-Zugangsrechte erteilt werden müssen.

Welche Einstellungen in der obigen Datei sshd_config betreffen die Sicherheit?

Wir erkennen zunächst das Sperren des root-Users für SSH über die Anweisung “AllowUsers”. Ein irgendwie geglückter SSH Crack beinhaltet dann zumindest nicht unmittelbar das Risiko einer Betätigung mit Root-Rechten.

Ferner sehen wir die Festlegung eines besonderen Ports “xxxxx” für den SSH-Service. Dieser TCP-Port muss natürlich in der Firewall geöffnet werden. Die Verschiebung des SSH-Services vom Standardport hält gewiefte Angreifer, die ausführliche Portscans unternehmen, deshalb nicht lange ab.

Password-Authentifizierung ist trotz PAM im Sinne der Kommentare im Konfigurationsfile abgeschaltet. Wir lassen PAM hier an, um auf PAM-Ebene noch weitere Möglichkeiten zur User-Einschränkung bzw. User-Überwachung zu bekommen. Wer dem nicht traut, kann die Nutzung von PAM aber auch abschalten.

Die Zeilen

RSAAuthentication yes
PubkeyAuthentication yes

sorgen dagegen für die von uns gewünschte Authentifizierung mit asymmetrischen RSA-Schlüsseln.

Unterbinden von Port Forwarding und Gateways für Tunnel
Da wir für SFTP kein TCP-Forwarding über SSH benötigen, schalten wir es aus Sicherheitsgründen ab. Die Nutzung unseres Servers als SSH-Gateway ist aus Sicherheitsgründen völlig unerwünscht. Wir schalten deshalb auch den Parameter GatewayPorts ab. X11 sollen unsere lieben SFTP-User natürlich auch nicht nutzen.

Das Einrichten und Nutzen von problematischen Reverse Tunnels über unseren Server ist damit künftig für unsere Entwickler schon nicht mehr so ohne weiteres möglich. Wir müssen weiter unten dennoch den Shell-Zugang für die definierten SFTP-User “alpha” und “beta” sperren, denn, wie die SSH-man-page so schön ausführt, gilt

Note that disabling TCP forwarding does not improve
security unless users are also denied shell access, as they can
always install their own forwarders.

U.a. netcat, portfwd und socat sind entsprechende Tools. See
https://www.digi77.com/the-art-of-port-forwarding-on-linux/
http://29a.ch/2009/5/10/forwarding-ports-using-netcat
Aber es geht u.U. auch einfacher:
http://clinging-to-reality.blogspot.com.br/2014/06/reverse-ssh-tunnel-if.html

Ein grundsätzlich wichtiger Punkt ist in diesem Kontext immer auch, dass ein umsichtiger Admin dafür sorgt, dass der sshd-Dämon auf dem Server nicht von jedermann gestartet werden kann:

chmod 754 /usr/sbin/sshd

Zur Sicherheit sollte man auch Compiler deaktivieren,
um das Kompilieren eigener Module aus eigenen Source-Quellen zu unterbinden.

Siehe zu einer Diskussion von Gefahren durch SSH und im Besonderen durch SSH Reverse Tunnels etwa:
http://www.techexams.net/forums/off-topic/67117-circumventing-network-security-via-ssh-tunneling.html

Einige Aspekte der Sicherheit werden im Zusammenhang mit verketteten Tunneln auch in folgendem Artikel angesprochen:
https://linux-blog.anracom.com/2013/11/22/ssh-getunnelter-datenbankzugang-fur-gehostete-lamp-server-i/

Sicherheitsanforderungen im Umgang mit privaten Schlüsseln

An dieser Stelle ist der dringende Hinweis angebracht, dass das sichere Verwahren von privaten Schlüsseln auf SSH/SFTP-Clients weiterer Schutzmaßnahmen bedarf. Hinsichtlich der Sicherheit ist immer die gesamte Kette der involvierten Systeme zu betrachten! Ein SSH-Auth-Key auf einem Windows-System in einem privaten oder öffentlichen Netzwerkumfeld ist ohne weitere Schutzmaßnahmen ggf. gefährlicher als eine Authentifizierung mit User IDs und einem generierten Passwort! Ferner:
Es gibt Leute,

  • die die Verwendung ein und desselben Key-Paars für verschiedene Server
  • und die dauerhafte Verwahrung von Keys auf einem System ohne weitere Verschlüsselungskomponenten wie etwa für die Dateisysteme, auf denen die Schlüssel gelagert werden,

für potentiell gefährlich halten. Gerade der zweite Punkt ist im Zusammenhang mit einem oben bereits diskutierten Diebstahl (z.B. eines Laptops) unbedingt zu unterstreichen. Ich meine aber, dass der generellen Absicherung der Client-Systeme im regulären Betriebszustand eine ebenso große Bedeutung zukommt. Auf einem Client-System, das mit Key Loggern und Trojanern kompromittiert wurde, nutzt der Einsatz einer schlüsselbasierten Authentisierung gar nichts.

Es versteht sich aus meiner Sicht von selbst, dass der private Schlüssel zusätzlich durch ein Passwort geschützt sein sollte. Man tut deshalb gut daran, sich nach FTP-Clients umzusehen, die Key-Authentifizierung mittels passwortgeschützten Private Keys unterstützen.

Genug für heute. Der nächste Artikel

SFTP mit Key-Authentication auf (gehosteten) Linux-Servern für Web-Entwickler mit unterschiedlichen Privilegien – II

befasst sich dann mit der konkreten Einrichtung unserer SFTP-User.

Allgemeine Links

http://www.unixlore.net/articles/five-minutes-to-even-more-secure-ssh.html

http://www.thegeekstuff.com/2011/05/openssh-options/