Vim: Datei trotz fehlender Schreibrechte speichern

Ich bekenne mich als vim-Fan. Abgesehen von Textmate habe ich noch keinen Editor gefunden, mit dem ich ähnlich produktiv arbeiten könnte. Unter vim wurde bisweilen meine Produktivität gelegentlich ein wenig gebremst: Schnell eine Änderung in einer Server-Konfigurationsdatei vorgenommen, :win die Tastatur gehackt und vim quittiert es mit E212: Can't open file for writing. Mal wieder die vergessen vim mit sudo zu starten. Zwar lässt sich die Datei problemlos unter einem temporären Dateinamen speichern und dann mit sudo mv verschieben, doch das kostet unnötig Zeit.

Viel eleganter und schneller lässt sich die Datei trotz mangelnder Zugriffsrechte direkt aus vim heraus abspeichern:
:w !sudo tee %

Ein kleine Befehlsfolge, die mir künftig viel Zeit sparen wird. 🙂

Linux: Mehrere IP-Adressen an ein Netzwerkinterface binden

Manchmal ist es erforderlich mehrere IP-Adressen an ein Netzwerkinterface zu binden. Nur so lassen sich beispielsweise auf einem angemieteten Rootserver mit nur einer Netzwerkkarte Websites unter verschiedenen IP-Adressen hosten – Voraussetzung dabei ist selbstverständlich, dass der Hoster zusätzliche IP-Adressen zur Verfügung stellt.

Linux bietet mit dem Konzept der virtuellen Netzwerkinterfaces eine elegante Lösung, um an einen Netzwerkadapter viele IP-Adressen zu binden. Jede physikalisch Netzwerkkarte trägt einen eindeutigen Namen, etwa eth0 für die erste Karte oder eth1 für die zweite Netzwerkkarte. Für jede physikalische Netzwerkarte lassen sich mehrere virtuelle Interfaces mit einer eigenen IP-Adresse konfigurieren. Dazu ist das physikalische Interface (eth0, eth1, eth2 usw.) gefolgt von einem Doppelpunkt und der Nummer des zu erstellenden virtuellen Interface anzugeben. So bezeichnet eth0:1 das erste virtuelle Interface an der physikalischen Netzwerkkarte eth0 und eth1:5 das fünfte virtuelle Interface an der zweiten Netzwerkkarte eth1.

Die virtuellen Netzwerkschnittstellen lassen sich mit den gleichen Werkzeugen konfigurieren, wie ihre physikalischen Pendants.

Um beispielsweise manuell die IP-Adresse 192.168.35.100 an die Netzwerkkarte eth0 zu binden, genügt es folgenden Befehl mit root-Rechten auszuführen.

ifconfig eth0:1 192.168.35.200 netmask 255.255.255.0 broadcast 192.168.35.255 up

Möchte man die manuell vorgenommene Konfiguration dauerhaft hinterlegen, wäre unter Debian die /etc/network/interfaces wie folgt zu editieren:

auto eth0:1
iface eth0:1 inet static
address 192.168.35.200
netmask 255.255.255.0
broadcast 192.163.35.255

SSH absichern

Vor einiger Zeit schon  habe ich mir vorgenommen etwas darüber zu schreiben, wie ein Webserver abgesichert werden kann. Darum nehme ich die heute kürzlich gestellte Frage zum Anlass endlich damit zu beginnen und fange bei SSH an. Im folgenden beziehe ich mich auf die Implementierung OpenSSH. Die Konfiguration anderer Implementierung wie etwas SSH.com verläuft ähnlich, weicht jedoch im Detail ab.

Bevor wir beginnen, solltest du sicherstellen, dass du eine aktuelle SSH Version benutzt. Unter Debian genügt dazu der Einzeiler apt-get update; apt-get dist-upgrade. Unter anderen Distributionen stehen ähnliche Werkzeuge zum Update zur Verfügung wie etwas yast unter Suse.

Nun ist es an der Zeit die Konfigurationsdatei /etc/ssh/sshd_config zu bearbeiten. Ich werde im folgenden die sicherheitsrelevanten Optionen durchgehen und kurz kommentieren.

ListenAddress 217.79.182.18

Wenn ein Server mit mehr als einem Netzwerkinterface ausgestattet ist, kann es sinnvoll sein den Zugriff bestimmte Interfaces zu beschränken. Beim klassischen Webserver dürfte das allerdings nicht der Fall sein.

Port 2222

Standardmäßig lauscht der SSH-Dämon auf Port 22. Viele Bruteforceattacken gegen ganze Netzwerksegmente können durch Nutzung eines anderen Ports erfolgreich abgewehrt werden. Solche Angriffe gehen meist von Botnetzen oder bereits gekaperten Servern aus, die mit großer Bandbreite tausende Logins gegen Port 22 feuern. Dabei werden Standardbenutzernamen (admin, root, httpd, mail usw.) mit leerem Passwort oder Passwörter aus Wörterbüchern und Passwortlisten durchprobiert. Solche Angriffe können zwar einen sicher konfigurierten Server nicht gefährden, blähen aber die Logdateien auf, führen zu verminderten Reaktionszeiten und schlimmstenfalls können sich legitimierte Benutzer ob der vielen Anfragen nicht über SSH einloggen. Selbstverständlich bietet die Nutzung eines anderen Ports keinen Schutz gegen gezielte Brutforceangriffe, bei denen dem eigentlichen Angriff ein Portscan vorausgeht. Abhilfe können hier zum Beispiel sshblack schaffen oder eine Kombination von Snort, Netfilter und iptables. Da DoS-Attacken kein SSH-spezifisches Problem sind, werde ich an dieser Stelle nicht weiter darauf eingehen.

Protocol 2

Die Version 1 des SSH-Protokoll enthält Designschwächen, die einen unbefugten Login ermöglichen, und sollte darum nicht benutzt werden.

PermitRootLogin no

Es ist eine gute Idee root den Zugang über SSH zu verwehren. Denn wenn jemand gelänge sich über SSH unbefugt Zugang zum Server zu verschaffen, könnte er als unprivilegierter Nutzer nur begrenz Schaden anrichten. Da es ohnehin von Leichtsinn zeugt stets als root zu arbeiten, spricht auch wenig dafür den direkten Login als root zu erlauben. Wichtig ist auf einen frisch installierten System einen neuen Benutzer anzulegen, bevor wir über PermitRootLogin no root vom SSH-Login ausschließen.

AllowUsers tom thomasfalkner@thomas-falkner.de
AllowGroups admin

Wenn nur bestimmte Nutzer sich via SSH auf dem Server einloggen dürfen, können diese über AllowUsers bestimmt werden. Wenn Benutzer nur von einem bestimmten Host aus Zugang zum Rechner erhalten sollen, kann dass über user@host geregelt werden. Das kann sinnvoll sein, wenn ein Webdesigner sich nur aus dem Firmennetzwerk, nicht aber von zu Hause auf dem Server anmelden darf. Durch die Option AllowGroups kann der Login auf bestimmte Benutzergruppen beschränkt werden.
Sollen mehr Benutzer erlaubt als ausgeschlossen werden, ersparen die Gegenstücke zu AllowUsers und AllowGroups, DenyUsers und DenyGroups, eine Menge Tipparbeit.

Doch es ist nicht nur wichtig festzulegen, wer sich über SSH anmelden darf, sondern auch welche Authentifizierungsverfahren dazu genutzt werden sollen. Hier greift die Regle: Alles deaktivieren, was nicht benötigt wird.

Wer mit dem höchsten Sicherheitsstandard arbeiten möchten, sollte ausschließlich die PubKeyAuthentication nutzen und alle anderen Authentifizierungsverfahren ausschalten.

RhostsRSAAuthentication no
HostbasedAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no
RSAAuthentication no

Obwohl die meisten Optionen wie etwa RhostsRSAAuthentication per Default abgeschaltet sind, halte ich es für sinnvoll sie explizit auf no zu setzen, um eine klare Konfiguration vor Augen zu haben. Ferner wäre es töricht davon auszugehen, dass die Defaulteinstellungen sich bei neueren Versionen nicht ändern würden. Updates sollten übrigens ohnehin nie ungeprüft eingespielt werden.

Bevor wir die Passwort basierte Anmeldung mittels PasswordAuthentication no und UsePAM no vollständig deaktivieren, muss zuerst die Anmeldung über PubKey konfiguriert und getestet werden – sonst laufen wir Gefahr uns selbst auszusperren.

Dazu ergänzen wir /etc/ssh/sshd_config wie folgt:

PubkeyAuthentication yes
Damit wird die Authentifizierungs per RSA- oder DSA-Schlüssel aktiviert.

AuthorizedKeysFile %h/.ssh/authorized_keys

Gibt an, wo die öffentlichen Schlüssel auf dem Server gespeichert werden.
Per Default im Homeverzeichnis des jeweiligen Benutzers unter .ssh/authorized_keys.

Nun sollte der der SSH-Dämon neu gestartet werden: sudo /etc/init.d/sshd restart

Damit ist der Server vorbereitet für den passwortfreien Login über Schlüssel. Was fehlt ist der Schlüssel, oder genauer gesagt das Schlüsselpaar. Da der private Teil des Schlüssels auf dem Client verbleibt und nur der öffentliche auf den Server kopiert wird, empfiehlt es sich das Schlüsselpaar auf dem Client zu erzeugen. Unter UNIX-Derivaten starten wir dazu unter dem Useraccount, der sich später auf dem Server einloggen können soll, ssh-keygen.

ssh-keygen -t dsa

Wenn die Voreinstellung bestätigt wird, legt ssh-keygen den private Schlüssel id_dsa als auch den öffentlich id_dsa_pub unter ~/.ssh ab. Die Frage nach der Passphrase kann mit 2x Return übergangen werden, wenn man den Schlüssel nicht mit einem Passwort schützen möchte. Eine generelle Empfehlung ob es sinnvoll ist den Schlüssel mit einem Passwort zu schützen oder nicht, ist schwer möglich. Wird kann Passwort vergeben, kann jeder sich auf dem Server anmelden, der in Besitz des Schlüssels ist. Soll heißen: Wird der Rechner, auf dem der private Schlüssel hinterlegt ist geknackt oder gerät in falsche Hände, steht dem Angreifer auch der Zugang zum Server offen.
Sind die Schlüssel mit einem Passwort zusätzlich geschützt, müsste der Angreifer erst das Passwort per Bruteforce knacken – was bei ausreichend starken Passwort nicht in angemessener Zeit möglich ist.
Das höhere Maß an Sicherheit erkauft man sich jedoch mit der lästigen Eingabe des Passworts beim Login über SSH.

Ist der Schlüssel je nach Gusto mit oder ohne Passpharse erzeugt, muss er auf den Server übertragen werden.

Zuerst prüfen wir, ob es in unserem Homeverzeichnis auf dem Server einen Order .ssh bereits gibt. Wenn nicht, legen wir ihn an. Dazu kann folgender Einzeiler vom Client aus abgesetzt werden:

ssh domain.tld -p2222 "test -d .ssh || mkdir .ssh && chmod 700 .ssh"

Wie oben erwähnt, gehe ich davon aus, dass der User auf dem Client den gleichen Namen trägt wie auf dem Server.
Aus Sicherheitsgründen ist es unerlässlich, dass die Zugriffsrechte des .ssh-Verzeichnisses auf 700 und die für authorized_keys auf 600. Ferner müssen sowohl Datei als auch Verzeichnis dem anzumeldenden User gehören.
Letztere Bedingung erfüllen wir, indem wir Verzeichnis und Datei selbst anlegen, die Zugriffsrechte indes sollten wir explizit setzen.
Auch das lässt sich zu einem Befehl zusammenfassen:
cat ~/.ssh/id_dsa_pub | ssh domain.tld -p2222 "cat >> .ssh/authorized_keys && chmod 600 .ssh/authorized_keys"

Der passwortlose Login sollte damit funktionieren.

Zu den Möglichkeiten von SSH lässt sich noch eine Menge schreiben. Zu gegebener Zeit an dieser Stelle mehr.

bye bye mod_php

Ich habe meine PHP-Apache-Installationen von mod_php auf php_cgi umgestellt. Anlass zu diesem Schritt gab mir, dass ich keine befriedigende Lösung gefunden habe, um beim Schreibzugriff auf Dateien mit PHP Berechtigungskonflikte zwischen Apache und dem User, dem die Dateien eigentlich gehören sollten, auszulösen. Auch war mir schon lange ein Dorn im Auge, dass mod_php nicht mit Threads umgehen kann und dazu zwingt zum ineffizienten Prefork-Modus zurückzukehren. Damit fällt eine wesentliche Verbesserung von Apache2 gegenüber 1.3 weg.
Und nicht zuletzt erscheint es mir in Hinblick auf die Serversicherheit keine gute Idee zu sein PHP mit den weitreichenden Befugnissen des Apache laufen zu lassen – zumal Restriktionen wie open_basedir leicht umgangen werden können.

PHP als FastCGI einzubinden stellt zwar einen etwas höheren Konfigurationsaufwand gegenüber mod_php dar, der jedoch mit Lösung der oben genannten Probleme belohnt wird.

Sobald ich mal wieder ein Quentchen mehr Zeit finde, werde ich ein Mini-Tuorial für Debian 4 an dieser Stelle veröffentlichen. Momentan bin ich noch damit befasst den Geschwindigkeitsunterschied zwischen mod_php und der FastCGI-Variante zu messen.

wget aufbohren: dotfiles per –mirror mitkopieren

Ich benutze GNU wget gerne um verschiedene Websites per FTP mit dem Parameter --mirror zu spiegeln. Leider werden dabei versteckte Dateien (so genannte dotfiles) wie etwa .htaccess nicht berücksichtigt. Nach eingehendem Studium der manpage stellte ich enttäuscht fest, dass wget tatsächlich keine Option zur Lösung des Problem vorsieht.

Aber zum Glück lässt sich GNU wget als Open-Source-Software an die eigenen Bedürfnisse anpassen, so dass ich folgenden q&d Patch „entwickelte“.

— wget-1.10.2_orig/src/ftp-basic.c 2005-06-19 15:47:10.000000000 +0200
+++ wget-1.10.2/src/ftp-basic.c 2007-04-21 14:17:33.000000000 +0200
@@ -977,7 +977,7 @@
uerr_t err;

/* Send LIST request. */
– request = ftp_request („LIST“, file);
+ request = ftp_request („LIST -a“, file);
nwritten = fd_write (csock, request, strlen (request), -1.0);
if (nwritten < 0) { [/code]
wget ftp://ftp.gnu.org/pub/gnu/wget/wget-1.10.2.tar.gz
tar -xzf wget-1.10.2.tar.gz
patch -p0 < wget-1.10.2_dotfiles ./configure make make install

Es genügt also LIST -a anstatt LIST an den FTP-Server zu senden, um wget zu überreden auch dotfiles rekursiv zu kopieren.
Der Patch ist – wie gesagt – ein übler Hack, der mir zur schnellen Lösung eines Problems dienen solle. Für mich funktioniert er gut. Perspektivisch wäre es jedoch wünschenswert durch einen Parameter zwischen LIST und LIST -a wählen zu können. Nach meiner mündlichen Diplomprüfung werde ich das sauber implementieren und als Feature vorschlagen.

EDIT 16:40: Hier gibt es einen sauberen Patch, allerdings nur für Version 1.9.1. Doch es sollte nicht allzu schwer fallen ihn auf die aktuelle Version zu portieren.

Zeichensätze bequem konvertieren

Eine bequeme Möglichkeit Zeichensätze zu konvertieren kommt natürlich aus der UNIX-Welt: iconv

Kürzlich wurde ich mit der Migration eines CRM beauftragt. Das alte CRM speicherte die Daten ISO 8859-1 codiert ab, das neue in UTF-8.

Hier die Lösung:

iconv -f iso-8859-1 -t utf-8 crm8859-1.sql > crmUTF-8.sql

Das SQL-Dump war übrigens > 2 GB, iconv eignet sich im Gegensatz zu vielen anderen Tools auch für umfangreichere Datenmengen.
Iconv lässt sich übrigens auch über viele Scriptsprachen wie etwa PHP, Perl oder Ruby benutzen.

Linux-Firewalls – Ein praktischer Einstieg

Linux-Firewalls - Ein praktischer Einstieg O’Reilly bietet Linux-Firewalls – Ein praktischer Einstieg als OpenBook zum kostenlosen Download an. Das Buch bietet auf 692 Seiten alles, was der Einsteiger zum Einrichten, Konfigurieren und Warten einer Firewall unter Linux wissen sollte. Nachdem der Autor Andreas Lessig dem Leser erklärt hat, was Firewalls sind und gegen welche Art von Angriffen sie schützen können, geht er dazu über Grundlagenwissen über Netzwerke zu vermitteln. Aufbauend auf einen kurzen, theoretischen Abriss über Firewalls wird der Leser durch die Installation und Konfiguration eines sicheren Linuxsystems, am Beispiel von SuSE 9.3 und Debian 3.1 geführt. Dieser Abschnitt nimmt meines Empfindens zuviel Raum im Buch ein. Installation und Konfiguration eines Linuxsystems werden in anderen Büchern ausführlicher und besser beschrieben, so dass Verweise auf auf weitere Literatur genügt hätten.

Erst in den Kapitel 11 und 12 kommt Andreas Lessig auf die Konfiguration einer Firewall mithilfe von ipchains und iptables zu sprechen. Die Ausführungen dazu sind ausführlich, umfassend und verständlich. Die Kapitel über Tests von Firewalls und dauerhafter Absicherung des Systems runden das Buch ab.

Für Einsteiger ist das Buch sehr gut geeignet, um sich in den Themenkomplex Paketfilter und Firewalls unter Linux einzuarbeiten, fortgeschrittene Anwender sowie Administratoren dürften jedoch wenig neues erfahren. So ist der Untertitel „Ein praktischer Einstieg“ auch seht gut gewählt.

Das Buch wird als LaTeX-Dokument angeboten, um es als PDF lesen zu können, muss eine LaTeX-Distribution auf dem Rechner installiert sein. Mit make pdf ist das Buch dann jedoch schnell kompiliert.

Wenn das Netzteil verreckt

Momentan stelle ich auf Basis von Debian Etch eine eigene Distribution für Terminalrechner zusammen. Dabei gilt es solche Probleme zu lösen wie etwa Anbindung von Touchscreens an X.Org, Ansteuerung eines Mikrocontrollers über CGI und nicht zuletzt Firefox für den Kioskmodus anzupassen.
An den Rande der Verzweiflung hat mich getrieben, dass mein Mini-ITX-Testsystem gelegentlich abgeschaltet hat. Da der Rechner bisher unter Sarge problemlos arbeitete, ging ich davon aus, dass der Grund für die Totalabstürze meine Kernelmodifikationen seien. Als die Box jedoch auch mit dem Standardkernel abstürzte, dränge sich mir der Verdacht auf, dass das Netzteil defekt sein könnte. Mit dem Multimeter konnte ich meinem Verdacht bestätigen: Liefern sollte das Netzteil eine Ausgangsspannung von 12V DC mit einer Toleranz von 5%. Mein Messwerte schwankten zwischen 9V und 14V.
Zwar ist auf dem Netzteil noch Garantie, aber bis das ausgetauscht ist dürfte einige Wochen ins Land ziehen. Momentan betreibe ich die Box an einem alten ATX-Netzteil, aber das ist keine sinnvolle Lösung, weil die Stromversorgung der 2.5″ Festplatte etwas wacklig ist.

Aufgeschraubtes Mini-ITX-System mit defektem Netzteil

Morgen werde ich versuchen bei Conrads einen Ersatz zu organisieren. Das hier sollte passen. Lediglich beim Stecker bin ich mir unsicher. Ob die wohl genormt sind?