Daniels Blog
15Jun/110

12 Maßnahmen um einen Linux root LAMP Apache MySQL PHP Webserver abzusichern


Die Hacking-Frequenz ist in den letzten Monaten stark angestiegen. Besonders viele Daten werden abgegriffen durch Hacks auf Webserver. Sogar der SONY-PSN-Hack nutzte Schwachstellen in einem ungepatchten Apache-Webserver. Deshalb sammele ich hier Maßnahmen, die den eigenen Server etwas sicherer gegen Angriffe von außen machen können. Natürlich bieten auch diese keinen 100%igen Schutz, aber es ist besser, den bösen Buben das Spiel ein wenig schwieriger zu machen. Einige der Maßnahmen benötigen nur einen minimalen Installations- und Wartungsaufwand. Andere benötigen viel Zeit und Kenntnisse von PHP um zu greifen. Man sollte immer auf das Kosten-Nutzen-Verhältnis bei der Auswahl der Sicherheitsmaßnahmen achten. Es macht keinen Sinn, eine kleine, private Website so abzusichern wie die Federal Reserve Bank. Allerdings können wenige gezielte Änderungen am System bereits ein großes Mehr an Sicherheit bedeuten. Und das sollte man sich schon gönnen, bevor es zu spät ist....

Alle Tipps und Codesnips beziehen sich auf eine aktuelle Debian-Kiste.

1. Die Firewall - erst einmal alles verbieten

Die meisten Linux-Distributionen öffnen in ihren Standardinstallationen keine Ports nach außen, die nicht unbedingt notwendig sind. Diese Situation kann man jedoch schnell selbst ändern, wenn man am Server
herumspielt und Dinge ausprobiert. Plötzlich lauscht auch der Mediaserver im Internet oder die Datenbank
nimmt Verbindungen aus dem Internet entgegen. Deshalb ist es nicht verkehrt sich selbst zu disziplinieren und eine sehr restriktive Firewall aufzusetzen, die grundsätzlich erst einmal alle Verbindungen von außen verbietet und nur (selbst) ausgewählte Verbindungen gestattet. Zum Glück ist das mit iptables schnell erledigt. Auf diese Art und Weise kann man nicht mehr aus versehen Dienste der Welt zugänglich machen, die dort nichts zu suchen haben. Man bezahlt leider mit etwas Komfort - die Firewall muss jedes Mal angepasst werden, wenn man neue Dienste anbieten möchte. Trotzdem ist der Aufwand klein und der Nutzen groß.

#!/bin/bash
# Bestehende Tables löschen
iptables -F

# Alle eingehenden Verbindungen verbieten
iptables -P INPUT DROP
iptables -P FORWARD DROP

# Alle ausgehenden erlauben
iptables -P OUTPUT ACCEPT

# SSH erlauben
iptables -A INPUT -j ACCEPT -p tcp --dport 22

# HTTP erlauben
iptables -A INPUT -j ACCEPT -p tcp --dport 80

# Weiteren Dienst (UDP) erlauben, zum Beispiel Gameserver
iptables -A INPUT -j ACCEPT -p udp --dport 4534

# Alles von Localhost erlauben. (Damit der Server selbst ungehindert auf seine Dienste zugreifen kann,
# zum Beispiel PHP auf die lokale Datenbank
iptables -A INPUT -j ACCEPT -s 127.0.0.1

# Bereits aufgebaute Verbindungen werden an jedem Port akzeptiert
# (Damit Antworten auf Anfragen, die vom Server kommen immer zurückkommen können)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Dieses kleine Grundgerüst kann man einfach weiter ausbauen und eigene Dienste hinzufügen. Bei Arbeiten an der Firewall sollte man immer für den Fall vorsorgen, dass man sich selbst aussperrt. Besonders bei Remote-Servern, auf die man keinen physischen Zugriff hat, ist es sehr ärgerlich, durch eine mißglückte Firewallregel den eigenen Zugriff zu verlieren. Um diesem Problem aus dem Weg zu gehen, kann man bei Arbeiten an der Firewall einfach temporär einen Cronjob starten lassen, der die Firewall alle paar Minuten zurücksetzt oder den Server neu startet. Sind die Regeln später getestet und geliebt, kann der Cronjob wieder deaktiviert werden und die neuen Regeln bleiben permanent aktiv.

Um herauszufinden, welche Dienste gerade auf dem eigenen Server herumlauschen, kann man netstat benutzen:

#Für TCP-Sockets:
netstat -lpn | grep tcp

#Analog für UDP:
netstat -lpn | grep udp

Um zu testen ob die Firewall wirklich funktioniert, kann man den eigenen Server von einem anderen Rechner aus portscannen. Hat alles geklappt, sollten im Ergebnis nur die selbst geöffneten Ports auftauchen:

#Für TCP:
nmap -p1-65535 meinserver.de
#Für UDP:
nmap -sU -p1-65535 meinserver.de

2. SSH Logins verbieten

Am eigenen root-Server hat man uneingeschränkten SSH-Zugriff. Das ist recht praktisch, da man von jedem SSH-Client aus mal eben auf den Server kann um an ihm zu arbeiten. Der Nachteil davon ist, dass das natürlich auch jeder andere kann, der unglücklicher Weise irgendwie an das eigene Passwort gelangt ist. Es ist viel sicherer SSH-Logins nur mit einer gültigen Schlüsseldatei zu erlauben. Dafür wird der öffentliche Schlüssel des Clients auf den Server kopiert und interaktive Logins per Passworteingabe werden deaktiviert.

# Auf dem Client einen öffentlichen Schlüssel erstellen
# Wird bei der Generierung ein Passwort angegeben, benötigt man zum
# einloggen später die Schlüsseldatei UND das Passwort. Ansonsten wird
# nur der Schlüssel benötigt.

ssh-keygen -t rsa

# Den erstellten Schlüssel danach auf den Server kopieren

ssh-copy-id -i ~/.ssh/id_rsa.pub root@meinserver.de

# Danach auf dem Server /etc/ssh/sshd_config anpassen
.
.
PasswordAuthentication no
.
.

# Danach SSh neu starten
/etc/init.d/ssh restart

Auch hier sollte man Vorkehrungen treffen, um sich nicht selbst auszusperren, falls etwas nicht funktioniert.
Der Public Key auf einem USB-Stick mit dem dazugehörigen Passwort im eigenen Kopf macht es sehr viel schwerer für böse Buben eine Shell zu erhalten.

3. SSH Bruteforcing verhindern mit denyhosts

Falls Tipp 2 nicht praktikabel ist und man den Komfort von passwortgestützten Logins nicht aufgeben will, kann man zumindest das automatisierte Passwortraten von Angreifern auf dem Server verhindern. Sehr viele Bots im Internet machen den ganzen Tag nichts anderes als nach SSH-Servern zu suchen und bei Ihnen verschiedenste Passwörter durchzuprobieren. Mit einem halbwegs sicheren Passwort ist das kein großes Problem, trotzdem gibt es ein besseres Gefühl, wenn nicht einmal das möglich ist. Außerdem schützt man so auch seine User, falls auf dem Server auch Useraccounts bestehen. Hier kann man sich nicht darauf verlassen, dass die Benutzer sichere Passwörter verwenden. denyhosts überprüft ständig Logins auf dem ssh und sperrt Benutzer für eine gewisse Zeit, die ihr Passwort wiederholt falsch angegeben haben. Die IP's dieser Nutzer landen temporär in /etc/hosts.deny, so dass für sie kein Zugriff mehr möglich ist. Damit wird SSH-Bruteforcing zu einer sehr langwierigen und wenig erfolgversprechenden Aufgabe.

apt-get install denyhosts

# denyhosts funktioniert direkt nach der Installation. Man kann es
# in der Datei /etc/denyhosts.conf feintunen

4. Blacklisten benutzen, um bekannte Problem-IPs auszusperren

Im Internet werden verschiedene Blacklisten gepflegt, die eine große Anzahl von kriminellen/gehackten/spammenden/betrügerischen Servern auflisten. Diese IP-Listen können direkt in die Firewall eingetragen werden, so dass von diesen bekanntermaßen nicht vertrauenswürdigen Rechnern überhaupt keine Verbindung mehr zum eigenen Server möglich ist. So kann man das Spamaufkommen auf dem eigenen Server drastisch verringern und auch das eine oder andere Script-Kiddie aussperren, weil sein Russland-Proxy plötzlich nicht mehr funktioniert. Wie man das macht habe ich bereits in einem anderen Blog-Artikel am Beispiel der Blacklist von Infiltrated.net beschrieben.

5. Kein FTP benutzen für die Arbeit am Server

FTP ist ein Relikt aus besseren Zeiten in denen das Internet noch ein kleines vertrauenswürdiges Dörfchen war. Viele Admins von Webseiten nutzen nach wie vor FTP um Dateien zum Server zu übertragen oder um an der eigenen Website zu arbeiten. Das ist leider sehr unsicher, da FTP alle Daten ungesichert übertragt. Passwörter und Daten können an jedem Hop zwischen Server und Client ohne Probleme mitgelesen werden. Viel sicherer geht es mit sshfs. Hiermit kann man sich per SSH ein Verzeichnis des Remote-Servers in sein lokales Dateisystem mounten. Man kann danach auf dem Server so arbeiten, als sei er auf dem lokalen Rechner. Alle Dateizugriffe auf Dateien auf dem Server sind komplett transparant, man kann also auch mit dem lokalen Grafikprogramm ein Bild auf dem Server direkt öffnen, bearbeiten und wieder speichern. Mehr Komfort und mehr Sicherheit ohne großen Aufwand.

#sshfs installieren
apt-get install sshfs

#mountpoint im lokalen Dateisystem anlegen
mkdir /media/meinserver

#Server ins lokale Dateisystem mounten
sshfs www-data@mein-server.de:/var/www /media/meinserver

#Nun ist das Verzeichnis /var/www auf meinserver lokal unter /media/meinserver verfügbar

6. Updates installieren

Ein super abgesichertes System hilft nichts, wenn das System selbst fehlerhaft ist und eine bekannte Sicherheitslücke ausgenutzt werden kann. Meist werden diese Sicherheitslücken schnell geschlossen, oft vergessen Admins jedoch regelmäßige Updates des Systems zu machen. Ob man automatische Updates auf Linux-Servern aktivieren sollte oder nicht ist ein strittiges Thema. Einige würden es niemals tun, da es natürlich mit viel Pech auch sein kann, dass die Updates das System unbrauchbar machen. Dies ist mir in über 10 Jahren Arbeit an Debian-Systemen allerdings niemals passiert und ich schätze den Nutzen von zeitnahen und regelmässigen Updates viel höher ein, als die daraus entstehende Gefahr.

#Diese Zeile in der /etc/crontab aktualisiert das System täglich um 6 Uhr morgens
0 6 * * *       root    apt-get update && apt-get -y upgrade

Diese Quick-and-dirty Methode funktionierte bei mir bisher immer gut. Vor kurzem habe ich gelesen, dass im Debian Repository auch das Paket unattended-upgrades existiert, das die Aufgabe wohl etwas eleganter löst, ich habe es allerdings bisher nicht getestet.

Auch bei diesen vollautomtischen Systemupdates ist man nicht komplett aus dem Schneider. Falls ein Kernel-Update ausgeliefert wurde, muss man das System trotzdem noch per Hand neu booten, da ansonsten die Änderungen nicht aktiv werden.

Benutzt man fremden PHP-Code auf dem Server, wie zum Beispiel ein Open-Source CMS oder ein Forum, ist es natürlich absolut notwendig auch diesen Code mit neuen Versionen aktuell zu halten. Da Debian mit seinen Updates Änderungen an diesen Applikationen in der Regeln nicht abdeckt, ist hier Handarbeit nötig. Am besten liest man die Mailinglisten der entsprechenden Produkte mit um immer auf dem Laufenden zu sein.

7. PHP einsperren mit open_basedir

Viele Hacks basieren darauf, dass eine Sicherheitslücke im PHP-Code ausgenutzt wird, um auf Dateien im Dateisystem zuzugreifen, die nicht zur Website gehören, sondern zum System selbst. Deshalb sollte man PHP einsperren, so dass es nur in explizit erlaubten Verzeichnissen lesen und schreiben darf. Dafür bietet die php.ini die Konfigurationsoption open_basedir. PHP hat nach setzten der Option nur noch Zugriff auf die dort erlaubten Verzeichnisse. Dateien wie /etc/passwd werden unerreichbar. Hostet man auf einem Server mehrere Webseiten sollte man open_basedir in der jeweiligen VirtualHost-Konfiguration pro Seite setzen.

# Global per php.ini:
# /etc/php5/apache2/php.ini
open_basedir = /var/www/:/tmp/

# Per Site in der VirtualHost Config:
php_value open_basedir /var/www/site/:/tmp/

Wichtig ist zu prüfen ob wirklich alle Orte eingetragen wurden, auf die die Skripte normalerweise Zugriff haben müssen, ansonsten kann es sein, dass man auch legitime Funktionen der PHP-Applikation behindert.

8. Für Websites einen eigenen MySQL-Benutzer anlegen

Benutzt die eigene PHP-Applikation MySQL, sollte man unbedingt für die Apllikation einen eigenen MySQL-Benutzer anlegen und auf keinen Fall den MySQL-root-Benutzer für Zugriffe nutzen. Außerdem sollte man die Rechte des Benutzers so weit einschränken, dass wirklich nur noch Operationen erlaubt sind, die das PHP-Skript benötigt. CREATE TABLE und DROP TABLE werden zum Beispiel häufig bei SQL-Injections genutzt und werden in den meisten PHP-Applikationen nie benötigt. Hostet man mehrere Websites mit mehreren Datenbanken auf einem Server, sollte man für alle Datenbanken eigene Benutzer anlegen. So hat ein Angreifer nach einem erfolgreichen Angriff nur Zugriff auf eine der Datenbanken und nicht direkt auf alle. Wenn man nicht die Kommandozeile bemühen möchte, um die MySQL-Useraccounts zu verwalten, funktioniert das Usermanagement auch recht einfach mit PHPmyAdmin unter der Registerkarte "Rechte".

9. PHP Fehlermeldungen abschalten

PHP-Fehlermeldungen können einem Angreifer viel über den eigenen Server verraten: Verzeichnisstrukturen, Datenbankstrukturen, Konfigurationsfehler, etc. Außerdem sehen sie für den Benutzer sehr unprofessionell aus. Aus diesem Grund sollte man sie auf einem Live-Webserver grundsätzlich abschalten, da man sie ohnehin weiterhin in den Logs sehen kann.

# Global per php.ini:
# /etc/php5/apache2/php.ini
display_errors = Off

# Per Site in der VirtualHost Config:
php_flag display_errors Off

# Fehlermeldungen trotzdem lesen:
cat /var/log/apache2/error.log | grep PHP

10. Angriffsfläche für SQL-Injections einschränken mit modSecurity

SQL-injections sind die wohl am häufigsten genutzte Angriffsmethode auf Webserver. Der Zugriff erfolgt direkt über die Webapplikation und es genügt ein Browser um sie durchzuführen. Dabei werden über vom User übermittelte Variablen geschickt SQL-Abfragen eingebaut, die mit den Rechten des Datenbankbenutzers alles an der eigenen Datenbank nach belieben auslesen, löschen oder bearbeiten können. Ein wirklicher echter Schutz gegen SQL-Injections besteht nur, wenn der PHP-Code der Site im Hinblick auf diese Angriffe geschrieben wurde. Jede Variable aus Benutzereingaben, die in eine SQL-Abfrage gelangen könnte, muss geprüft und escaped werden. PHP bietet dafür die Funktion real_mysql_escape_string().

Ist man nicht sicher, ob der Code sauber ist, kann mod_security für den Apache helfen eine große Menge dieser Angriffe trotzdem abzuwehren. mod_security überprüft ständig alle Requests an den Webserver und reagiert auf vorgefertigte Muster mit denen viele SQL-Injection-Angriffe abgewehrt werden können. Leider funktioniert auch mod_security nur gut mit manuellem Aufwand. Oft blockt mod_security nach einer frischen Installation auch gewünschte (normale) Funktionen des eigenen PHP-Codes, so dass einem nichts anderes übrig bleibt, als die komplette Applikation nach der Installation einmal durchzutesten. Nur so findet man heraus, ob mod_security nicht eventuell auch gewünscht Funktionen blockt. Ist das der Fall, muss die Filterliste angepasst werden, so dass die false-positives verschwinden.

Die Konfiguration von mod_security ist etwas komplizierter und würde den Umfang dieses Artikels sprengen, es gibt aber massenweise gute Tutorials zu mod_security im Internet.

11. Ausweiskontrolle - Der Apache sagt nicht mehr, wer er ist
Dies ist keine wirklich wirkungsvolle Methode gegen einen Hack, sie macht es automatisierten Skripten, die nach Server-Versionen suchen aber etwas schwerer. Normalerweise zeigt der Apache auf Seiten mit Fehlermeldungen (z.B. 404 Not Found) seine Serversignatur.

Apache/2.2.16 (Debian) Server at www.daniel-ritter.de Port 80

So erhalten potentielle Angreifer zumindest schon einmal Informationen über den eigesetzten Webserver und den Versionsstand. Die Serversignatur ist schnell ausgeschaltet:

#/etc/apache2/conf.d/security
ServerSignature Off

12. Nicht benutze Apache-Module deaktivieren

Per default hat der Apache einige Module geladen, die fast nie benötigt werden. Unter Debian findet man die geladenen Module
als Softlinks in /etc/apache2/mods-enabled.

Fast immer entfernt werden können:

mod_cgi

Dient dem ausführen von CGI-Skripten. Diese Technik stammt noch aus den Urzeiten des Web und war der Vorvater der modernen Skriptsprachen um dynamische Webseiten zu ermöglichen. mod_cgi ist auf 99% der PHP-Websites unnötig und bei einer fehlerhaften Apache-Config eine potentielle Sicherheitslücke

a2dismod cgi

mod_status

Ermöglicht es Browsern Statusinformationen über den Apache auszulesen. Es wird so gut wie nie für "normale" Sites genutzt, bietet Angreifern aber Statusinformationen über den Apache.

a2dismod status

mod_autoindex

mod_autoindex sorgt dafür, dass Verzeichnisse auf dem Webserver aufgelistet werden können, wenn es keine gültige Index-Seite in dem entsprechenden Verzeichnis gibt. Falls diese Funktionalität nicht erwünscht ist, sollte man sie abschalten, da durch sie ganze Verzeichnisbäume auf dem Webserver nach aussen sichtbar werden können.

a2dismod autoindex
29Apr/100

6 nützliche Dinge, die man mit SSH tun kann

SSH ist wahrscheinlich mein liebstes Stück Software. Es ist frei, gibt mir Freiheit, es ist einfach zu benutzen und ist trotzdem sehr mächtig. Mit SSH kann man Kommunikation verschlüsseln. Das klappt auf eine sehr universelle Weise für fast jedes Problem. In diesem kleinen Howto zeige ich 6 nützliche Dinge die man - ohne zu großen Stress - mit SSH tun kann. SSH ist mehr als "nur" eine sichere Remote-Shell!

Ding #1 - Eine sichere Remote-Shell

ssh_console1

Das ist das Offensichtlichste was man mit SSH tun kann und die meisten Linuxuser haben es wohl schon einmal gemacht: Eine sichere Verbindung mit einem anderen Rechner herstellen und diesen darüber administrieren.

Das geht sehr einfach:

ssh user@box_B

Das verbindet Dich zu BOX B als "user". Danach kann man als "user" auf BOX B arbeiten.

Manchmal benötigt man gar keine interaktive Sitzung zu einem entfernten Rechner, sondern möchte lediglich ein einzelnes Kommando ausführen.

ssh user@box_B command

Hier wird man zu Box B als "user" verbunden, das Kommando "command" wird ausgeführt, das Ergebnis landet auf der lokalen Standardausgabe und die Verbindung wird beendet.

Ding #2 - Dateien zwischen Rechnern sicher kopieren

ssh_copy

Cool, wir können eine entfernte Maschine mit SSH administrieren, aber man kann mit SSH auch Dateien von einer Maschine zu einer anderen kopieren. Es funktioniert im Grunde so wie das "cp" Kommando, es heisst aber "scp" - Secure Copy.

scp /home/me/a_file.txt user@box_B:/home/me/

Das kopiert die lokale Datei "/home/me/a_file.txt" auf Box A nach "/home/me/a_file.txt" auf Box B.

Es funktioniert auch andersherum:

scp user@box_B:/home/me/b_file.txt /home/me

Das würde die Datei "/home/me/b_file.txt" von Box B ins Home-Verzeichnis auf Box A kopieren.

Weil "scp" so ähnlich funktioniert wie "cp" sind auch Wildcards erlaubt:

scp /var/log/* user@box_B:/home/me/logsbackup

Das kopiert alle Logfiles von Box A nach "/home/me/logsbackup" auf Box B.

Ding #3 - Ein Verzeichnis auf einem entfernten Rechner ins lokale Dateisystem mounten

ssh_mount

Manchmal reicht es nicht einfach nur einige Dateien von einem Rechner auf einen anderen zu kopieren. Ein entferntes Verzeichnis ins lokale Dateisystem zu mounten ist super nützlich, wenn man mit lokalen Programmen Remote-Files bearbeiten will. Ein gutes Beispiel dafür wäre zum Beispiel die Arbeit an einer Webseite auf einem entfernten Server. Man kann einfach das Web-Verzeichnis des entfernten Servers ins lokale Dateisystem mounten und danach die Dateien mit all den coolen lokal installierten HTML-Editoren und Grafikprogrammen öffnen und speichern. Ganz so als wären die Dateien auf der loaklen Platte. Hierfür benötigt man "sshfs". Das FUSE-Filesystem ist in vielen Distributionen nicht standardmässig installiert aber meistens in den Repositories enthalten. Unter Debian und Ubuntu kann man es so installieren:

apt-get install sshfs

Nach der Installation kann man beginnen es zu benutzen

mkdir /mnt/b_data
sshfs user@box_B:/b_data /mnt/b_data

Das mountet das Verzeichnis "/b_data" auf Box B nach "/mnt/b_data" im lokalen Dateisystem. Nun kann man mit lokalen Programm die Remote-Dateien bearbeiten. Wenn man fertig ist, kann man den mount wieder entfernen:

fusermount -u /mnt/b_data

Falls der unmount fehlschlägt sollte man überprüfen, ob noch Dateien vom Remoterechner geöffnet sind oder ob man sich noch mit der Shell oder einem Dateimanager im gemounteten Verzeichnis befindet.

Ding #4 - Unzensiert und anonym von "kritischen Orten" aus im Web surfen

ssh_proxy

Firmenrichtlinien, faschistische Regierungen, Internet-Cafes und andere unfreundliche Regelungen, Institutionen und Orte können einen sicheren und privaten Zugriff aufs Web ziemlich schwierig gestalten. Firewalls und Proxys könnten interessante Webseiten blocken, loggen wo man herumsurft, Man-In-The-Middle-Attacken ausführen oder einfach nur ein mulmiges Gefühl generieren. SSH ist die Lösung für alle diese Probleme. Es bietet die Möglichkeit als Web-Proxy (SOCKS) zu arbeiten. Man verbindet sich einfach per SSH zur guten vertrauenswürdigen BOX B und surft durch diese Verbindung.

(Lokaler Browser <-> Lokaler SSH Proxy <-> SSH <-> Box B <-> Webseite)

Dann kann niemand mehr im unfreundlichen lokalen LAN blockieren, zensieren oder schnüffeln.
Klingt gut? Es ist sogar sehr einfach einzurichten und zu benutzen! SSH bietet die "-D" Option um einen SOCKS-Proxy auf der lokalen Maschine einzurichten:

ssh -D 1234 user@box_B

Nun hat man einen SOCKS-Proxy der auf localhost Port 1234 lauscht. Nun muss man nur noch seinem Browser so konfigurieren, dass er für Internetverbindungen diesen Proxy benutzt. Man kann überprüfen ob alles funktioniert hat, wenn man im Browser eine Webseite aufruft, die die IP-Adresse ausgibt, die für die Verbindung genutzt wurde. http://www.whatismyip.com würde funktionieren, aber es gibt auch 1000de andere Seiten. Wenn dort die IP von Box B erscheint, ist alles in Butter. Ein portalbler Browser auf einem USB-Stick wie zum Beispiel Portable Firefox würde die Sache noch angenehmer machen.

Ding #5 - Den Traffic von lokalen Programmen verschlüsseln und tunneln oder auf Dienste in LANs zugreifen, die normalerweise nicht übers Internet erreichbar sind.

ssh_tunnel_l

OK, wir haben sicher Maschinen administriert, Dateien sicher von Maschine zu Maschine kopiert und haben sogar in China unzensiert im Web gesurft. Aber SSH kann mehr! Man kann damit den Datenaustausch aller lokalen Programme die TCP benutzen durch einen Tunnel zu einem vertrauenswürdigen Rechner schicken. Wie schon mit dem SOCKS-Proxy kann man Daten-Verkehr zunächst durch diesen Tunnel schicken, zum Beispiel den vom lokalen E-Mail Client, damit er nicht durchs lokale LAN fliessen muss. Wir möchten unsere E-Mail in einer "kritischen" Umgebung abrufen. Skript Kiddies, blöde Admins und Terror-China-Hacker könnten die Mail mitlesen oder sogar das E-Mail-Passwort mitsniffen. SSH hilft. Die Syntax für Tunnel mit SSH ist etwas krampfig und zunächst ein ziemlicher Brain-Twister aber eigentlich ziemlich logisch und mit ein bisschen Übung nicht schwierig:

ssh -L local_port:target_host:target_port user@box_B

zum Beispiel:

ssh -L 10000:pop3.mailprovider.com:110 user@box_B

Was ist hier geschehen? SSH wurde angewiesen einen Tunnnel mit einem lokalen (-L) Endpunkt auf Port 10000 anzulegen. Alles was in diesen lokalen Endpunkt an Daten hineingeworfen wird, fliesst zunächst verschlüsselt zu Box B und danach zu "pop3.mailprovider.com" auf port 110 (Port 110 ist POP3). Die Daten fliessen also vom lokalen E-Mail Client verschlüsselt zu Box B und von dort aus an den E-Mail-Provider. Der E-mail Account im lokalen Client benötigt somit also für den POP-Server folgende Einstellungen: Server: localhost / Port: 10000. Aber es muss nicht unbedingt E-Mail sein. Jede Applikation, die das TCP-Protokoll benutzt kann so getunnelt werden. Zum Beispiel IRC, FTP, HTTP, IMAP, etc.

Falls sich der Server auf den zugegriffen werden soll nicht irgendwo im Internet sondern auf Box B selbst befindet, kann der Zielrechner natürlich auch BOX B sein:

ssh -L 10000:127.0.0.1:110 user@box_B

Ziel in diesem Beispiel ist "127.0.0.1", weil es das Ziel aus der Sicht von Box B ist. Denn "127.0.0.1" gesehen von Box B ist Box B selbst.

Tunneln kann nützlich sein um Internetdienste abzusichern, aber auch um auf Dienste in BOX B's privatem Netzwerk zuzugreifen. Falls man einen von außen zugänglichen SSH-Account in einem LAN besitzt, kann man so auf alle TCP-Dienste in diesm LAN zugreifen, ganz so als sei man ein "echter" Client in diesem LAN.

Angenommen BOX B steht in einem Intrantet, das einen interessanten Webserver beherbergt, der aber nicht aus dem Ineternet zugänglich ist. Dieser Server läuft im LAN auf Kiste 192.168.0.77. Mit SSH tunnelt man nun einfach einen lokalen Port auf Port 80 des Webservers im LAN:

ssh -L 10000:192.168.0.77:80 user@box_B

Wenn man nun "http://127.0.0.1:10000" im lokalen Webbrowser aufruft landet man auf der Homepage des Webservers im entfernten Intranet.

Ding #6 - Ein Tunnel - andersherum

ssh_tunnel_r_good

Wenn #5 klar ist, sollten umgekehrte Tunnel kein Problem mehr sein. Hier wird ein entfernter Endpunkt für den Tunnel erstellt. Alles was dort hineinfliesst wird verschlüsselt weitergeleitet an BOX A (den lokale Rechner) und danach an den Zielrechner weitergeleitet.

ssh -R remote_port:target_host:target_port user@box_B

zum Beispiel:

ssh -R 10000:pop3.mailprovider.com:110 user@box_B

Im E-Mail-Client würde man als POP-Server "Box B" und Port "10000" eintragen.
BOX B tunnelt dann den Traffic zunächst sicher auf BOX A um. Box A leitet danach weiter an "pop3.mailprovider.com" port "110"

Nützliche Kommandozeilenoptionen für SSH

-c "Compress"

Die "-c" Option komprimiert die übertragenen Daten mit gzip bevor sie durchs Inetrnet fliessen. Das erhöht die Geschwindigkeit beim Übertragen von unkomprimierten Daten (so wie reinem Text) stark. Sie ist nützlich beim Übertragen
langer Textdateien oder beim Websurfen wenn man SSH als Proxy nutzt.

ssh -c -D 1234 user@box_B

-g "Grant Access"

Die "-g" option eraubt anderen Rechnern als localhost auf die lokal angelegten Tunnelendpunkte zuzugreifen. So können also zum Beispiel auch andere Rechner im LAN die lokal angelegten Tunnel nutzen.

ssh -L -g 10000:127.0.0.1:110 user@box_B

-p "Port"

Die "-p" Option benötigt man, wenn der entfernte SSH-Server nicht auf dem Standardport 22 lauscht.

ssh -p 22000 user@box_b

-v "Verbose"

Mit dieser Option kann man sehr viele technische Verbindungsinformationen sehen, falls man tiefer in SSH eintauchen möchte.

Mehr Lesestoff:

Ich habe versucht diesen Artikel so einfach wie möglich zu schreiben, da er mir selbst in erster Linie als Referenz dienen soll. Es gibt aber noch sehr viel mehr was man mit SSH tun kann:

The SSH man page

The SSH RFC

Wikipedia on SSH

SSH - The Definitive Guide by O'Reilly

19Nov/090

6 Useful Things You Can Do With SSH

SSH must be my favourite piece of software ever. It's free, it gives you freedom, it's simple to use yet powerful in the things it can do. It helps you to encrypt and secure your communication. It can do this in an universal way and for nearly every usage case. In this post, I want to show you 6 things you can do with SSH without too much hassle. SSH can do more than just serve as an encrypted remote session. Try the following examples for yourself and explore the power of the Secure Shell.

Thingy #1 - A secure remote shell

ssh_console1

OK, this is the most obvious thing you can do with SSH and i bet most of you have already done it: Connect to a remote machine via a SSH-secured connection and type on it's console to administer it.

This is very simple:

ssh user@box_B

This will connect you to Box B as user "user". After having entered your password, you will be able to use BOX B's console.

Sometimes you don't want to connect to the remote machine for an interactive session, because you just want to run a single command on the remote machine. In that case you can just do a

ssh user@box_B command

This will connect to Box B as "user", run "command", show you "command"'s output and disconnect.

Thingy #2 - Copy files between your boxes

ssh_copy

Great, we can administer a remote machine with SSH but we can also move data between machines in an encrypted and secure way. It basicly works like the standard "cp" command, but it has got a different name: "scp"

scp /home/me/a_file.txt user@box_B:/home/me/

This will copy the local file "/home/me/a_file.txt" on our Box A to "/home/me/a_file.txt" on Box B.

It will work vice versa as well:

scp user@box_B:/home/me/b_file.txt /home/me

This would get the file "/home/me/b_file.txt" and would put in into our home dir on box A.

Because "scp" works like "cp" wildcards are allowed as well:

scp /var/log/* user@box_B:/home/me/logsbackup

This would copy all of the log files from our Box A to "/home/me/logsbackup" on Box B.

Thingy #3 - Mount a remote directory into your local file system

ssh_mount

Sometimes it's not enough to simply copy one or more files from one machine to another. Mounting a remote directrory into your local filesystem becomes super useful, when you want to work on the remote files with local programs. A good example for this would be working on a remote website. You can simply mount the web-directory from the remote server into your local filesystem and use all your fancy HTML-editors and image-programs on the remote files as if they were on your local harddrive. That's where "sshfs" comes in handy. The tool isn't installed by default in most distributions but you should be able to find it in your repository. On Debian based systems just install it with:

apt-get install sshfs

After having installed sshfs you can start using it:

mkdir /mnt/b_data
sshfs user@box_B:/b_data /mnt/b_data

This mounts the directory "/b_data" from box B into "/mnt/b_data" on your local file system. Now you can work on your remote files with local tools. When you are done, you can unmount the directory with:

fusermount -u /mnt/b_data

If the unmount fails, check if you have still open files in the directory or if you are still in that directory in some shell or Nautilus/Konqueror window.

Thingy #4 - Surf the Web uncensored and anonymously from "critical" locations

ssh_proxy

Corporate policies, fascist governments, internet cafés and other "unfriendly" rules, institutions and places can give you a hard time, when you want to access the web in a secure and private way. Firewalls and proxies may block your favourite sites, log the sites you have visited, perform man in the middle attacks or can just give you a bad feeling. SSH is the solution for these problems. It offers you the possibility to use it as a web-proxy. You simply connect to your good old trusted box B and surf through the encrypted connection.

(Local Browser <-> Local SSH Proxy <-> SSH <-> Box B <-> Website)

Now nobody on your unfriendly local LAN can block or spy on your surfing session.
Sounds good? Great! It's even simple to setup. SSH offers the "-D" option to provide a SOCKS proxy on the local machine:

ssh -D 1234 user@box_B

You'll have a proxy listening on localhost port 1234. Now you just have to setup your webbrowser to use the "SOCKS proxy" on localhost port 1234 and all your surfing will go through Box B. You can check if it worked by visiting a website that shows your IP. http://www.whatismyip.com is a site that would work. If that site shows Box B's IP-address instead of your local one, you setup everything correctly. A portable webbrowser on your USB-pendrive like  Portable Firefox would make things even more cozy.

Thingy #5 - Encrypt the data traffic of your favourite local application or access services in LAN's you couldn't reach otherwise with SSH-tunnels

ssh_tunnel_l

OK, we encrypted remote admin-sessions, copied files securely and even surfed the web in a private way. But SSH can do more. You can encrypt the traffic of every application that uses the TCP-protocol with SSH tunnels. Like with our SOCKS-proxy, we can tunnel other data through ssh, for example the traffic of our e-mail client. Lets say you want to pickup your e-mail while being in a "critical" environment. Bad corporations / governments / script kiddies could read your email and even worse could sniff your e-mail password. SSH helps. The syntax for tunnels in SSH might puzzle your brain at first sight, but it's not too hard:

ssh -L local_port:target_host:target_port user@box_B

for example

ssh -L 10000:pop3.mailprovider.com:110 user@box_B

OK, lets see what happened here. We told ssh to create a tunnel with a local (-L) endpoint at port "10000". Everything that is put into our local endpoint goes first encrypted to our Box B and after that to "pop3.mailprovider.com" on port 110 (which is POP3). You relay all data that goes into our local endpoint in an encrypted way via Box B to your E-Mail provider. In this example you would set the POP-account in your e-mail client to "localhost" port "10000". It doesn't have to be e-mail. Any other application that uses a protocol utilizing TCP works as well. For example IRC, FTP, HTTP, IMAP, you name it...

in case you are running your own server-service on Box B, "target host" can be Box B itself of course:

ssh -L 10000:127.0.0.1:110 user@box_B

Target host in this example is "127.0.0.1" because it's the target from Box B's point of view. "127.0.0.1" seen from Box B sure is Box B itself.

Tunneling can be useful to secure your services or to connect to services inside BOX B's network. Lets say BOX B is in an intranet that has an interesting webserver on IP "192.168.0.77" and you are unable to access that server from the outside. You just tunnel your way to BOX B and let BOX B forward you to the webserver:

ssh -L 10000:192.168.0.77:80 user@box_B

Now typing "http://127.0.0.1:10000" into your local webbrowser will show you the homepage of the intranets webserver.

Thingy #6 - A tunnel the other way around

ssh_tunnel_r_good

OK, this could have been part of "Thingy #5" but to make things more clear i made an extra point for it. If you understood #5 this should be no problem for you. Here, you open up a "remote" endpoint on Box B. Everything that goes in there is relayed encrypted to Box A (the one you are using at the moment) and after that to the target host.

ssh -R remote_port:target_host:target_port user@box_B

for example

ssh -R 10000:pop3.mailprovider.com:110 user@box_B

An e-mail client would set "box_B" and port "10000" as the POP3 server. BOX B would relay the traffic to BOX A through SSH. BOX A would relay the traffic to "pop3.mailprovider.com" port "110".

Useful commandline options for SSH

-c "Compress"

The "-c" option in SSH compresses all traffic with gzip before sending it to the remote host. This increases the speed greatly with uncompressed data-types. It's very useful for copying large text-files over SSH or for surfing the web with the "-D" option. In general "-c" never hurts, it just puts a little more pressure onto your CPU.

ssh -c -D 1234 user@box_B

-g "Grant Access"

The "-g" option allows other hosts to connect to your local tunnel endpoints. If you don't use "-g" in combination with a tunnel, only your own localhost (Box A in the examples) may use the tunnel.

ssh -L -g 10000:127.0.0.1:110 user@box_B

-p "Port"

The "-p" option is needed, if the SSH-server you want to connect to doesn't run on the default port "22"

ssh -p 22000 user@box_b

-v "Verbose"

Add this option if you want to dive deeper into SSH. You will see many technical information while connecting to a remote host.

Further reading

I tried to keep this article as simple as possible to make it usable. There is a lot more to know about SSH. If you are looking for a more comprehensive read i suggest you check out these docs:

The SSH man page

The SSH RFC

Wikipedia on SSH

SSH - The Definitive Guide by O'Reilly