Archiv für die Kategorie „Server“

Dynamische Firewall mit iptables

Samstag, 10. Juli 2010

Einer der Gründe warum ich meinen Netgear-Router zum Switch/AP degradiert habe war, dass ich mehr Kontrolle über meine Datenströme haben will. Meine grundlegende Anforderungen sind:

  • Aufschlüsselung der Bandbreite nach Clients
  • unterwerfen von unbekannten Clients unter eine dynamische Bandbreiten Beschränkung
  • gute Wartbarkeit
  • gute Monitoring-Möglichkeit

Die ursprüngliche Anregung habe ich diesem Artikel entnommen. Man muss das Konzept nur noch um die Dynamik ergänzen, damit auch Clients verwaltet werden können die man vorher nicht kennt.

Unter Ubuntu hat man die Wahl zwischen der “uncomplicated Firewall” (UFW) und dem direkten Zugriff mittels iptables. Ich hab mich für iptables entschieden. Zum einen bin ich unter UFW zu schnell in Bereich gestoßen, bei den ich quasi iptables-Befehle geschrieben habe (nur ohne iptables vorangestellt). Zum anderen lieferte mir UFW zu viele “default”-Regeln aus, die mit “nicht löschen” markiert sind ohne zu Begründen warum. Hat man sich einmal in iptables eingearbeitet, so hat man die volle Freiheit die man braucht.

WICHTIGER HINWEIS:Beim Ausführen der folgenden Befehle sollte man in Reichweite des Rechners sitzen oder einen alternativen Zugang zum Rechner haben, da man sich u.U aussperrt.

Es empfiehlt sich für das einstellen der Firewall-Regeln ein eigenes Set an Scripts zu erstellen, z.B. unter /etc/firewall. So kann man mit einfacher die Firewall zu und abschalten.

Als erstes sollte man die default-Policy der Haupt-Regel-Ketten auf DROP setzen. Das ist zwar ein wenig Paranoid hilft aber ungemein, da man jedes Loch bewusst aufmachen muss.

Diese Kommandos verhindern das jegliches einloggen via Remote-Access-Tools. Es wird jeder Traffic gedropt.
iptables -L INPUT -p DROP
iptables -L FORWARD -p DROP
iptables -L OUTPUT -p DROP

Bei aller Regelwut sollte man eines bedenken, das Durchlaufen der Filterregeln kostet zeit. Je nachdem auf welchem Layer man die Entscheidung zum DROP/ACCEPT trifft, müssen die Pakete aufwändig entpackt werden. Einige Module beherrschen dabei die sogenannte DeepPackageInspection (DPI). Diese Filterregeln sollten jedoch nur sparsam zum Einsatz kommen da sie sonst den kompletten Netzwerktraffic drücken.

Als erstes sollte man eine Regel einrichten die jede Verbindung annimmt die schon mal geprüft wurde. Zu diesem Zweck nutzt man das “state”-Module bzw Connection-Tracking.

iptables -L INPUT -m state --state ESTABLISHED,RELEATED -j ACCEPT
iptables -L OUTPUT -m state --state ESTABLISHED,RELEATED -j ACCEPT

Nun sollte man die Input-Chain um statische Ausnahmen für die Fernwartung und eventuell benötigte Dienste erweitern. Vorzugsweise mit angaben aus welchem Netz diese Zugriffe erfolgen dürfen. Hier bietet es sich an eigene “Chains” anzulegen und so die Wartbarkeit zu erhöhen.

Beispiel: Es ist sinnvoll den “eingehenden” Traffic nach “Herkunft” zu unterscheiden. Traffic aus dem eigenen Netz unterliegt einer anderen Vertrauenswürdigkeit als externer Traffic.

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth1 -j ACCEPT #vom lokalen netz zum server alles zulassen
iptables -A INPUT -i ppp0 -j server_incoming_traffic
iptables -A INPUT -j LOG --log-level 4 --log-prefix "Input dropped by firewall: "

Die ersten beiden regeln erlauben jeglichen Traffic des “localhost” und “eth1″ Interfaces. Nur Traffic des ppp0 Interfaces wird einer Filter-Chain unterworfen. Führt in dieser “server_incoming_traffic”-Chain keine Regel zu einem DROP oder ACCEPT wird diese einfach verlassen und das LOG – Kommando wird ausgeführt, zum logging aber später mehr.

Die Filter-Chain kann dann so aussehen:

iptables -N server_incoming_traffic
iptables -A server_incoming_traffic -p tcp --dport 22 -j ACCEPT
iptables -A server_incoming_traffic -p tcp --dport 443 -j ACCEPT
iptables -A server_incoming_traffic -p tcp --dport 6880:6999 -j ACCEPT
iptables -A server_incoming_traffic -p udp --dport 6880:6999 -j ACCEPT

so kann man eine Reihe von Port-Ranges freigeben. Man kann auf Wunsch die Regeln auch noch ins unendliche erweitern. Aber immer dran denken, dass frisst Performance.

Beim ausgehenden Traffic kann man es ähnlich händeln, mit einer Ausnahme. Bei einigen Programmen weiß man im vornherein nicht ob und welche Ports genutzt werden. Hier führen DROP-Policys normalerweise dazu, dass die Programme nicht oder nur eingeschränkt funktionieren. Entweder reißt man für solche Programme große Lücken in seine Firewall oder nutzt das “owner”-Modul. Bei ausgehenden Traffic ist es möglich zu ermitteln unter welcher UID oder GID der Socket aufgemacht wurde. Auch darauf kann man filtern. Wenn man sich an den Standard hält jedem Dienst seinen eigenen User zu verpassen, kann man so schön auf Dienstebene freigeben, wer was darf.

Folgendes Beispiel gibt für rTorrent allen ausgehenden Traffic frei.

iptables -A server_outgoing_traffic -p tcp -m owner --uid-owner rtorrent -j ACCEPT
iptables -A server_outgoing_traffic -p udp -m owner --uid-owner rtorrent -j ACCEPT

Kommen wir nun zum Forward-Traffic. Hier wird es ein wenig kniffeliger. Zum ein landet hier alles was geroutet wird, zum anderen muss man hier mit dem “in” und “out” aufpassen. Am einfachsten fällt die Unterscheidung nach Zielnetzen.

iptables -A FORWARD -o ppp0 -s 192.168.99.0/24 -j outgoing_traffic
iptables -A FORWARD -o eth1 -d 192.168.99.0/24 -j incoming_traffic
iptables -A FORWARD -j LOG --log-level 4 --log-prefix "Forward dropped by firewall: "

Die regeln sind schnell erklärrt: alles was an ppp0 gerouted wird und vom Netz 192.168.99.0/24 kommt wird der Chain ” outgoing_traffic” unterworfen. Gleichlaufend wird alles was an eth1 geroutet wird und an das gleiche Netz gesendet wird der Chain “incoming_traffic” unterworfen. Alles andere wird geloggt und gedropt.

In diesen beiden Listen passiert nun das “magic”. Clients die ins “Internet” wollen müssen durch diese Regeln durch. Hier muss also am ende jeder Client aufgeführt sein der Accepted werden soll. Deshalb sollte man erstmal jeden Port droppen den man nicht geroutet wissen will. Das dient weniger dazu, dass der User die entsprechenden Programme nicht nutzt (ein umbiegen von Ports, beherrscht wohl jeder …) sondern soll eher verhindern, dass gewisse Windows-Clients unwissend ihre Existenz in Netz hinaus posaunen…

Danach muss man nun die Clients dynamisch in der Firewall freigeben. Das geht am besten über den DHCP-Deamon. Jeder Client muss sich eine IP holen, tut er es auf korrektem weg, wird er in der Firewall freigeschaltet, ansonsten bekommt er nicht gerouted. Das einzige Einfallstor sind dann noch IP/Mac spoofing. Das kann man aber bei kommen. Der dhcpd3-Daemon bietet für diese Zwecke die Möglichkeit ein Script auszuführen. Mittels folgendem Eintrag in der dhcpd.conf kann man Scripte anstoßen wenn ein Client ein Lease bekommt oder freigibt.

on commit {
  set ClientIP = binary-to-ascii(10, 8, ".", leased-address);
  set ClientMac = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6));
 
  log(concat("Commit: IP: ", ClientIP, " Mac: ", ClientMac));
 
  execute("/etc/firewall/add-client", ClientIP);
}
 
on release {
  set ClientIP = binary-to-ascii(10, 8, ".", leased-address);
  set ClientMac = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6));
 
  log(concat("release: IP: ", ClientIP, " Mac: ", ClientMac));
 
  execute("/etc/firewall/del-client", ClientIP);
}
 
on expiry {
  set ClientIP = binary-to-ascii(10, 8, ".", leased-address);
  set ClientMac = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6));
 
  log(concat("expire: IP: ", ClientIP, " Mac: ", ClientMac));
 
  execute("/etc/firewall/del-client", ClientIP);
}

Sobald man diesen Code in die /etc/dhcp3/dhcpd.conf einfügt, werden zwei Scripte ausgeführt. in diesem Fall del-client und add-client. Wichtig dabei ist, dass man in apparmor die Ausführung dieser Scripte von dhcpd zulässt. Entweder über das unsichere “ohne eigene Regeln ausführen” oder man legt schnell eine eigene Regel an.

In den Scripts wird einfach nur folgendes gemacht:

#!/bin/bash
RULEOCCURE=`iptables -L -n|grep -c $1`
if [ $RULEOCCURE -eq 0 ]; then
        /usr/bin/sudo /sbin/iptables -A outgoing_traffic -s $1 -j ACCEPT
        /usr/bin/sudo /sbin/iptables -A incoming_traffic -d $1 -j ACCEPT
fi
iptables -D outgoing_traffic -s $1 -j ACCEPT
iptables -D incoming_traffic -s $1 -j ACCEPT

Das $1 wird zur Laufzeit durch die gewünschte IP ersetzt.

Kommen wir nun zum Logging, Eine Firewall die nicht überwacht wird bringt recht wenig. Deswegen sollte man mitloggen was passiert. Rudimentär kann man mittels des iptables-Befehl selber auswerten.

iptables -L -v -n

Durch diesen Befehl wird für jede FilterChain aufgelistet wie oft sie angewendet wurde. (Counter und Bytes) So kann man auch raus finden welcher Client wie viel Traffic erzeugt. Geht der Counter für die Drops jedoch extrem hoch sollte man mal schauen was da eigentlich passiert. Für dieses anliegen braucht man die LOG – Rule.

iptables -A FORWARD -j LOG --log-level 4 --log-prefix "Forward dropped by firewall: "

Man braucht kein Präfix, es empfiehlt sich aber. So kann man mittels rsyslog dafür sorgen, dass alle Meldungen der Firewall in eine Datei geloggt werden. Dazu bedarf eines eines Eintrag in der rsyslog-config.

#
# FIREWALL logging
#
:msg, contains, "firewall"      /var/log/firewall
:msg, contains, "firewall"      ~

Mittels eines Scriptes kann man nun alle fünf Minuten diese Statistik und die Logs auswerten und ggf Gegenmaßnahmen einleiten. Zb “vollautomatisch” eine DROP-Regel für eine IP anlegen die eine flood-Attacke durchführt und gleichzeitig eine Warn-Mail absetzen.

Ubuntu als Router

Samstag, 10. Juli 2010

Handelsübliche “DSL-Router”, oder die sogenannten eierlegenden Wollmilch-Säue, nehmen einem im Alltag schon sehr viel Arbeit ab. Leider legen die Hersteller wenig Wert auf  Transparenz oder Wartbarkeit.  Spätestens wenn man etwas mehr Flexibilität will, darf man gleich richtig Tief in die Tasche greifen oder sich selber was basteln.

Linux-Distributionen kommen schon seit Jahren mit einer Grundkonfigurationen die sie mit wenigen Handgriffen in einen vollwertigen Router verwandelt.

Einen DSL-Modem kann man mittels pppoeconf ansprechen.

sudo pppoeconf

Der Installationsmechanismus ist ein wenig krüppelig aber anschließend hat man eine Verbindung ins Internet. Standardmäßig ist sie im “persistenten” Modus, soll heißen, nach einem 24 Stunden disconnect verbindet sich das System automatisch neu. Zusätzlich wird noch die möglichkeit geboten scriptes aufzurufen wenn die Verbindung auf oder abgebaut wurde. Das kann man dazu nutzen einen dyndns-Dienst
zu aktualisieren. Installiert man den ddclient, klinkt er sich dort eigenständig ein.

sudo aptitude install ddclient

zusätzlich zu dieser Konfiguration bedarf es noch der Verschaltung der Netzwerke. Wenn man nicht gerade ein öffentliches Netz im betrieb hat wird man NAT nutzen müssen. Dazu muss man einfach mittels iptables folgende regeln konfigurieren. Am besten sollte man das gleich in /etc/rc.local ablegen, damit das setup bei jedem reboot gesetzt wird.

sudo -s
echo "1" > /proc/sys/net/ipv4/ip_forward #alternative /etc/sysctl bearbeiten
 
iptables -A FORWARD -o <internes interface> -m state --state ESTABLISHED,RELATED -J ACCEPT #alles akzeptieren was vom Internet kommt und von lokalen Lan initialisiert wurde.
iptables -A FORWARD -o <externes interface> -J ACCEPT #alles was von Intern nach Extern will akzeptieren.
 
iptables -t nat -A POSTROUTING -o <externes interface> -j MASQUERADE #NAT aktivieren

Nach diesem Setup hat man erstmal wieder Internet von allen Clients, wenn man den default-dns-server und standart-gateway korrekt eingestellt hat.

Wenn man über längere zeit “ernsthaft” einen rechner direkt am I-Net hängen lässt, sollte man sich jedoch über iptables genauer Informieren. Das genannte Setup ist nur ein Grundsetup um last den Router-Rechner ziemlich “exposed” im Netz.

Munin und 3Ware

Samstag, 17. Oktober 2009

Hinter Munin versteckt sich ein sehr puristisches aber brauchbares Monitoring-Tool um ein ganzes Netzwerk zu überwachen. Munin besteht dabei aus zwei teilen. Der Node und einem Crawler, der Zyklisch (alle 5 Minuten) alle bekannten Nodes abfragt. Danach werde Graphen von den gesammelten Daten über die Zeiträume Tag, Woche, Monat und Jahr erzeugt. Damit lassen sich gut Trends und Ungereimtheiten ablesen. Dazu wird noch rudimentäres “Allerting” geboten. Über/Unter-schreitet ein “getrackter” Wert ein vorgegebenes Limit, wird eine Warnmail ausgesendet. Zudem wird der Wert Farblich zusätzlich markiert. So das man beim Kontrollieren der Status-Webseite sofort sieht, das was im argen ist.

Die Node bietet dabei von Start weg überhaupt keine Funktionalität. Alles was man angezeigt bekommen will, muss via Plugins geliefert werden. Die Communitie bietet hier jedoch ein extrem umfangreiches Repertoire an schon vorhanden Plugins. Darunter auch Plugins die SNMP Quellen abfragen.

Nun bieten 3Ware einen SNMP Zugang zu allen RAID-Daten. Nur ist dies leider sehr umständlich. Da sich Plugins sehr einfach schreiben lassen, hab ich einfach drei Plugins geschrieben, die mir die wichtigsten Daten extrahieren und in Munin zur Verfügung stellen. Ich benutzte dazu “tw_cli” welches von 3Ware mitgeliefert wird. Anschließend wird dessen Output ausgewertet und dargestellt.

die Sources gibt es hier:

  • RAID-Status: Liefert den Status aller im System bekannten RAID-Units
  • RAID-Unit-Status: Listet den Status aller physikalisch Einheiten einer RAID-Unit.
  • BBU – Status: Liefert den Status der installierten BBUs

Performance vs Verschlüsselung

Freitag, 2. Oktober 2009

Wenn man einen File-Server betreibt, so kann man unglaublich viel Zeit investieren, den Raid zu planen, die Verschlüsselung einzurichten und das Netzwerk zu tunen. All das nutzt aber nichts, wenn am Ende der benutzer glaubt, die Bytes einzeln über die Leitung schieben zu müssen.

Es kann bzw wird passieren, wenn man seinen File-Server verschlüsselt. Der toolste RAID bringt wenig, wenn er auf den CPU warten muss, weil der fröhlich am ent-/verschlüsseln ist. Hier liegt ein grundlegender Widerspruch zwischen zwei Anforderungen vor. Jeh stärker man die Verschlüsselung forciert, desto langsamer wird der Datenzugriff.

Die erreichten Werte skalieren dabei nicht jedoch nicht wie erwartet. Und überhaupt fällt es im ersten Moment schwer, die wirklich wichtigen Parameter auszumachen. Zuallererst müssen die Rahmenparameter abgesteckt werden:

  • Wichtig ist die LAN-Anbindung. 100MBit/s oder 1GBit/s. Beides Transferraten sind wesentlich langsamer als das was fast alle RAIDs (auch Software RAIDs) zustande bringen. Aus dem stand schaffte mein Testsystem 251,59MByte/s (write) und 293,41 (read). An dieser Stelle sei darauf hingewiesen, dass eine Umrechnung von Bits in Byte. (1GBit/s=1024MBit/s = 128MByte).
  • Der zweite Rahmenparameter sind die Clients, bzw. deren Festplatten. Die maximale Transferrate ergibt sich aus der Lese/Schreibgeschwindigkeit dieser Komponente. In großen Netzwerken sollte kann man das getrost ignorieren, da immer mehrere Clients den Server ans Limit fahren. Im Privatgebrauch mit weniger als fünf Clients sollte man aber schon mal schauen wie viel Power man wirklich braucht. Dazu nimmt man seine “schnellste” Kiste (in meinem Fall 60MByite/s Read/40MByte/s Write) und nimmt die mal 1.5. Das ist zwar keine Wissenschaft, aber über den Daumen reicht das.

Neben diesen “harten” Rahmenbedingungen gibt es noch eine Reihe weicher “Auswahlkriterieren”. Bei fast jedem Benchmarktool bekommt man verschiedene Werte der “Festplatte” ausgewiesen. Sequenzjelles(Block) Lesen/Schreiben, zufälliges Lesen/schreiben und so weiter. Eine Fülle von Informationen von denen man nicht weiß nach was man Bewerten soll. Zur Vereinfachung lässt sich sagen, dass bei einem Fileserver in 90% der Fälle das sequenzielle Lesen/Schreiben wichtiger ist.

Zum Testszenario: Alle Verschlüsselungs/Cipher-Algorithmen-Kombination musste ein 750GB Device verschlüsseln, wobei auch verschiedene Schlüssellängen durchprobiert wurden. Als überlagertes Dateisystem kam XFS zum Einsatz. Der CPU (ein 2.5GHz Intel Core 2 Duo) übernahm dabei nur die Krypto-Aufgaben. Der RAID-Controler war für die IO Zuständig. Die 4GB RAM kann man ausklammern, da der Benchmark (in diesem Fall bonnie++) bewusst den RAM umgeht. Bei einem Testfile von 8GByte nutz einem weder der 4GByte-RAM noch die 256 MByte Controller-Cache irgendwas. Was ja auch Sinn dieser Test ist. Das ganze lief unter einem 64 Bit Ubuntu 9.04

Zum Ergebnisdiagramm:  Der RAID lieferte nativ (unverschlüsselt) 252 MByte/s (Block Write) und 293,41 MByte/s (Block Read). Dies ist nicht auf dem Diagramm zu sehen, weil dann die Skalierung unvorteilhaft geworden wäre. Die ersten 3 Testwerte stellen daher die “praktischen” Referenzwerte dar. Als maximal physikalische steht dabei die 1GBits Ethernet Verbindung. In der Praxis bringt die es bei mir ungefähr auf 800 Mbit/s (100MByte/s), folglich sind alle IO-Bandbreiten, mit mehr Leistung sinnlos. Als zweiten Referenzwert hab ich die Festplattenleistung aller meiner Clients gemessen und deren Ergebnis gemittelt. Mehr Leistung als diese ist zwar nett, da dadurch mehrere Rechner gleichzeitig auf dem server arbeiten können aber sonderlich viel mehr Leistung wird nicht gebraucht, da dass Netzwerk aus nicht mal 5 Rechnern besteht. Der dritte Referenzwert ist der Wert der (mich) am meisten überrascht. Es ist die Rohleistung der Standart SMB-Client (libsmbclient 2:3.3.2-1ubuntu3.2) auf die Leitung bringt. Überraschend deswegen, weil er schneller schreiben als lesen kann. Ob dies an meiner Serverkonfig liegt, konnte ich noch nicht verifizieren.

Alle Test fanden Donnerstag von 23 bis Freitag 2 Uhr statt.


Verschlüsselung Performance Statistic

Verschlüsselung Performance Statistik


CPU Auslastung

CPU Auslastung


Speicher Auslastung

CPU Auslastung

Die Auswertung: Da der Referenzbalken der Unverschlüsselten Performance fehlt, sieht das Ergebnis Feld ganz brauchbar aus. Das täuscht. Als erstes fällt auf, dass sich alle Algoritmen-Mischungen ungefähr gleich geschlagen haben. In absoluten Zahlen ausgedrückt sieht das wie folgt aus:

  • Write Char: Der schlechteste Wert ist 66.25 MByte/s und erreicht somit noch immer 91% der nativen Leistung. Ach die Streuung ist vernachlässigbar, Zwischen dem schnellsten und langsamsten Algorithmus liegen gerade mal 3 MByte/s.
  • Write Block: Der eigentlich interessante Wert für einen Fileserver weißt die erste Überraschung auf. Hier bringt es der schnellte Algorithmus gerade mal auf 61% (152 KByte) der ursprünglichen Leistung. Die Streuung ist hier auch am größten. Zwischen den beiden Extremen liegen 60 KByte/s. Das ist gemessen am absoluten Leistungsverlust (99MByte/s) ein enormer Wert.
  • Rewrite: Hier zeigt sich wieder ein ähnliches Bild wie beim “Write Char”-Test. Das Ergebnisfeld ist dicht beieinander. Mit einem Maximalunterschied von 6KByte/s spielt es fast keine Rolle.
  • Read Char: Auch hier das gleiche Bild. Alle Algorithmen liegen dicht beieinander. Auch der Verlust hält sich in Grenzen. (7KByte/s)
  • Read Block: Die größte Überraschung am Schluss: Mit einem Leistungsverlust von fast 80% schlagen sich alle Algorithmen in dieser Disziplin schlecht. Zudem gibt es hier wieder nennenswerte Unterschiede zwischen den einzelnen Algorithmen.(20KByte/s bei einem Absoluten Verlusst von 230 Kbyte) Da dies eine Königsdisziplin der FileServer ist (Dateien ausliefern) gebietet es sich, hier genauer hin zuschauen.

Neben diesen Einzelwerten fällt auf, dass die Leistung der Algorithmen nicht skalliert wie man es erwartet. Das liegt zum einen daran, dass der absolute Verlusst an der Dimensionierung der CPU im Vergleich zum nativen Leistung ist. Auf Deutsch: ein Monster RAID + LowCost CPU ist blöd. Der RAID wird sich die ganze zeit langweilen, weil der CPU nur am Rödeln ist. Hier wird auch klar, dass nachrüsten von Speicher an so einer Leistungsgrenze wenig bringt. Der Flaschenhals ist die CPU. Dass sieht anders aus, wenn man einen Software- oder Fake-RAID benutzt. Aber auch die Algorithmen selber skallieren nicht wie erwartet. Wenn ein Algorithmus gut im Random-Access ist, sagt das noch lange nichts über seine Leistung im Block-Lesen oder gar Schreiben aus.  Dass Schreiboperationen performanter als Leseoperationen durchgeführt werden, entzieht sich komplett meiner Logik.

Neben diesen reinen Duschsatzzahlen war  es interessant Festzustellen, dass alle Algorithmen aus CPU-Sicht gleich aufwändig sind. Die Auslastung lag fast immer am Limit. Auch wenn das CPU-Diagramm etwas anderes vermuten lässt. Im ersten Moment sieht es so aus, dass der CPU eine hohe IDLE-Rate (Pinker+Türkies). Das ist aber nur die halbe Wahrheit. Besonders bei dem langen Block nach den Test (von 3 Bis 4 Uhr – hier wurden 180 GByte Backupdaten wieder auf den RAID aufgespielt) fällt auf, dass es faktisch keinen nur noch drei Statie gibt, in dem sich der CPU befindet: IDLE, IOWAIT oder SYSTEM.  Eigentlich müssten sich IOWAIT und SYSTEM zu 100% ergänzen. Der Grund für das IDLE ist einfach. Ein CPU hat sich immer gelangweilt. Das hat den Vorteil, dass das System trotz Vollast noch gute Antwortzeiten aufweist und einsatzfähig ist, kostet aber enorm an Durchsatz.

In hab mich für den aes-xts-plain mit einer Schlüssellänge von 256 entschieden. Da dieser die beste Block-Read/Write Performance hat. AES-ECB ist zwar nochmal eine ganze Ecke schneller (besonders beim lesenden Zugriff) jedoch ist dieser Algorithmus für eine reihe von Angriffen anfällig, die bis zur Extraktion der Krypto-Keys gehen.

[UPDATE] Nach der Veröffentlichung in den ubuntuusers-Foren hat mich Red Radish darauf hingewisen, dass viele der hier genannten Verschlüsselungs-Algoritmen zwar möglich aber wenig sinnvoll sind. Leider ging das aus den Seiten die ich biss her gelesen hab nicht hervor. Die Anzahl der “sinnvollen” Ciphers sind:

  • aes-ecb
  • aes-cbc-essiv:sha256
  • aes-lrw-benbi
  • aes-xts-plain
  • twofish-cbc-essiv:sha256
  • twofish-lrw-benbi
  • twofish-xts-plain

Danach sieht das Diagramm etwas übersichtlicher aus.


Verschlüsselung Performance Statistic

Verschlüsselung Performance Statistik

Links:

Verschlüsselung von RAIDs

Mittwoch, 23. September 2009

Will man einen RAID verschlüsseln, steht man vor verschiedenen Problemen. Zuallererst muss man sich klar werden, dass eine Verschlüsselung die Datensicherheit (Redundanz) gefährden kann. Tausend Backups nützen nichts wenn der Schlüssel bzw. das Schlüsselfile verloren gegangen ist. Das klingt banal, schießt einen aber ins Knie, wenn der RAID bei einem Systemausfall die wichtigen Daten am Leben hält, das Schlüsselfile aber mit ins Nirwana gegangen ist.

Umgekehrt torpediert dein RAID meist mit der schieren Masse an  Daten die Datensicherheit im Sinne des Zugriffsschutzes. Je mehr Daten man mit dem gleichen Schlüssel verschlüsselt, desto “leichter” lässt sich der Schlüssel aus dieser Menge extrahieren. Ab 2 GByte sollte man sich intensiv damit beschäftigen, welchen Verschlüsselungsalgorithmus (Cipher) man verwenden kann und mit welcher Schlüssellänge man arbeiten sollte.

Neben solchen theoretischen Vorüberlegungen muss man sich aber auch klar werden wie man Verschlüsseln will. Welche Features will man nutzen, worauf kann man verzichten. Ich für meinen Teil hatte klare Vorstellungen von meinem Setup:

  • FullDiskEncryption (FDE): Das RAID Array soll im ganzen verschlüsselt werden.
  • Dynamische RAID-Vergrößerung: Ab gewissen Speichergrößen ist eine Verdopplung des Speichers nicht mehr praktikabel oder schlicht bezahlbar.

Beide Punkte zusammen haben jedoch ihren Knackpunkt. Nicht alle Verschlüsselungstechnologien sind bei FDE (oder überhaupt) in der Lage einmal verschlüsselte Container/Volumes in der Größe zu verändern. TrueCrypt kann dies nur bei Containern und dann mit einem Performance-Overhead, der inakzeptabel ist. Bei den OpenSource-Technologien bleibt dann nur noch dm-crypt über. Dieses hat jedoch die “Schwäche”, dass der Verschlüsselungheader (welcher Cipher, Start, Ende, etc) selber unverschlüsselt auf der Platte liegt. Sicherheitstechnisch ist das kein Problem. Auch wenn der Angreifer den Cipher kennt, beißt er sich bei den richtigen Algorithmen und Schlüssellängen die Zähne aus. Nur kann ein dm-crypt Benutzer nicht glaubhaft abstreiten, dass er eben dm-crypt nicht benutzt.

Mir war die juristische Debatte erstmal egal, ich wollte ein verschlüsseltes dynamisches RAID-Device. Das hat mich ein ganzes Wochenende gekostet (500GB auf 750GB zu migrieren dauert immer ungefähr 4 Stunden). Es hat sich mir ein zentrales Problem in den weg gestellt. Es gibt für die Konsole kein Tool, dass eine Partition vergrößern kann, dessen Dateisystem es nicht erkennt. Man kann mittels fdisk die Partitionstabelle löschen und neu schreiben. So sadomasochistisch bin ich aber nicht veranlagt. Man riskiert immer vollen Datenverlust!

Man kann den Umweg über Logical Volume Manager (LVM) gehen. Dazu wird bei einem vergrößerten Device nicht die Partition vergrößert, sondern im neuen freien Bereich einfach eine weitere Partition erstellt. Diese wird dann dem Logischen Device hinzugefügt. Arbeitet man nur mit einem Fake- oder Software-RAID, mag das akzeptabel sein. Kommt es bei diesen zu einem Stromausfall darf man eh beten. Hardware-RAIDs nutzen jedoch BBUs um Datenverlust im Fehlerfall zu unterbinden. Was mit der LVM Zwischenschicht wieder ausgehebelt währe.

Möglichkeit drei ist einfach: man nutzt keine Partitionierung. Dazu muss man einfach wie folgt sein Device “beschreiben”

sudo parted /dev/
mklabel msdos
quit

Nach dieser Aktion hat man eine MSDOS – Partitionstabelle, aber nicht erschrecken, die verschwindet gleich wieder ;)

Jetzt kann man die Festplatte direkt verschlüsseln, was z.B. bei einer GPT – Partitionstabelle nicht geht.

sudo cryptsetup luksFormat --cipher aes-xts-essiv:sha256 -s  -q /dev/ #Verschlüsselung anlegen
sudo cryptsetup luksOpen /dev/  #Verschlüsseltes Device öffnen
mkfs.ext3 /dev/mapper/ #verschlüsseltes Device formatieren
mount /dev/mapper/ /mnt/

Beim Wiedereinhängen einfach luksFormat und mkfs weglassen, sonst blöd ;)

Interessant wird jetzt die Vergrößerung. Dazu im unterlagerten RAID erstmal das Device vergrößern. Um die neue Festplattengröße dem System bekannt zu machen muss man entweder mittels des RAID-Treibers ein rescann auslösen oder man entlädt einfach den ganzen Treiben und hängt ihn wieder ein.

sudo lsmod #alle Treiber anzeigen lassen und den RAID-Treiber raus suchen.
sudo modprobe -r <treibername> #RAID-Treiber entladen
sudo modprobe <treibername> #RAID-Treiber laden

Letztes geht nicht ohne das aushängen der gemountet Partition. Besser gesagt, es geht schon, bloß muss man dann mit Datenverlust rechnen. Ein Rescan sollte zu keinem Datenverlust führen, das ist jedoch treiberabhängig, in jedem Fall das Manual oder den Maintainer konsultieren.

Ist die neue Festplattengröße im System bekannt, muss man sie nutzbar machen. Dazu gibt es zwei Möglichkeiten:

  • Online – ohne Downtime des Dateisystems: Dies benötigt ein Dateisystem, was das Vergrößern/Verkleinern “on-the-Fly” unterstützt. Das können z.b. EXT3 oder XFS.
    sudo fdisk -lu /dev/ #Sektoren raus schreiben
    sudo cryptsetup status  #Offset raus schreiben
    sudo cryptsetup resize -o  -b ;
    sudo resize2fs /dev/mapper/ #resize des FileSystems am Beispiel EXT3
  • Offline – mit Downtime des Dateisystems: Die kann mit allen Dateisystemen durchgeführt werden, die vergrößert/verkleinert werden können. Es ist auch ein Stück komfortabler.
    sudo umount /dev/mapper/<wunschname>; #aushängen des verschlüsselten Devices (wenn nicht schon vor dem Scann passiert)
    sudo cryptsetup luksClose  #schließen des verschlüsselten Devices (wenn nicht schon vor dem Scann passiert)
    sudo cryptsetup luksOpen  #damit ist auch schon die Vergrößerung des verschlüsselten Devise erledigt...
    sudo resize2fs /dev/mapper/ #resize des FileSystems am Beispiel EXT3/EXT2

    Beim öffnen des Device nutzt selbiges scheinbar automatisch allen verfügbaren Platz, wenn man nichts anderes (mittels resize) einstellt.

So kann kann in jedem Fall ohne viel Stress seine RAID-Device stückchenweise nach seinen Bedürfnissen erweitern. Dennoch sollte man von allen wichtigen Daten immer ein Backup haben! Zudem sollte man dieses Vorgehen ein, zwei mal geübt haben, bevor man es mit wichtigen Daten durchführt;)

3Ware installation

Samstag, 19. September 2009

Das erste was nach der Installation der Hardware auffällt ist, dass der Boot-Vorgang extrem viel länger dauert. Beim ersten Start hat es locker 30 Sek gebraucht, bis das BIOS des RAID-Controllers durch war und mein Server endlich ins Linux gebootet hat. In den folgenden Boots wird das nicht viel besser.

Die Installation des 9650 ist unter Ubuntu 9.04 denkbar einfach. Auch alle anderen Distributionen werden (wenn auch nicht offiziell) ohne Probleme unterstützt. Einzig die Kernelversion 2.6.14  oder die entsprechenden Treibermodule werden vorausgesetzt. 3Ware bietet drei Möglichkeiten den RAID-Controller zu administrieren. BIOS, CLI und die 3DM -genannte webbasierte RemoteManagement – Konsole. Die Installation erfolgt problemlos, einzig eine „echte“ JavaRuntime und das Programm „bc“ werden benötigt. Beide sind aber im offiziellen Repository enthalten und man gefährdet seinen Server nicht mit Fremdquellen. Ein „kleines“ “aptitude install” vorneweg und die Installation kann beginnen.

Hat man eine grafische Oberfläche kann man das Setup einfach so starten, steht einem nur ein Kommandozeilen-Terminal zur Verfügung muss man noch den Parameter „-console“ anhängen. Anschließend führt ein Assistent durch die Installation und nach „wenigen“ Minuten steht einem der RAID-Controller in vollen Funktionsumfang zur Verfügung.

sudo aptitute install bc
tar xfvz 3DM2_CLI-Linux-x86_64-9.5.2.tgz
sudo ./setupLinux_x64.bin -consol

Jetzt wird man durch den Assistenten geführt. Das dauert wie gesagt ein paar Minuten. Anschließend ist alles nach Wunsch installiert und konfiguriert. Will man nachträglich etwas ändern so findet man das Config-File unter /etc/3dm2/

Man muss nur noch dafür sorgen, dass die Remote – Konsole auch automatisch gestartet wird. Leider ist der mitgelieferte Startscript, der auch brav unter /etc/init.d abgelegt wird, nicht ganz Standardkonform. Es fehlen die Angaben zu Required-Start und Required-Stop. Ergo schnell die Datei mit einem Editor der Wahl geöffnet und den Header angepasst.

#!/bin/sh
#
# 3dm2:         Starts the 3ware daemon
#
# Author:       Michael Benz
 
#
# Default-Start: 3 4 5
# Default-Stop: S 0 1 6
# Required-Start:  $network $remote_fs $syslog
# Required-Stop:   $network $remote_fs $syslog
# Provides: tdm2
# Short-Description: 3ware Daemon
# Description: Start the 3dm2 application which logs the current state
#              of the 3ware DiskSwitch controller card, and then polls
#              for state changes.
#
# config: /etc/3dm2/3dm2.conf

Zeile 9 und 10 sind von mir eingefügt. Anschließend folgenden Befehl ausführen.

sudo update-rc.d tdm2 defaults

Nun startet die Remote-Konsole automatisch beim Systemstart mit.
Für den ersten Test startet man entweder neu oder ruft den Script manuell auf.

/etc/init.d/tdm2 start

Wenn man die Konsole aufrufen will muss man beachten, dass nur HTTPS anfragen beantwortet werden. Nach dem Login (Standartpassword: 3ware) sollte man sofort die Passwörter ändern und ein BIOS-Update einspielen. letzteres bedarf leider eines Neustarts.

Anschließend kann man seine RAID-Arrays konfigurieren.

Apache und Mono die zweite

Dienstag, 18. August 2009

Unter ubuntu hat man ein “kleines” Problem wenn man nur Mono 2.0 installiert und eine ASP WebtSeite via Apache hosten will. Es fehlt dann an einem symbolischen Link.

Es müssen sowohl /usr/bin/gmcs und /usr/bin/gmcs2 vorhanden sein. Ist nur letzteres vorhanden muss das erste über einen symbolischen Link “hergestellt” werden.

Um es bei der administration/einrichten von Webspaces etwas einfacher zu haben bieten sich ‘mono-server2-admin’ und ‘mono-server2-update’ an. Damit lässt sich eine ASP Seite recht einfach einrichten. Die erste Testseite grinnst einen in wenigen “Sekunden” an…

Server Suspend – a long tail

Mittwoch, 8. Juli 2009

Einleitung

Was braucht man sinnigerweise für einen Server den man Schlafen legen will?

  1. Eine CPU/Board – Kombo die das unterstützt…
  2. Eine Netzwerkkarte die WakeUp-on-LAN unterstützt
  3. Alle Periferiere muss Suspend unterstützen (RAID Controler, etc…)

Primär spielt es keine Rolle welchen Suspend man anstrebt. Ob “Suspend to Ram” (Suspend) oder “Suspend to Disk”(Hibernate) unterscheidet sich im Administrativen, wie man den Server dazu bekommt, nicht. Es muss einfach ein anderer Wert (Zahl) in /proc/acpi/sleep geschrieben werden…

In meinen Versuchen hat sich Suspend to RAM aber als sinnvoller erwiesen. Das Aufwachen nach einem Suspend ging (erwartungsgemäß) schneller. Aus einem Suspend kam der Server innerhalb von unter 2 Sek wieder zum laufen (laut Kernel – Syslog, zu messen war das kaum sinnvoll…) beim Hibernate benötigte es einen kompletten Boot… das dauerte bei mir ganze 5-7 Sekunden.

Die Einsparung an Energie gegenüber einem Suspend hielt sich in grenzen:

  • Server (Boot): 75 Watt
  • Server (Working): 20 Watt
  • Server (Idle): 15 Watt
  • Server (Suspend): 3 Watt
  • Server (Hibernate): <1 Watt

Der geringe “Gewinn” war es mir nicht wert meine Sicherheit und die Response-Zeit zu opfern… Man sollte immer bedenken, dass der Memory auf die Festplatte geschrieben wird…. und selbst wenn man den verschlüsselt, ein Angreifer den Server bewegen kann (da er keinen Strom braucht) und in seiner umgebung booten kann… Hat man hingegen ein verschlüsselte Boot-Partition (TrueCrypt etc) nutzt einem der Hibernate nicht viel, da der Server nicht “unbeobachtet” wieder hoch kommt…

Vorbereitungen

Als erstes muss man die Netzwerkkarte testen bzw fit für WakeUp on Lan (WOL) machen. Wie das geht wird sehr gut hier beschrieben. Zu den einzelnen WOL-Modi:

  • WOL-Packet: Das eigentlich aufwecken über ein WOL/Magic-Packet ist weniger Sinnvoll und erlaubt nur einen Betrieb eines File/Domain-Servers. Beim Booten müssen alle Clientes automatisiert das WOL-Packet lostrehten und der Server darf über die dauer der Session nicht runter Fahren.
  • u/m/b/a: Das Aufwachen des Servers bei Broad/Multi/Uni-Cast ist die (imho) interessanteste Variante. Der Server wird in jedem Fall geweckt wenn er gebraucht wird. Fast alle heute verwendeten Protokolle arbeiten über IP. Dabei impliziert ist das beziehen einer Adresse (DHCP) und das Auflösen einer Adresse (ARP). Beide Protokolle beginnen den initialen Request über Broadcast. So kann man fast alles betreiben: DHCP, DNS, Webserver. Warum im Standart nochmals ein WakeUp on ARP(a) ausgewiesen wird, erschließt sich mir nicht…
  • WakeUp on physikal activity: diesen Modus hab ich bei meinen getesteten Karten nicht zum laufen bekommen. Oder nicht so wie ich das wollte. Entweder wurde der Rechner sofort nach seinem suspend wieder geweckt oder er reagierte überhaupt nicht… wer denn Sinn dahinter versteht, möge es posten…

Shutdown

Ich habe lange gesucht (ok, nicht wirklich lange, aber schon länger… ;) ) bis ich eine geeignete Methode gefunden hatte, bzw zu meiner ersten Idee zurück kam. Ich machs kurz: Sleepd und andere Methoden Interupts abzufragen (oder besser deren nichterscheinen) funktionierten nicht oder nur eingeschränkt… Die interessanten Interrupts ließen sich nicht abhören und so was wie Maus und Tastatur nutzt bei einem Server ohne selbige nichts.

Deswegen verwende ich einen Script der alle 5 Minuten via Cron ausgeführt wird. Dieser ist in seiner “Urform” hier zu finden. Der Script als solches funktioniert prima, musste nur um zwei Funktionalitäten an meine Bedürfnisse angepasst werden.

  • Wenn man den Server als zentralen FileServer für die Home-Dirs nutzt, sollte dieser tunlichst nicht runterfahren, solange ein User angemeldet ist. Das CIFS/Samba Protokoll und deren Implementierungen können das zwar ab, die Programme (KDE, OpenOffice, …) jedoch nicht. Stalled Lockfiles und andere “interessante” Probleme sind die Folge… Aus diesem Grund habe ich den Script um eine Überprüfung erweitert, ob SMB-User angemeldet sind. Dies erfolgt über “smbstatus”.
  • Des weiteren kam es immer wieder dazu, dass der Server nicht “richtig” in den Suspend ging, oder nicht ordentlich aufwachte.Dies häufte sich besonders bei häufigen Suspends (ich hatte Testhalber die Überprüfung auf minütlich gesetzt). Nach einer weile /var/syslog-Studium fand ich den Übeltäter. Cron kann zuschlagen, während der Kernel noch am “aufwachen” ist und im somit abermals einen Schlafbefehl verpassen. Das bringt den Kernel ein wenig aus dem Trab. Um das zu unterbinden hab ich zwei weitere Prüfungen eingebaut. Zum einen wird ein Lockfile angelegt, das erst nach dem beenden von des “echo”-Befehls gelöscht wird, eine Semaphore. Zum zweiten muss zwischen “Aufwachen” und erneutem Suspend mindestens 30 Minuten liegen. Dies wird mit einem Datei geprüft die mittels “touch” aktualisiert wird, bevor das Lockfile gelöscht wird. Danach einfach das Datediff abfragen…

Die von mir verwendete Version ist hier zu finden.

Fazit

Der Server steht mir nunmehr 24/7 zur Verfügung, spart sich jedoch Strom da nicht immer an… Zudem zühlt die Uptime auch hoch, obwohl der Server am “Schlafen” ist, nennt man das cheaten? *G*

Einziges Manko: Aus Sicht der Festplatten handelt es sich um einen “Shutdown”. Zu mindestens wird der Motor komplett stromlos geschaltet. Das Wiederanfahren sowie justieren der Köpfe reduziert die Lebensdauer der Platten entsprechend. Bei guten (verlässlichen) RAIDs sollte das aber kein Problem darstellen.

Links

Hello Mono (ASP)

Sonntag, 28. Juni 2009

mit folgenen befehlen installiert man das mono plugin für apache (unter ubuntu)

sudo apt-get install libapache2-mod-mono
sudo apt-get install mono-apache-server2

und mittels

sudo a2enmod mod_mono(_ autoload)

aktiviert man den ganzen kram…

aber vorsicht: vorher noch die Datei /etc/apache2/mods-available/mod_mono.conf checken, welche mono version geladen wird, standartmäßig ist das die 1.0…