Aus Linux-Magazin 05/2005

Generisches Proxy-Protokoll Socks 5 im Detail

Ein universelles Proxy-Protokoll für TCP und UDP, mit dem interne Hosts sicher über die Firewall kommen und dabei ihre Benutzer authentifizieren – diese Identity-Management-Aufgabe erfüllt das Socks-Protokoll. Der Artikel stellt das Protokoll und eine Implementierung vor.

Während viele Firewall-Admins den direkten Webzugang vom internen ins externe Netz erlauben, sind sie bei anderen Diensten wie FTP oder SMTP restriktiver. Ihr gutes Argument: Eine Firewall muss übersichtlich und leicht kontrollierbar sein, daher dürfen die Regeln nur wenige Dienste und Ports durchlassen. Noch mehr Kontrolle erlauben Application Level Gateways: Diese ALGs sind meist als Proxy implementiert (Abbildung 1a). Allerdings braucht jeder Dienst seinen eigenen Proxy.

Einen Mittelweg zwischen Stateful-Paketfilter und ALG beschreitet das Socks-Protokoll ([2], RFC 1928, Abbildung 1b). Implementiert ist es zum Beispiel im Dante-Paket[1]. Mit der generischen Socks-Proxy-Technik behält die Firewall die Kontrolle über jede Applikation, sie trennt die Netze auf Transportebene und stellt den Clients einen festen Anfrage-Port bereit (meist 1080).

Im Socks-Request teilt der Client dem Proxy den gewünschten Zielserver und Dienst mit (etwa HTTP, SMTP oder FTP). Der Socks-Proxy (auch Socks-Server genannt) authentifiziert den Client und autorisiert seinen Zugriff, baut stellvertretend die Verbindung zum Zielserver auf und reicht alle Sende- und Empfangsdaten durch.

Dazwischenschieben

Üblicherweise müssen die Client-Applikationen Socks-Support integriert haben, um den Proxy zu nutzen, da Socks in den Protokollablauf eingreift. Es funktioniert aber auch mit einem Wrapper, der mit »LD_PRELOAD«-Technik in fertig kompilierte Programme die Socks-Unterstützung nachträglich einfügt. Der Wrapper implementiert dazu eine angepasste Socket-Bibliothek.

Der Kunstname Socks leitet sich von Socket ab, der ursprüngliche Arbeitsname lautete SOCK-et-S. Es existieren zwei Hauptversionen: Socks v4 und v5. Beide Protokolle schieben sich im OSI-Modell zwischen Transport- und Anwendungsschicht. Version 4 beschränkt sich darauf, Verbindungsanfragen zu verarbeiten, Proxy-Regeln umzusetzen und Anwendungsdaten weiterzureichen. Sie verzichtet auf jede Authentifizierung und funktioniert ausschließlich über TCP. Socks 5 ergänzt starke Authentifikationsmechanismen sowie den Umgang mit UDP.

Auf Umwegen

In einem typischen Socks-Szenario will der Client zum Beispiel den HTTP-Dienst eines Servers im externen Netz nutzen. Der Ablauf ist in Abbildung 2 dargestellt, das Datenformat in Abbildung 3 und der Inhalt der Felder in Tabelle 1. Zunächst öffnet der Client eine TCP-Verbindung zum Socks-Proxy, per Default auf Port 1080. Im Negotiation-Paket schlägt er einige Authentifikationsmethoden vor; deren Anzahl steht in »NMETHODS«, die Methoden im Feld »METHODS«.

Akzeptiert der Proxy diese Anfrage (Schritt 2 in Abbildung 2), dann teilt er dem Client per Server-Negotiation-Paket die gewünschte Authentifizierungsmethode mit (»METHODS« mit genau einem Eintrag). Anschließend authentifiziert sich der Client (Schritt 3). Der genaue Ablauf in diesem Schritt hängt von der gewählten Methode ab.

Der Client teilt danach dem Proxy in einer Request-Nachricht mit, welchen Dienst er in Anspruch nehmen will (die Zieladresse in »DST.ADDR« und den Zielport in »DST.PORT«). Der Socks-Proxy evaluiert diese Anfrage anhand der Identität des Clients sowie der Zieladresse, dabei berücksichtigt er Firewall-typisch eine Zugriffskontrollliste. Bei verbotenen Zugriffen bricht der Socks-Proxy die Verbindung zum Client ab. Andernfalls antwortet er mit einem oder mehreren Server-Reply-Paketen.

Socks-Anfragen und -Antworten können Adressen verschiedenen Typs enthalten. Das Protokoll erlaubt IPv4- und IPv6-Nummern ebenso wie Domain-Namen. Letztere befreien den Client davon, DNS-Anfragen stellen zu müssen. Je nach Art des Client-Request, also abhängig vom »CMD«-Wert (siehe Abbildung 2 und Tabelle 1), sind die Adressenangaben in der Socks-Server-Antwort verschieden zu verstehen. In der Antwort auf ein »CONNECT« enthalten »BND.PORT« und »BND.ADDR« die Socks-Server-Adresse, von der aus der Proxy den Zielserver erreicht hat.

Die »BND.ADDR«-Adresse wird sich in der Regel von der Adresse des Socks-Servers unterscheiden, an die sich der Client gewandt hat. Diese Konstellation ist unter dem Namen Muli Homed Socks Server bekannt und typisch für eine Socks-Firewall, die zwei Netze verbindet. Nach einem erfolgreichen Connect-Kommando kommunizieren Client und Zielserver transparent über den Proxy; Socks leitet alle Daten weiter.

Abbildung 1a: Ist sie als Application Level Gateway implementiert, trennt die Firewall internes und externes Netz auf Applikationsebene. Allerdings braucht sie für jedes Protokoll einen eigenen Proxy.

Abbildung 1a: Ist sie als Application Level Gateway implementiert, trennt die Firewall internes und externes Netz auf Applikationsebene. Allerdings braucht sie für jedes Protokoll einen eigenen Proxy.

Abbildung 1b: Anders als ein ALG arbeitet Socks als generischer Proxy. Er nimmt auf Port 1080 Verbindungen für beliebige Applikationsprotokolle entgegen, authentifiziert den Client und autorisiert den Transfer.

Abbildung 1b: Anders als ein ALG arbeitet Socks als generischer Proxy. Er nimmt auf Port 1080 Verbindungen für beliebige Applikationsprotokolle entgegen, authentifiziert den Client und autorisiert den Transfer.

Verkehrte Welt

Einen »BIND«-Request setzt der Client ab, wenn er selbst eine Verbindung vom Zielserver erwartet. Diese verdrehte Konstellation ist zum Beispiel beim aktiven Modus des FTP-Protokolls üblich. Bei FTP erstellt zunächst in bester Client-Server-Tradition der Client eine Verbindung zum FTP-Server, die so genannte Kontrollverbindung. Für jede zu übermittelnde Datei öffnet aber der Server rückwärts zum Client eine eigene Datenverbindung. Der Client teilt dem Server vorher mit, an welche Adresse und welchen Port er sich wenden soll. Diese Information sendet er über den Kontrollkanal.

Socks ist in der Lage, diese Verbindungen ins interne Netz kontrolliert zu gestatten. Zunächst startet der Client mit einem normalen Connect-Request den Kontrollkanal zum Server. Danach bittet er den Socks-Proxy in einer zweiten Verbindung mit einem Bind-Request darum, einen Port für die hereinkommende Datenverbindung zu öffnen.

Der Proxy antwortet mit zwei Rückmeldungen. In die erste trägt er ein, auf welchem Port und unter welcher Adresse der Socks-Server auf die Verbindung von außen wartet. Das zweite Reply-Paket sendet der Proxy erst, wenn der Zielrechner eine Verbindung zu ihm geöffnet hat. Der Proxy trägt in dieses Antwortpaket die Quelladresse und den Quellport ein, von dem aus sich der Zielrechner mit ihm verbunden hat. Anschließend leitet er alle Daten vom externen Server zum internen Client weiter.

UDP-Relay

Soll Socks als UDP-Proxy arbeiten, dann muss sich der Client zunächst ebenfalls per TCP am Proxy melden und authentifizieren (Abbildung 4). Er verwendet als »CMD« den dritten in Tabelle 1 genannten Wert: »UDP Associate«. Da er die Pakete später tatsächlich per UDP versenden wird, muss er dem Proxy mitteilen, von wo diese Pakete kommen werden. Dazu trägt der Client sich selbst in die Felder »DST.ADDR« und »DST.PORT« als künftigen Absender ein.

Der Proxy öffnet dann einen internen UDP-Relay-Port, über den der Client Pakete nach außen senden darf. Wo sich dieses Relay befindet, erfährt der Client aus der Antwort des Servers auf die UDP-Associate-Frage nach »BND.PORT« und »BND.ADDR«. Dorthin sendet der Client UDP-Pakete, die ins externe Netz gehen sollen. Seine UDP-Pakete verpackt er in einen UDP-Request (Abbildung 3 unten). Das UDP-Relay bleib so lange aktiv, wie der Client die authentifizierte TCP-Verbindung offen hält.

Die gewählte Authentifikationsmethode kann – trotz ihres Namens – auch für Vertraulichkeit und Integrität auf dem Weg zwischen Client und Proxy sorgen. Dazu verkapselt sie die Daten eventuell. Beispielsweise bei SSL/TLS: Nach der Client-Server-Negotiation authentifiziert sich der Client über SSL/TLS. Alle weiteren Daten laufen ebenfalls SSL/TLS-gesichert, Vertraulichkeit und Integrität sind sichergestellt. Damit sind auch mobile, drahtlose Geräte sicher am Socks-Proxy zu betreiben.

Abbildung 2: Beim Verbindungsaufbau über Socks 5 beginnt der Client mit einem Negotiation-Paket an den Socks-Proxy (1). Er authentifiziert sich (3), der Proxy stellt die Verbindung mit dem Zielserver her (6) und leitet dann die Daten zwischen Client und Server weiter (8).

Abbildung 2: Beim Verbindungsaufbau über Socks 5 beginnt der Client mit einem Negotiation-Paket an den Socks-Proxy (1). Er authentifiziert sich (3), der Proxy stellt die Verbindung mit dem Zielserver her (6) und leitet dann die Daten zwischen Client und Server weiter (8).

Abbildung 3: Die Socks-Version 5 arbeitet mit den fünf Paketarten Client Negotiation, Server Negotiation, Client Request, Server Reply und UDP-Request. Die ersten vier benutzt es über TCP, nur der fünfte Pakettyp arbeitet mit UDP. In den Feldern sind ihr Name und ihre Größe angegeben. Tabelle 1 beschreibt den Inhalt.

Abbildung 3: Die Socks-Version 5 arbeitet mit den fünf Paketarten Client Negotiation, Server Negotiation, Client Request, Server Reply und UDP-Request. Die ersten vier benutzt es über TCP, nur der fünfte Pakettyp arbeitet mit UDP. In den Feldern sind ihr Name und ihre Größe angegeben. Tabelle 1 beschreibt den Inhalt.

Abbildung 4: Für den UDP-Paketversand verbindet sich der Client zunächst über TCP mit dem Socks-Proxy. Als Client Request (4) setzt er ein UDP-Associate-Kommando ab, in dem er dem Proxy mitteilt, von wo aus er UDP-Pakete senden wird. Der Proxy antwortet mit einem Relay-Port (hier Y genannt).

Abbildung 4: Für den UDP-Paketversand verbindet sich der Client zunächst über TCP mit dem Socks-Proxy. Als Client Request (4) setzt er ein UDP-Associate-Kommando ab, in dem er dem Proxy mitteilt, von wo aus er UDP-Pakete senden wird. Der Proxy antwortet mit einem Relay-Port (hier Y genannt).

Listing 1:
Socks-Server

01 logoutput: syslog
02 #logoutput: stdout
03 
04 internal: eth0 port = 1080
05 external: eth1
06 #internal: 10.0.0.11 port = 1080
07 #external: 192.168.23.1
08 
09 method: username
10 #method: none
11 #method: rfc931
12 #method: pam
13 
14 user.privileged: proxy
15 user.notprivileged: nobody
16 
17 client pass {
18   from: 10.0.0.3/0 port 1-65535 to: 0.0.0.0/0
19 }
20 
21 client block {
22   from: 0.0.0.0/0 to: 0.0.0.0/0
23   log: connect error
24 }
25 
26 block {
27   from: 0.0.0.0/0 to: 10.0.0.11/0
28   log: connect error
29 }
30 
31 pass {
32   from: 10.0.0.3/0 to: 10.0.0.10/0
33   user: aleitner tkuhn
34 }
35 
36 block {
37   from: 0.0.0.0/0 to: 0.0.0.0/0
38   log: connect error
39 }

Dante

Die BSD-lizenzierte Socks-Client- und -Server-Implementierung Dante[1] unterstützt Socks 4 und 5 sowie das weniger gebräuchliche MSproxy. Ende Januar 2005 ist Version 1.1.15 erschienen. Dante wird von der norwegischen Beratungsfirma Inferno Nettverk A/S entwickelt, die zusätzlich als kostenpflichtige Module Bandbreitenkontrolle und Port- sowie Umleitungsüberwachung anbietet. Für die meisten Aufgaben ist die freie Version völlig ausreichend. Sie arbeitet auch als HTTP-Proxy, implementiert Authentifizierung mit Benutzernamen und Passwort oder per Pluggable Authentication Module und erlaubt Interface-Namen in der Konfigurationsdatei, um DHCP zu unterstützen.

Nach der Installation mit dem üblichen »configure && make && make install« landet die Socks-Server-Konfigurationsdatei in »/etc/sockd.conf« (Listing 1). In Zeile 1 legt eine »logoutput«-Anweisung fest, wohin Dante protokollieren soll (Syslog oder Stdout). Die interne und die externe Netzwerkschnittstelle sind per Interface-Namen angegeben (Zeilen 4 und 5). Das hilft bei DHCP-konfigurierten Rechnern; die Zeilen 6 und 7 zeigen, dass andernfalls auch IP-Adressen genügen. Wichtig: Die interne Schnittstelle benötigt eine Portnummer.

Als Authentifikationsmethoden unterstützt Dante neben der Benutzername-Passwort-Variante (Zeile 9) auch das Ident-Verfahren nach RFC 931 (Zeile 11) und PAM. Je nach Methode braucht der Socks-Server passende Benutzerrechte. Bei Zugriffen auf die Passwortdatei wählt er den privilegierten Benutzer (laut Zeile 14: »proxy«) und begnügt sich bei normalen Aufgaben mit »nobody« (Zeile 15). Im Praxiseinsatz empfiehlt sich ein eigenes Benutzerkonto für die Socks-Software. Ein Chroot-Käfig hält sie von Systemdateien fern und verpasst ihr auf Wunsch eine eigene Passwortdatei.

Gut gefiltert

Filterregeln in der Konfigurationsdatei bestimmen, welcher Client Zugriff auf den Socks-Proxy erhält und wohin er sich verbinden darf. Die Dante-Software arbeitet Filterregeln der Reihe nach ab. Zuerst wertet sie die Regeln mit dem Präfix »client« aus und ermittelt jene Rechner, die auf den Socks-Server zugreifen dürfen (Zeilen 17 bis 24). Die »pass«-Regeln erlauben Zugriffe, während »block« sie abwehrt. Die Zeilen 17 bis 19 gestatten dem Rechner mit der IP-Adresse 10.0.0.3 jeden Zugriff, die Zeilen 21 bis 24 verweigern ihn allen anderen Rechnern. Diese Regeln gelten auf TCP/IP-Ebene, sie haben noch nichts mit dem Socks-Protokoll zu tun.

Tabelle 1:
Paket-Tags

 

Tag

Inhalt/Beschreibung

ATYP

Adressentyp: 0x01: IPv4-Adresse

0x02: Domain-Namen

0x03: IPv6-Adresse

BND.ADDR

Socks-Proxy-Quelladresse für die Datenübertragung zum
Server

BND.PORT

Socks-Proxy-Quellport für die Datenübertragung zum
Server

CMD

Übertragungsarten:

0x01 CONNECT

0x02 BIND

0x03 UDP Associate

DST.ADDR

Gewünschte Zieladresse (Server)

DST.PORT

Gewünschter Zielport (auf dem Server)

FRAG

Aktuelle Fragmentnummer (für UDP-Pakete)

METHODS

Auswahlfeld für Authentifizierungsmethoden:

0x00: Keine Authentifikation

0x01: GSSAPI

0x02: Benutzername und Passwort

0x03 bis 0x7E: Von der IANA definiert

0x80 bis 0xFE: Reserviert für private Methoden (nur lokal
genutzt)

0xFF: Der Proxy hat keine vom Client angebotene Methode
akzeptiert

NMETHODS

Anzahl der Einträge im »METHODS«-Feld

REP

Antwortfeld (Reply):

0x00: Erfolgreich

0x01: Allgemeiner Socks-Proxy-Fehler

0x02: Verbindung laut Regelsatz nicht erlaubt

0x03: Netzwerk nicht erreichbar

0x04: Rechner nicht erreichbar

0x05: Verbindungsaufbau abgelehnt

0x06: Zeitüberschreitung (TTL abgelaufen)

0x07: Socks-Kommando nicht unterstützt

0x08: Adresstyp nicht unterstützt

0x09 bis 0xFF: Nicht definiert

RSV

Reserviert

VER

Protokollversion

Abbildung 5: Ein Webbrowser benutzt Socks 5, um sich über den Proxy mit dem Server zu verbinden. Der Netzwerkmonitor Ethereal zerlegt diese Kommunikation in ihre Einzelteile.

Abbildung 5: Ein Webbrowser benutzt Socks 5, um sich über den Proxy mit dem Server zu verbinden. Der Netzwerkmonitor Ethereal zerlegt diese Kommunikation in ihre Einzelteile.

Erst die zweite Filterklasse betrachtet den Inhalt der Client-Requests. Diese Regeln bestimmen, welche Anfragen der Proxy erlaubt. In Listing 1 verwirft die »block«-Anweisung in Zeile 26 bis 29 alle Anfragen von Rechnern, die auf 10.0.0.11 zugreifen wollen. Die beiden User »aleitner« und »tkuhn« dürfen von 10.0.0.3 aus Verbindungen zu 10.0.0.10 herstellen (Zeilen 31 bis 34). Alle anderen Anfragen ignoriert der Proxy.

Der Aufruf »/sbin/sockd -d« startet den Socks im Debug-Modus. Dabei schreibt der Proxy wichtige Informationen auf »logoutput«. Abbildung 5 zeigt eine typische Socks-Kommunikation im Netzwerksniffer Ethereal: Das Programm verfolgt detailliert die Kommunikation. Als Testclient eignet sich der Mozilla-Browser. Abbildung 6 zeigt die passende Konfiguration für »Preferences | Advanced | Proxies«: Unter »Manual proxy configuration« ist der Socks-Server auf 10.0.0.11 und Port 1080 festgelegt.

Lehnt der Socks-Proxy eine Verbindung wegen fehlender oder falscher Zugriffsrechte ab, bemerkt der Anwender oft nur die Folgen, ohne etwas über die Ursachen zu erfahren. Beispielsweise gibt der Mozilla-Browser bei Fehlern im zweiten Teil der Filterregeln lediglich die Meldung »The document contains no data« aus, aber keinen Hinweis darauf, dass der Proxy daran schuld ist. Dann hilft ein Blick in die Proxy-Logfiles, bei Syslog-Ausgabe zum Beispiel »/var/log/messages«.

Abbildung 6: Die Konfiguration des Mozilla-Browsers für Socks 5 versteckt sich unter »Preferences | Advanced | Proxies«. Socks nutzt per Default Port 1080.

Abbildung 6: Die Konfiguration des Mozilla-Browsers für Socks 5 versteckt sich unter »Preferences | Advanced | Proxies«. Socks nutzt per Default Port 1080.

Neben dem Socks-Server enthält das Dante-Paket ein einfaches Wrapper-Skript mit Namen »socksify«. Es stattet die meisten fertig kompilierten Netzwerk-Clientprogramme (etwa für SMTP, FTP, NTP, DNS oder IRQ) nachträglich mit Socks-Fähigkeiten aus:

./socksify -c ftp 10.0.0.10

Zusammen mit einer geeigneten Konfigurationsdatei »/etc/socks.conf« bringt Socksify das »ftp«-Clientprogramm dazu, den Socks-Proxy zu benutzen – ohne es neu übersetzen zu müssen. Die Einstellung

route {
  from: 0.0.0.0/0 to: 0.0.0.0/0 
  via: 10.0.0.11 port = 1080
  proxyprotocol: socks_v5
}

sorgt dafür, dass Socksify als Proxy-Protokoll Socks v5 benutzt, um über den Rechner 10.0.0.11 und Port 1080 eine gesicherte Verbindung herzustellen.

In einer Hand

Die Socks-Technologie erlaubt einfaches und transparentes Sicherheitsmanagement. Sie stattet vernetzte Anwendungen mit Authentifizierung und Verschlüsselung aus. Im Unterschied zu vielen anderen Protokollen trennt Socks die Verbindungs- und die Benutzerprüfung nicht und erlaubt der Firewall dadurch eine vollständige Kontrolle des Datenverkehrs. (fjl)

Infos

[1] Dante: [http://www.inet.no/dante/]

[2] RFC 1928, SOCKS Protocol Version 5: [http://www.ietf.org/rfc/rfc1928.txt]

[3] RFC 1929, Username/Password Authentication for SOCKS V5: [http://www.ietf.org/rfc/rfc1929.txt]

[4] RFC 1961, GSS-API Authentication Method for SOCKS Version 5: [http://www.ietf.org/rfc/rfc1961.txt]

Der Autor

Thomas Kuhn ist wissenschaftlicher Mitarbeiter am Lehrstuhl für System- und Softwaretechnik am Institut für Informatik der Technischen Universität München und beschäftigt sich mit der Entwicklung sicherer Software. Zuvor war er mehrere Jahre als Sicherheitsberater tätig.

LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben