LUG Erding

Fehlersuche bei Netzwerkproblemen


Dirk Geschke

LUG-Erding

telnet

Die meisten wichtigen Applikationen verwenden das TCP-Protokoll. Daher kann ein telnet-Client sehr gut dazu verwendet werden um zu testen ob ein Dienst an der Gegenstelle antwortet und was geantwortet wird oder ob er nicht antwortet.

Die meisten Serverdienste verwenden Klartext und oft wird eine Begrüßungszeile übermittelt, wie z.B. der Mailserver von GMX:

$ telnet mx0.gmx.de smtp
Trying 213.165.64.100...
Connected to mx0.gmx.de.
Escape character is '^]'.
220 {mx059} GMX Mailservices ESMTP

Es gibt natürlich mehrere Möglichkeiten was passieren kann:

Der Server antwortet, eine Verbindung kann hergestellt werden.

Zu erkennen ist dies an der Zeile:

Connected to mx0.gmx.de.

Das Problem liegt nicht an TCP, es muß also beim höheren Protokoll liegen.

Die Verbindung wird via RESET abgelehnt.

Zu erkennen ist dies z.B. an:

telnet: Unable to connect to remote host: Connection refused

Dies läßt vermuten, daß bei der Gegenstelle kein Serverdienst auf diesem Port horcht. Es kann natürlich auch die Folge einer Firewall sein, die den Zugriff auf diesen Dienst unterbindet

Die Verbindung läuft in einen Timeout

Dies dauert in der Regel ein paar Minuten:

telnet: Unable to connect to remote host: Connection timed out

Die Gegenseite verwendet vermutlich einen Paketfilter der die Verbindungspakete einfach verwirft.

Der Server antwortet und schließt sofort die Verbindung

Dies ist leicht mit telnet zu erkennen:

majestix:~$ telnet mx0.gmx.de 25
Trying 213.165.64.100...
Connected to mx0.gmx.de.
Escape character is '^]'.
Connection closed by foreign host.

Der Server verwendet eine ACL-Liste, die Absende-IP-Adresse wird aktiv von der Applikation geblockt. In diesem Fall ist des GMX, die nehmen von dynamisch eingewählten ADSL-Clients keine E-Mails entgegen. T-Online ist noch schlimmer, die liefern an dieser Stelle noch nicht einmal Connected.

Aus diesem letzten Beispiel kann man aber noch mehr erkennen:

majestix:~$ telnet mx0.gmx.de 25
Trying 213.165.64.100...

Die Namensauflösung funktioniert, mx0.gmx.de hat die IP-Adresse 213.165.64.100. Auch dies kann ein Hinweis auf ein Problem sein, nämlich wenn die Namensauflösung nicht funktioniert.

Es ist also schon erstaunlich was alles mit einem telnet-Programm herausgefunden werden kann.

Je nachdem in wieweit der Zugriff auf die Remote-Systeme erfolgreich ist, kann nun die Fehlersuche an geeigneter Stelle fortgesetzt werden.

ping

Ein sehr häufiges Problem ist, daß auf einen Timeout gestoßen wird. Dies kann mehrere Gründe haben, eventuell ist der Server nicht aktiv, d.h. er ist z.B. gerade wegen Wartungsarbeiten abgeschaltet.

In diesem Fall hilft ein ping sehr schnell weiter. Wenn die Gegenstelle anpingbar ist, dann kann zumindest schon einmal folgendes festgestellt werden:

In diesem Fall ist das ist schon die Halbe Miete.

Daß ein Server aktiv ist, heißt noch lange nicht, daß er am Netzwerk angeschlossen ist. Ein angeschlossener Server muß aber nicht unbedingt via Netzwerk ansprechbar sein.

Ist die Gegenstelle nicht erreichbar, d.h. die pings gehen alle verloren, so kann es daran liegen, daß die Gegenstelle auch diese einfach verworfen hat, z.B.:

majestix:~$ ping 83.241.131.138 -c 5
PING 83.241.131.138 (83.241.131.138): 56 data bytes

--- 83.241.131.138 ping statistics ---
5 packets transmitted, 0 packets received, 100% packet loss

In diesem Fall ist die Gegenstelle aktiv im Netzwerk, sie antwortet nur nicht auf ICMP Echo Requests. Dies kann hieran jedoch nicht erkannt werden.

Was aber auch passieren kann ist, daß einige Pakete nur verloren gehen (hier ein System in China):

majestix:~$ ping 61.172.194.154 -c 5
PING 61.172.194.154 (61.172.194.154): 56 data bytes
64 bytes from 61.172.194.154: icmp_seq=0 ttl=242 time=940.8 ms
64 bytes from 61.172.194.154: icmp_seq=1 ttl=242 time=938.9 ms
64 bytes from 61.172.194.154: icmp_seq=2 ttl=242 time=947.7 ms
64 bytes from 61.172.194.154: icmp_seq=4 ttl=242 time=945.4 ms

--- 61.172.194.154 ping statistics ---
5 packets transmitted, 4 packets received, 20% packet loss
round-trip min/avg/max = 938.9/943.2/947.7 ms

Da die Gegenstelle in diesem Fall in China liegt ist das nicht weiter dramatisch. Einzelne IP-Pakete dürfen durchaus verloren gehen. Es kann aber ein Indiz dafür sein, daß ein Netzwerkproblem auf dem Weg vorliegt.

Interessant wird es wenn größere Pakete ins Spiel kommen:

majestix# ping -s 4000 -c 3 61.172.194.154
PING 61.172.194.154 (61.172.194.154): 4000 data bytes

--- 61.172.194.154 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss

In diesem Fall sind die 4000 Bytes deutlich mehr als die MTU von Ethernet, d.h. die Pakete müssen fragmentiert werden. Einige Router scheinen aber IP-Fragemente zu verwerfen, wie hier ein Router in China.

Daß es ein Router in China ist kann mit traceroute herausgefunden werden, auch hier können verschiedene Paketgrößen verwendet werden.

Ein möglicher Grund hierfür kann ein Paketfilter in Kombination mit Load-Balancing sein. In einem solchen Fall laufen die einzelnen Fragmente über verschiedene Router und keiner kann das komplette Paket sehen. In solchen Fällen verwerfen die meisten Filter solche Fragmente.

traceroute

Traceroute bietet die Möglichkeit durch schrittweises Erhöhen der TTL und protokollieren der Time Exceeded ICMP-Meldungen den Weg der IP- Pakete zu ermitteln. Jeder Router auf dem Weg zum Ziel muß ein ICMP Time-Exceeded generieren wenn die TTL den Wert Null erreicht.

D.h. gestartet wird mit einer TTL von 1, der erste Router - sofern er nicht das Ziel ist - muß die TTL um 1 reduzieren. Damit erreicht die TTL den Wert 0, das Paket wird verworfen und ein ICMP Time Exceeded wird generiert. Dieses ICMP-Paket hat als Absendeadresse die IP-Adresse des Routers.

Traceroute reagiert darauf, protokolliert die IP-Adresse und erhöht die TTL um 1 auf 2. Damit wird der nächste Router angesprochen.

Linux verwendet per default 3 UDP Pakete mit den Zielports 33434, 33435 und 33436. Wird das Zielsystem erreicht, so wird dort mit Sicherheit für mindestens ein Port ein ICMP Port unreachable gesendet.

Mit der Option -I werden ICMP Echo Requests anstelle von UDP-Paketen versendet.

Es gibt auch eine TCP-Variante von traceroute, diese ist aber per default nicht unter Linux zu finden.

Welches Verfahren auch verwendet wird, es kann auf einfache Weise der Weg zum Server gefunden werden. Bei Netzwerkproblemen kann dann auch gesehen werden bei welchem Router der Weg aufhört.

Z.B. liefert:

majestix:~$ traceroute -n 83.241.131.138
traceroute to 83.241.131.138 (83.241.131.138), 30 hops max, 38 byte packets
 1  192.168.178.1  2.066 ms  2.581 ms  0.745 ms
 2  217.0.116.77  54.463 ms  49.676 ms  57.637 ms
 3  217.0.69.134  55.430 ms  57.597 ms  55.643 ms
 4  217.239.38.38  165.354 ms  89.584 ms  87.638 ms
 5  62.153.203.154  95.354 ms  93.631 ms  90.569 ms
 6  62.181.249.89  98.342 ms  92.632 ms  91.556 ms
 7  62.181.249.82  101.355 ms  92.596 ms  90.635 ms
 8  217.13.227.46  97.372 ms  91.585 ms  89.629 ms
 9  217.13.227.50  97.364 ms  93.638 ms  89.571 ms
10  217.13.227.54  99.373 ms  91.593 ms  89.631 ms
11  83.241.255.137  97.331 ms  93.577 ms  89.652 ms
12  83.241.255.146  97.348 ms  91.602 ms  89.637 ms
13  83.241.255.142  99.363 ms  93.592 ms  91.641 ms
14  * * *
15  * * *
16  * usw.

Da Hop 13 sehr nahe am Ziel ist, das ist vermutlich die andere Seite des letzten Routers, liegt die Vermutung nahe, daß hier auch die Pakete verworfen werden (gedropped).

Wenn der letzte verwertbare Eintrag nicht in Relation zum Zielsystem gesetzt werden kann, so liegt ein Netzwerkproblem eines ISP's nahe.

Manchmal tauchen zwei Router im Wechsel auf, dann ist es klar, daß ein Provider einen Routing-Loop hat. Da hilft es nur den ISP zu verständigen.

Es ist übrigens nicht unüblich, daß zwischendurch ein paar Hops nur mit Sternen aufgeführt werden und danach geht es regulär weiter. Dafür kann es mehrere Ursachen geben:

  Da diese eigentlich nicht gerouted werden dürfen verwirft ein   Router auf dem Weg diese Adressen.

Außer für ICMP Meldungen tauchen die Router-IP-Adressen in der direkten Verbindung nicht auf. Daher kann ein ISP aufgrund der Knappheit von IP-Adressen durchaus auf private zurückgreifen. Diese werden mitunter auch angezeigt, das hängt aber vom Verhalten der Router auf dem Weg ab.

Z.B. hier:

# traceroute -n 212.14.67.242 
traceroute to 212.14.67.242, 40 hops max, 40 byte packets
 1  196.15.171.193  2.177 ms  2.133 ms  2.092 ms
 2  172.21.225.1  30.250 ms  31.832 ms  33.201 ms
 3  192.168.69.1  31.149 ms  30.887 ms  32.086 ms
 4  4.3.2.66  32.128 ms 4.3.2.65  31.587 ms 4.3.2.66  31.773 ms
 5  196.25.56.133  32.301 ms  31.373 ms  32.089 ms
....

Die Router 2 und 3 haben offensichtlich RFC 1918 Adressen. Auf dem Rückweg werden diese auch folglich verworfen:

# traceroute -n 196.46.141.146 
traceroute to 196.46.141.146, 40 hops max, 40 byte packets
....
13  4.3.2.18  201.279 ms 4.3.2.17  219.297 ms 4.3.2.18  197.848 ms
14  * * *
15  * * *
16  * * *
17  196.46.141.146  237.887 ms  242.824 ms  242.614 ms

Der Weg den traceroute auflistet ist natürlich nicht unbedingt der korrekte, denn der Weg darf sich durchaus ändern. Aber die Erfahrung lehrt, daß dies eher selten der Fall ist.

Was jedoch häufiger vorkommen kann ist etwas wie bei Hop 4 bzw. Hop 13, da scheinen 2 Router load-balancing zu betreiben. Einmal geht das Paket über den ersten Router, das andere mal über den zweiten. Es scheinen in beiden Fällen die gleichen Router zu sein, allerdings das jeweils andere Interface.

ARP

Ist die Gegenstelle im gleichen Subnetz, so kann es durchaus lohnenswert sein sich die ARP-Tabelle anzusehen ob es einen korrekten Eintrag gibt. Dies geschieht mit

majestix:~$ /usr/sbin/arp -an
? (192.168.178.1) at 00:04:0E:21:0A:EB [ether] on eth1

Wenn nun ein Computer via ping nicht erreicht werden kann, z.B. weil er die ICMP Echo Requests einfach verwirft, so gibt einem arp doch einen Hinweis:

majestix:~$ ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes

--- 192.168.1.1 ping statistics ---
4 packets transmitted, 0 packets received, 100% packet loss

majestix:~$ /usr/sbin/arp -an
? (192.168.1.1) at <incomplete> on eth0
? (192.168.178.1) at 00:04:0E:21:0A:EB [ether] on eth1

Hier kann nun leicht erkannt werden, daß auch der ARP-Eintrag fehlt, d.h. die Gegenstelle antwortet auch nicht auf ARP-Requests. Das ist dann meist eindeutig: Die Gegenstelle ist offline oder falsch verkabelt.

Filterregeln greifen gewöhnlich nur auf IP-Ebene, nicht auf Ethernet-Ebene. Es ist sehr selten, daß hier gefiltert wird.

Ein mögliches Problem kann durch die Verwendung falscher Netzwerkmasken entstehen. ARP-Requests werden nur gesendet, wenn die Gegenstelle im gleichen Subnetz liegt!

Da ich ein Class-C Netz verwende:

majestix:~$ /sbin/ifconfig eth0 | head -2
eth0      Link encap:Ethernet  HWaddr 00:E0:4C:00:82:9F  
          inet addr:192.168.1.5  Bcast:192.168.1.255  Mask:255.255.255.0

wird z.B. für 192.168.2.1 gar kein ARP-Request generiert:

majestix:~$ ping 192.168.2.1
PING 192.168.2.1 (192.168.2.1): 56 data bytes

--- 192.168.2.1 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss

Folglich taucht die fehlende MAC-Adresse auch nicht in der ARP-Tabelle auf:

majestix:~$ /usr/sbin/arp -an
? (192.168.1.1) at <incomplete> on eth0
? (192.168.178.1) at 00:04:0E:21:0A:EB [ether] on eth1

Es ist klar, in diesem Fall sagt die Routing-Tabelle, daß dies über die default-Route versendet werden muß, Gateway 0.0.0.0 heißt übrigens, daß das Ziel direkt erreicht werden kann:

majestix:~$ netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
192.168.178.0   0.0.0.0         255.255.255.0   U         0 0          0 eth1
192.168.1.0     0.0.0.0         255.255.255.0   U         0 0          0 eth0
0.0.0.0         192.168.178.1   0.0.0.0         UG        0 0          0 eth1

Folglich existiert nur ein ARP-Eintrag für das Gateway 192.168.178.1.

Der umgekehrte Fall gilt übrigens auch, wenn die Netzmaske zu groß ist, dann wird versucht das Ziel direkt zu erreichen, d.h. es wird ein ARP-Request im lokalen Netzwerksegment generiert. Das Ziel steht aber hinter einem Router, d.h. es sieht weder den ARP-Request noch würde eine Antwort darauf Sinn machen. Auch hier kann mitunter etwas länger gesucht werden bis der Fehler gefunden wird.

Langsame Verbindungen

Das ist immer ein problematisches Thema, für langsame Verbindungen kann es viele Gründe geben, manche sind schlichtweg von der Leitung selber bestimmt:

Leitungsengpass

Leitungsengpässe auf dem Weg können leicht erahnt werden wenn es nur einen oder wenige Server betrifft. Den theoretischen Durchsatz kann mit Tools wie z.B. bing gemessen werden. Dieses Kommando mißt den Durchsatz zwischen 2 Routern auf der Strecke, diese muß man natürlich selber angeben und sollten auch auf dem Weg liegen, siehe traceroute.

Dazu werden Pakete an den ersten Router analog zu ping gesendet und die Zeit gemessen. Danach werden Pakete zu dem anderen Router gesendet, hier wird ebenfalls die Zeit gemessen. Aus der Differenz ergibt sich dann theoretisch die Bandbreite des Zwischennetzes. Zu finden ist dieses Tool gelegentlich, das Tool ist schon älter, der Autor hat die ursprüngliche Website verlassen, unter http://fgouget.free.fr/bing/index-en.shtml

Ferner gibt es noch

Schwieriger zu analysieren ist der nächste Punkt.

Leitung ist zu

Hiermit ist der eigene Internetzugang gemeint. Das ist nicht leicht zu erkennen, unter OpenBSD wäre das relativ leicht durch z.B.

netstat -isbn -I fxp0 10

zu ermitteln. Dieses Kommando gibt alle 10 Sekunden die übertragenen bzw. empfangenen Bytes aus. Wird der Wert durch 10 und 1024 dividiert, so wird direkt der Durchsatz in kByte/s erhalten. Leider hat Linux diese Möglichkeit (noch) nicht.

Es gibt aber auch hilfreiche andere Tools um diesen Durchsatz zu bestimmen und sogar um festzustellen welche Verbindungen die meiste Last verursachen. Dazu gehören Programme wie

Argus dient eigentlich der Überwachung eines Netzwerkes nach Traffic, für den Heimgebrauch ist es also weniger geeignet.

EtherApe ist ein nettes graphisches Tool. Es zeigt den Traffic durch Keile an und die Gegenstelle je nach Traffic als unterschiedlich große Kreise dar.

Die anderen 3 Tools sind aber für den aktuellen Gebrauch noch am Besten geeignet, sie sind gewöhnlich curses basiert, d.h. sie laufen auch z.B. in der Konsole.

Ein anderes nützliches Tool ist auch netstat -an, dies zeigt z.B. an wieviele Daten noch in der Sende- oder Empfangs-Queue sind. Dies kann auch ein Indiz sein, daß ein Prozeß die Daten nicht schnell genug liest oder verarbeitet. Vielleicht hat das System eine hohe Last? Allerdings sollte das eher bemerkt werden bevor im Netzwerkbereich die Suche angefangen wird.

DNS-Probleme

Dies ist auch ein guter Kandidat, wenn auch manchmal schwierig zu lokalisieren. Wenn bekannt ist worauf geachtet werden muß ist es durchaus leicht zu finden.

Wenn DNS nicht funktioniert, dann können die Dienste via IP-Adressen verwendet werden jedoch nicht mit dem DNS-Namen. Ein einfacher DNS-Test kann auch mittels nslookup oder dig durchgeführt werden.

Der Nameserver, der verwendet werden soll steht in der Datei

/etc/resolv.conf

Hier können nun durchaus mehrere Nameserver eingetragen sein. Wenn der erste nicht funktioniert, dann wird der zweite verwendet.

Und genau hier liegen die meisten Probleme: Die Namensauflösung erfolgt normalweise via UDP, d.h. es gibt keinen Verbindungsaufbau wie bei TCP oder ein Reset wenn die Gegenstelle nicht antwortet. Manchmal funktioniert der Nameserver auch nur halb, d.h. er nimmt Pakete entgegen, er antwortet aber nicht.

Daher wird hier gewöhnlich mit einem Timeout reagiert, d.h. erfolgt nach typischerweise 20-30 Sekunden keine Antwort, so wird der nächste Server gefragt. Diese Verzögerung ist typisch für Probleme dieser Art.

Aber damit dies nicht leicht zu finden ist wird oft der nscd, der Name Service Caching Daemon, eingesetzt. Dieser speichert antworten von Nameservern eine gewisse Zeit und soll dadurch die Namensauflösung zum Einen schneller machen bzw. vermeiden und zum Anderen das Befragen der Nameserver reduzieren.

Jetzt ist klar, wo es hakt: Wenn nach 20-30 Sekunden der nächste Server befragt wird, so wird die Antwort gecached, ein erneuter Zugriff auf den gleichen Namen funktioniert nun ohne Verzögerung. Allerdings nur so lange bis der nscd den Eintrag verwirft.

Wenn dies alles im Hinterkopf verankert ist, dann lassen sich solche Probleme durchaus finden. Wichtig dabei ist nur, daß bekannt ist woran gedacht werden muß. Typisch sind diese Probleme auch beim Aufruf einer Website, hier sind mitunter verschiedene URL's von diversen Servern eingebettet. Bei Nameserverproblemen dauert es dann diese 20-30 Sekunden bis ein Teil aufgebaut wird und dann wieder bis der nächste Request aufgelöst werden kann.

Das ist übrigens bei der Verwendung von PAC-Dateien besonders spaßig. PAC steht für Proxy Autoconfiguration. Hier kann je nach Zieladresse entschieden werden welcher Proxy oder ob überhaupt einer verwendet werden soll. Dazu muß aber meistens erst der DNS-Name aufgelöst werden. Gelingt dies nicht wird die Anfrage an den default-Proxy weitergeleitet. Hier können dann mitunter wieder die berühmten 20-30 Sekunden Verzögerung beobachtet werden.

Einstellungen der Ethernetkarte

Bei langsamen Verbindungen ist es naheliegend, daß die Karte vielleicht nur mit 10 MBit/s statt mit 100 MBit/s arbeitet. Das kann unter Linux nicht gerade leicht herausgefunden werden. Falls es aber unterstützt wird funktioniert dies mit dem mii-tool:

dg4:~# /sbin/mii-tool 
eth0: negotiated 100baseTx-FD, link ok
SIOCGMIIPHY on 'eth1' failed: Operation not supported

Es kann leicht erkannt werden, daß die 2. Karte es nicht unterstützt.

Ansonsten kann es auch über die Kernel-Meldungen erhalten werden. Das kann im laufenden Betrieb via dmesg erfolgen. Allerdings ist der Kernelpuffer ein Ringpuffer, d.h. mit der Zeit werden die Meldungen überschrieben. Diese Meldungen erfolgen aber nur bei Änderungen des Link-Status oder Aktivieren der Karte:

eth0: VIA Rhine II at 0xdffff700, 00:a0:cc:d8:ac:17, IRQ 9.
eth0: MII PHY found at address 1, status 0x7869 advertising 05e1 Link 41e1.
eth0: link up, 100Mbps, full-duplex, lpa 0x41E1

In beiden Fällen kann erkennt werden, daß die Karte 100 MBit/s verwendet und im Full-Duplex Modus (FD) arbeitet.

Wenn die Netzwerkverbindung lokal eigentlich problemlos ist aber die Übertragungsrate einbricht sobald große Datenmengen transferiert werden, so könnte es an der Fehlkonfiguration liegen bei der eine Seite im Full-Duplex Modus arbeitet und die Gegenstelle im Half-Duplex Modus.

Dieser Fehler kann allerdings nur an den Input-Errors auf der Maschine die im Half-Duplex Modus läuft erkannt werden. Bei Full-Duplex wird davon ausgegangen, daß das Medium immer für das Senden frei ist, daher wird hier weder nach Kollisionen noch Fehlern geprüft.

Ein anderer Wert, auf den Acht gegeben werden sollte, ist im Half-Duplex Modus die Zahl der Kollisionen. Diese sollte nicht größer als ca. 10-20% sein.

Das Kommando um dies alles zu überwachen ist normalerweise, d.h. auf allen Unixsystemen, netstat -ni. Bei Linux werden diese Parameter aber auch bei ifconfig ausgegeben, was wohl daran liegt, daß beide Programme die gleichen Sourcen verwenden.

Höhere Protokolle

Dies ist jetzt eine kurze Übersicht wie mit einfachen Mitteln die Funktion einiger höherer Protokolle mit telnet getestet werden können.

smtp

Nach einem Connect erfolgt der Begrüßungstext. Danach wird vom Client entweder ein HELO (RFC 822, Simple Mail Transfer Protocol - SMTP) oder das neuere EHLO (RFC 1870, Extended SMTP) zusammen mit der Domain des Senders erwartet. EHLO hat den Vorteil, daß die implementierten Features der Gegenstelle aufgelistet werden. Dies wird auch benötigt, wenn SMTP-Authentisierung oder TLS (Transport Layer Security) verwendet werden sollen.

Der Server verwendet Statuscodes als erstes und dann erst den Text, z.B.:

220 {mx036} GMX Mailservices ESMTP

Die Domain wird eigentlich von keinem Mailserver überwacht, wichtig ist nur, daß der Server darauf korrekt antwortet. Bei EHLO antwortet der Server mit einer Liste der unterstützten Optionen, falls statt dessen eine Fehlermeldung kommt, dann spricht der Mailserver kein extended SMTP. Auch das kann gelegentlich die Ursache für ein Problem sein.

Diese Optionen sind für das Debuggen meist nicht notwendig oder hilfreich, daher reicht oft erst einmal ein simples HELO domainname, es sei denn ein explizites Features beim Mailversand wird verlangt.

Danach kann mit MAIL FROM: Sender@domainname der Absender festgelegt werden. Als nächstes können der oder die Empfänger angegeben werden. Dies erfolgt mit RCPT TO: Recipient@was.auch.immer, für jeden Empfänger eine eigene Zeile.

Die Antwort des Servers auf diese Zeilen ist besonders wichtig, gibt sie doch oft Aufschluß über das, was vorgeht. Die Statuscodes sind das, worauf andere Mailserver oder -clients reagieren. Der Text dient nur der Fehlersuche.

Sektion 4.2.1 von RFC 821 definiert die Statuscodes. Generell läßt sich festhalten:

Die MAIL FROM: und RCPT TO: Zeilen werden als Envelope der E-Mail bezeichnet. Diese Daten sind normalerweise nicht Bestandteil der E-Mail! Einige Mailserver setzen diese Werte aber als Kommentar in den Mail-Header, z.B.:

Envelope-To: dirk@geschke-online.de

und in der eigentlichen To-Zeile steht:

To: dirk@lug-erding.de

Letzteres ist übrigens das, was der Mailclient als Absender anzeigt. Das ist nicht notwendigerweise identisch mit dem Envelope!

Ab hier wird es für die Netzwerkfehlersuche uninteressant.

Weiter geht es mit DATA als einzelnes Wort, danach gibt es ein 354 vom Server zurück und es kann begonnen werden die E-Mail zu senden und zwar mit Mail-Header. Der Unterschied zwischen Header und Body der E-Mail ist lediglich eine Leerzeile.

Am Ende wird am Zeilenanfang einfach ein Punkt . eingegeben, die Mail ist versendet wenn ein positiver Rückgabewert vom Server erfolgt (2xx).

QUIT beendet die Verbindung.

Also z.B. bei einem Exim-Mailserver:

debix:/home/geschke# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 debix.physik.home ESMTP Exim 3.36 #1 Mon, 24 Oct 2005 20:45:40 +0200
HELO genua.de
250 debix.physik.home Hello root at localhost [127.0.0.1]
MAIL FROM: geschke@genua.de
250 <geschke@genua.de> is syntactically correct
RCPT TO: geschke@debix.physik.home
250 <geschke@debix.physik.home> verified
DATA
354 Enter message, ending with "." on a line by itself
Subject: Testmail
From: Der Guru 
To: Dirk

Just a test...
.
250 OK id=1EU7Kt-0000rb-00
quit
221 debix.physik.home closing connection

Dies resultiert in:

geschke@debix:~$ frm
Der Guru        Testmail

Es wird also nur der Mail-Header ausgwertet, nicht der Envelope!

Ein genauer Blick auf den Header dieser E-Mail zeigt:

Return-path: <geschke@genua.de>
Envelope-to: geschke@debix.physik.home
Received: from localhost
        ([127.0.0.1] helo=genua.de ident=root)
        by debix.physik.home with smtp (Exim 3.36 #1 (Debian))
        id 1EU7Kt-0000rb-00
        for <geschke@debix.physik.home>; Mon, 24 Oct 2005 20:46:47 +0200
Subject: Testmail
From: Der Guru
To: Dirk
Message-Id: <E1EU7Kt-0000rb-00@debix.physik.home>
Date: Mon, 24 Oct 2005 20:46:48 +0200

Interessant sind hier die Einträge die der Mailserver selber vornimmt:

Die einzigen Werte auf die wirklich Verlaß sind ist die Received-Zeile sowie die Message-Id. Die Received-Zeile enthält die Adresse von der die E-Mail an den Server zugestellt wurde und das Datum wann diese E-Mail empfangen wurde. Der ident-Eintrag besagt sogar welcher Benutzer diese Mail generierte. Dies funktioniert in der Regel aber nur bei localhost, die meisten Server im Internet unterbinden ident-Anfragen. Auf diese Zeilen ist deswegen Verlaß weil der eigene Mailserver diese Einträge vornimmt. Diesem sollte schon vertraut werden.

Der Aufbau einer E-Mail mit den verschiedenen Varianten von Attachments ist ein anderes Thema.

HTTP

Auch HTTP ist ein Klartextprotokoll. Die Syntax ist relativ einfach, es gibt aber keinen Begrüßungstext vom Server, also nicht wundern, wenn bei einer telnet-Sitzung nur ein Connected vom Client kommt.

Der Aufbau ist immer gleich:

Methode URL Protokoll
{Leerzeile}

Zusätzlich zur ersten Zeile können noch Header-Daten mitübergeben werden. Diese können den eigentlichen Server benennen, z.B. bei mehreren virtuellen Servern, oder den eigenen Browsertyp sowie die Fähigkeiten und Präferenzen des eigenen Browsers. Ferner können hier noch Authentisierungsmethoden stehen, inklusive Passwort! Passwörter stehen hier gewöhnlich als Base64 codiertes "user:passwd".

Die Leerzeile wird oft bei einer telnet-Sitzung vergessen, dann kann recht lange gewartet werden. Nach dem Request muß also 2xEnter eingegeben werden!

Im einfachsten Fall z.B.:

Trying 151.136.100.3...
Connected to www.genua.de.
Escape character is '^]'.
HEAD / HTTP/1.0
Host: www.genua.de
    
HTTP/1.1 200 OK
Date: Mon, 24 Oct 2005 19:03:22 GMT
Server: Apache/1.3.29 (Unix) mod_ssl/2.8.16 OpenSSL/0.9.7d
Last-Modified: Mon, 24 Oct 2005 15:52:21 GMT
ETag: "25f29983f347889a20dc2e075c0a13c58e76f7a3"
Accept-Ranges: bytes
Content-Length: 6784
Connection: close
Content-Type: text/html
 
Connection closed by foreign host.

In diesem Beispiel ist die Antwort ein 200 OK, alles ist in Ordnung.

Die Methode HEAD liefert nur den Header des Webservers. Hier steht u.a. welcher Server eingesetzt wird und weitere Informationen wie Art des Inhaltes. Diesen wird normalerweise vom Browser nicht angezeigt.

Die, möglicherweise, verfügbaren Methoden sind:

 method    defined    cachabil.  meaning
 ----- ---------- ---------- -------------------------------------------
 GET       HTTP/0.9   possibly   object retrieval and simple searches.
 HEAD      HTTP/1.0   possibly   metadata retrieval.
 POST      HTTP/1.0   CC or Exp. submit data (to a program).
 PUT       HTTP/1.1   never      upload data (e.g. to a file).
 DELETE    HTTP/1.1   never      remove resource (e.g. file).
 TRACE     HTTP/1.1   never      appl. layer trace of request route.
 OPTIONS   HTTP/1.1   never      request available comm. options.
 CONNECT   HTTP/1.1r3 never      tunnel SSL connection.

 PROPFIND  rfc2518    ?          retrieve properties of an object.
 PROPATCH  rfc2518    ?          change properties of an object.
 MKCOL     rfc2518    never      create a new collection.
 COPY      rfc2518    never      create a duplicate of src in dst.
 MOVE      rfc2518    never      atomically move src to dst.
 LOCK      rfc2518    never      lock an object against modifications.
 UNLOCK    rfc2518    never      unlock an object.

Normalerweise kommt GET zum Einsatz um die Seiten zu holen, bei CGI-Skripten bzw. Formularen kommt auch POST zum Einsatz. Der Unterschied ist relativ einfach, bei GET stehen alle Parameter in der URL, bei POST im Header des Requests. Die Daten werden aber in beiden Fällen im Klartext übertragen.

CONNECT wird bei Webproxies verwendet um SSL-verschlüsselte Verbindungen zu ermöglichen. Die Verschlüsselung erfolgt immer zwischen Server und Client, d.h. ein Proxy kann den Traffic nicht entschlüsseln und daher auch nicht cachen.

Die restlichen Methoden werden hauptsächlich von webdav verwendet.

Testen eines Proxies erfolgt ähnlich, nur wird hier die vollständige URL inklusive Protokoll an den Proxy übergeben:

majestix:~$ telnet 192.168.1.5 3128 
Trying 192.168.1.5...
Connected to 192.168.1.5.
Escape character is '^]'.
HEAD http://www.genua.de/ HTTP/1.1

HTTP/1.0 200 OK
Date: Sun, 23 Oct 2005 15:30:20 GMT
Server: Apache/1.3.29 (Unix) mod_ssl/2.8.16 OpenSSL/0.9.7d
Last-Modified: Sun, 16 Oct 2005 23:40:26 GMT
ETag: "56ffaa0a1760caaabe6df087743a6d6fcef464ef"
Accept-Ranges: bytes
Content-Length: 6784
Content-Type: text/html
Age: 99791
X-Cache: HIT from majestix
Proxy-Connection: close

Connection closed by foreign host.

Wie erkannt werden kann fügt der Proxy auch ein paar Headerzeilen an. Je nach Proxy kann auch modifiziert werden welche Header vom Browser wie weitergegeben werden.

Und wer es nicht glauben mag, der IE meldet sich wirklich als Mozilla:

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)

Tja, warum hier NT 5.1 steht ist eine andere Frage. Aber vermutlich ist es der gleiche Grund warum sich der IE als Mozilla meldet. Denn sonst wären W2K und W2K3 nicht NT-kompatibel und würden einige der Seiten von einem IIS nicht bekommen.

Die häufigsten Return-Codes sind:

 200 OK

 301 Moved Permanently
 302 Moved Temporarily

 400 Bad Request
 401 Unauthorized
 403 Forbidden
 404 Not Found
 407 Proxy Authentication Required

 500 Internal Server Error
 501 Not Implemented
 502 Bad Gateway
 503 Service Unavailable
 505 HTTP Version Not Supported

Die Syntax und Bedeutung sind also ähnlich wie bei SMTP.

Manche Probleme enstehen aber häufig auch durch den übertragenen Header. Hier kann es bei unterschiedlichen User-Agents verschiedene Antworten geben. Auch die akzeptierten Formate können zu Problemen führen. Aber das liegt nun wirklich nicht mehr im Bereich Netzwerkprobleme. Diese liegen meist bei Webdesginern und ihrem falschen Verständnis des World Wide Webs.

Die Kommunikation des Browsers mit einem Web-Proxy wie z.B. squid erfolgt immer via HTTP. Das gilt auch wenn Dateien via FTP heruntergeladen werden. Der Proxy spricht mit dem Server FTP, er leitet die Daten dann aber via HTTP an den Browser/Client weiter.

Das im Hinterkopf behalten werden wenn Probleme mit einem Proxy vermutet werden. Auf der anderen Seite ist dies gut zu Wissen wenn FTP eingesetzt werden soll und Gedanken über Sicherheit gemacht werden sollen.

Dann reicht bei FTP-Downloads mitunter ein HTTP-Proxy!

FTP

Es heißt nicht von ungefähr

FTP must DIE!

Dieses Protokoll verursacht so manches Kopfzerbrechen. Das schlimme am FTP ist, daß zwei Kanäle, d.h. Verbindungen, involviert sind.

Die Eine ist die Kontrollverbindung über die Befehle abgesetzt werden können, die andere Verbindung wickelt den eigentlichen Datentransfer ab.

Es werden je nach Server eine Vielzahl von Befehlen unterstützt vom Erstellen von Verzeichnissen, dem Umbenennen von Dateien bis zum Anhängen von Daten.

Besonders wichtig sind die beiden verschiedenen FTP-Verfahren:

aktiv und passiv

Aktives FTP:

Passives FTP:

Der Vorteil bei passivem FTP ist, daß der Client beide Verbindungen öffnet, d.h. es kann vorhergesagt werden wer die Verbindung wirklich öffnet, nämlich der Client. Das ist für Filterregeln für den Client sehr hilfreich.

Das verursacht aber Kopfschmerzen, wenn ein Server über Filterregeln abgesichert werden soll. Denn nun ist hier ein Port für eine eingehende Verbindung nur schwer vorhersagbar.

Bei aktivem FTP ist die Situation genau umgekehrt.

In den passiven Modus wird mit dem Kommando pasv gewechselt Als Antwort wird die Adresse für den Datenkanal zurückgeliefert:

pasv
227 Entering Passive Mode (127,0,0,1,128,1)

In diesem Fall wird auf 127.0.0.1:32769 ein Port geöffnet, das berechnet sich über 128*256+1.

Ein telnet auf diesen Port liefert nun:

geschke@debix:~$ telnet localhost 32769
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

Wird nun in der ersten telnet-Sitzung, dem Kontrollkanal, ein list abgesetzt so passiert folgendes:

list
150 Opening ASCII mode data connection for '/bin/ls'.
226 Transfer complete.

Gleichzeitig gibt es die Daten, in diesem Fall eine Auflistung der Dateien, in der zweiten telnet-Sitzung auf Port 32769:

total 20
-rw-r--r--  1 genua genua  266 Jul 12  2004 .alias
-rw-------  1 genua genua  147 Oct 26 22:09 .bash_history
-rw-r--r--  1 genua genua  704 Jul 12  2004 .bash_profile
-rw-r--r--  1 genua genua 1290 Jul 12  2004 .bashrc
-rw-r--r--  1 genua genua  375 Jul 12  2004 .cshrc
drwx------  2 genua genua    6 Oct 26 20:34 Mail
Connection closed by foreign host.

Es funktioniert offensichtlich.

Umgekehrt, im aktiven Modus, funktioniert es auch, es muß nur ein TCP-Server geöffnet werden, der auf dem richtigen Port horcht. Netcat bzw. nc kann dies bewerkstelligen. Der Port kann auch mit dem Kommando port auf der Kontrollverbindung festgelegt werden:

port 127,0,0,1,128,1
200 PORT command successful.
list
150 Opening ASCII mode data connection for '/bin/ls'.
226 Transfer complete.

Hierbei ist gleichzeitig mit nc ein Server auf Port 32769 geöffnet worden:

geschke@debix:~$ nc -l -p 32769 
total 20
-rw-r--r--  1 genua genua  266 Jul 12  2004 .alias
-rw-------  1 genua genua  147 Oct 26 22:09 .bash_history
-rw-r--r--  1 genua genua  704 Jul 12  2004 .bash_profile
-rw-r--r--  1 genua genua 1290 Jul 12  2004 .bashrc
-rw-r--r--  1 genua genua  375 Jul 12  2004 .cshrc
drwx------  2 genua genua    6 Oct 26 20:34 Mail

Netcat bzw. nc kann übrigens sehr gut dazu verwendet werden Daten zwischen zwei Systemen auszutauschen. Auf dem Einen wird nc im LISTEN-Modus gestartet, d.h. als Server, mit der Option -l, auf dem Anderen einfach nur mit der Adresse und dem Port, also z.B.:

debix:~$ nc -l -p 1234  > Datei

und

majestix:~$ ls -l stat.pl 
-rwxr-xr-x    1 geschke  physik       5129 Aug 12  2002 stat.pl
majestix:~$ md5sum stat.pl 
b2b92dc021534afe0e4a72aa531c49c1  stat.pl
majestix:~$ cat stat.pl| nc 192.168.1.18 1234

Beenden mit CTRL-C liefert dann:

debix:~$ ls -l Datei
-rw-r--r--  1 geschke physik 5129 Oct 29 22:13 Datei
debix:~$ md5sum Datei 
b2b92dc021534afe0e4a72aa531c49c1  Datei

Es hat also funktioniert. Das ist ein nettes Spielzeug, es kann sogar mit UDP arbeiten und hat sich schon oft als hilfreich erwiesen. Wenn auf die Schnelle eine Lösung für Datentransfer benötigt wird, so liefert nc eine gute Möglichkeit dazu.

SSH

SSH-Server können auch via telnet getestet werden. Allerdings liefert ein ssh-Server nur einen Begrüßungstext, der einem mitteilt wer bzw. was auf der Gegenseite lauscht. Das reicht aber gelegentlich schon, der Rest kann dann mit dem ssh-Client und der Option -v herausgefunden werden. Es ist möglich diese Option mehrfach anzugeben und der Client wird immer geschwätziger.

POP und IMAP

Was für eine Überraschung, diese alten Protokolle sprechen auch Klartext. Allerdings gibt es auch SSL-verschlüsselte Verfahren wie pops bzw. imaps oder TLS, Transport Layer Security. Der Unterschied liegt darin, daß erstere grundsätzlich verschlüsselt sind während bei TLS erst mit dem normalen Dienst TLS ausgehandelt wird. Dabei können u.a. auf verschiedene Verfahren ausgehandelt werden und dann in den verschlüsselten Modus gewechselt werden.

POP, das Post Office Protocol, ist ein sehr einfaches Protokoll. Dies dient eigentlich nur dem Abholen der E-Mails vom Server.

IMAP, das Internet Message Access Protocol, ist neuer und leider auch deutlich komplexer. Es verfügt u.a. über die Möglichkeit die E-Mails auf dem Server zu verwalten. Einige Optionen von IMAP sind aber später bei POP eingeflossen.

Die wichtigsten POP-Kommandos sind:

USER {username}
PASS {Passwort}
STAT
LIST {Message-Nr}
RETR {Message-Nr}
DELE {Message-Nr}
TOP {Message-Nr} {Zahl der Zeilen}
QUIT

Ansonsten gibt es noch das AUTH Kommando sowie APOP. Mit AUTH kann ein alternatives Authentisierungsverfahren mit dem Server vereinbart werden, soweit dieser das unterstützt.

APOP {username} {MD5-digest}

bietet die Möglichkeit einer Authentisierung bei der das Passwort nicht im Klartext mitgelesen werden. Dazu wird aus dem Zeitstempel des Servers und dem Klartext-Passwort ein MD5-Hash gebildet der hier zusammen mit dem Benutzernamen übermittelt wird.

Damit das funktionieren kann muß allerdings das Benutzerpasswort auf dem Server im Klartext hinterlegt worden sein, ähnlich wie bei CHAP.

IMAP dagegen ist deutlich komplexer, jede Kommunikation wird durch ein vorangestelltes TAG eindeutig zugewiesen. Dadurch können mehrere Requests direkt hintereinander abgesetzt werden ohne daß auf die Beendigung der einzelnen Requests gewartet werden muß. Z.B. kann dadurch ein Umkopieren einer Mailbox im Hintergrund weiterlaufen und es kann regulär weitergearbeitet werden. Durch das TAG können die Antworten des Servers eindeutig zum Request zugeordnet werden. Es können ferner mehrere Mailfolder auf dem Server verwendet werden, usw.

CAPABILTY liefert die Möglichkeiten, d.h. Protokollelemente und Authentisierungsverfahren des Servers, LOGOUT beendet eine Sitzung, z.B.:

debix:~# telnet localhost 143
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
* OK IMAP4rev1
T10 CAPABILITY
* CAPABILITY IMAP4rev1 NAMESPACE IDLE X-VERSION
T10 OK CAPABILITY Completed
1234 LOGOUT
* BYE Session terminating.
1234 OK LOGOUT Completed
Connection closed by foreign host.

Weitere Kommandos sind:

AUTHENTICATE {Methode}
LOGIN {username} {passwort}
SELECT {mailbox}
EXAMINE {mailbox}
CREATE {mailbox}
DELETE {mailbox}
RENAME {old mailbox} {new mailbox}

Es gibt noch eine Vielzahl weiterer Optionen. Die meisten Probleme werden jedoch bei der Authentisierung gefunden. Aufgrund der vielen möglichen Verfahren ist dies nicht gerade trivial.

Ein wichtiger Punkt ist vielleicht noch: Auch ein LOGOUT benötigt ein TAG! Ansonsten kann sich nicht ordentlich abgemeldet werden.

Damit haben wir auch die wichtigsten bzw. häufigsten Protokolle angesprochen die im Klartext betrieben werden.

tcpdump / wireshark

Dies sind Werkzeuge zum Mitschneiden des Netzwerkverkehrs der an der Ethernetkarte vorbeikommt. D.h. es können theoretisch auch Pakete mitgeschnitten werden die nicht für das eigene System gedacht sind. Im Zeitalter von Switchen reduziert sich das aber gewöhnlich auf diese Pakete.

Tcpdump ist das ältere Tool und nur auf der Kommandozeile benutzbar, d.h. es wird kein graphisches Display angeboten.

Ethereal hingegen hat eine graphische Benutzerschnittstelle und kann erheblich mehr höhere Protokolle analysieren als tcpdump. Ferner kann es TCP-Streams reassemblieren, d.h. den kompletten Datenstrom auf Applikationsebene zusammengebastelt darstellen. Bei einer telnet-Verbindung wird gewöhnlich jedes Zeichen einzeln übertragen, da kann dann lange gesucht werden bis die Informationen beisammen sind die wirklich ausgetauscht werden. Ethereal macht das mit einem Klick.

Beide Programme haben Vor- und Nachteile. Die Nachteile von wireshark sind:

tcpdump kann dagegen bequem auf der Kommandozeile verwendet werden, es ist schnell verfügbar und ist meistens sehr hilfreich.

Das Gute:

tcpdump kann die mitgeschnittenen Daten in eine Datei schreiben die anschließend von wireshark verarbeitet werden kann. Ethereal kann dazu unter einer andere UID als root laufen und kann zudem dann offline, also ohne Netzwerkverbindung, betrieben werden.

tcpdump

Tcpdump hat eine Vielzahl von Option und Filtermöglichkeiten. Die wichtigsten Optionen sind:

 -i Interface   Auf welchem Interface soll gesniffed werden?
 -s snaplen     Wieviele Daten sollen mitgeschnitten werden, normalerweise
                sind das nur 68 Bytes, -s 0 sniffed alles mit.
                Ansonsten gilt für Ethernet für alles: -s 1514
 -v             detailliertere Ausgabe
 -n             Keine Namensauflösung, Adressen werden als IP-Zahlen
                dargestellt.
 -c count       Es werden nur "count" Pakete gelesen.
 -w file        Schreibt die Daten in die angegebene Datei.
 -r file        Liest die Daten aus der Datei statt von der Netzwerkkarte
 -e             Gibt die Link-Level Header aus (Ethernetheader)
 -x             Gibt die Daten in HEX aus
 -X             Gibt zusätzlich ASCII-Zeichen in Klartext aus

Die Filteroptionen sind noch reichhaltiger. Meistens genügt es aber das Protokoll, die Ports oder die involvierten IP-Adressen zu verwenden, z.B.:

  port Port
  host Rechnernamen/adresse
  net  Netzwerkadresse
  proto Protokoll

Diese können mit UND (and) oder ODER (or) verknüpft werden.

Eine Anwendung wäre z.B.:

debix# tcpdump -i eth0 -n -v -x -X -s 1514 host 192.168.1.5 and port 3128

Das protokolliert den Netzwerkverkehr zu der Adresse 192.168.1.5 und Port 3128 auf dem Interface eth0 mit.

Sollen der Deutlichkeit halber die Filter gruppiert werden, damit klarer ist wie z.B. die and/or Verknüpfungen zu verstehen sind, so können diese zusammengehörigen Einträge durch Hochkommata eingeschlossen werden. Dann gruppiert das zwar die Shell und nicht tcpdump, d.h. die Shell überreicht die gesamte eingeschlossene Zeichenkette als ein Argument an _tcpdump aber das ist eigentlich egal, der Effekt zählt schließlich.

Dies geht z.B. via

tcpdump -n 'host 192.168.1.5 or host 192.168.1.1' and port 3128

Hilfreich bei Netzwerkproblemen ist es auch ICMP mitzuschneiden, also z.B.:

debix# tcpdump -n -v host 192.168.1.5 or icmp

Manchmal liegt das Problem schlichtweg darin begründet, daß entweder auf ICMP-Meldungen nicht reagiert wird oder diese unterwegs verloren gehen. Für letzteres können auch die eigenen IPTables Filterregeln verantwortlich sein, siehe IPTables weiter unten.

Wichtig ist noch ein Punkt:

tcpdump greift vor Filterregeln

D.h. wenn IPtables z.B. ICMP-Pakete verwirft, so werden diese dennoch mit tcpdump angezeigt!

Können Pakete auf einem Interface gesehen werden, auf dem anderen, wo es laut Routing-Tabelle herauskommen sollte, nicht, so kann dies meist an folgendem liegen:

Der letzte Punkt kann global aber auch je Interface aktiviert bzw. deaktiviert werden:

  /proc/sys/net/ipv4/ip_forward 
  /proc/sys/net/ipv4/conf/eth0/forwarding
  /proc/sys/net/ipv4/conf/eth1/forwarding
  /proc/sys/net/ipv4/conf/lo/forwarding
  /proc/sys/net/ipv4/conf/default/forwarding
  /proc/sys/net/ipv4/conf/all/forwarding

Hier gilt aber auch: Wenn IP-Forwading global erlaubt ist kann es auf einem einzelnen Interface trotzdem eingeschaltet sein, dann steht eine 0 in der globalen Variable!

Wichtig ist das Deaktivieren von Namensauflösung durch -n bei tcpdump, ansonsten würde für jede neue IP-Adresse erst eine Namensauflösung eingeleitet. Das kann zu Verzögerungen oder auch Paketverlusten führen.

Am Ende einer tcpdump-Sitzung werden noch Statistiken ausgegeben:

12 packets received by filter
0 packets dropped by kernel

Es ist allerdings meistens nicht sehr leicht einen Fehler auf diese Weise zu finden. Je nach Lage in der Protokollebene des Problems ist entweder tcpdump oder wireshark besser geeignet. Liegt das Problem in den höheren Protokollebenen so ist gewöhnlich wireshark besser geeignet den Fehler bzw. das Problem zu lokalisieren.

Auf der anderen Seite führt wireshark meist dazu, daß an der falschen Stelle gesucht wird. Oft zerlegt wireshark die Pakete in scheinbar besser lesbare Formate, hier ist die Ausgabe von tcpdump oft besser lesbar.

Ein weiteres Problem besteht gewöhnlich darin den relevanten Datenstrom herauszufiltern. Bei HTTP-Zugriffen wird meist auf das Zielsystem sowie Port 80 gefiltert. Ein Browser verwendet aber gewöhnlich mehrere Requests parallel um allen Inhalt einer Seite möglichst schnell darstellen zu können.

Hier ist ein reduziertes Beispiel eines Mitschnittes das einen Fehler beinhaltet:

IP 194.121.48.2.48258 > 217.111.27.27.443: S 2285705822:2285705822(0) win 32768
IP 217.111.27.27.443 > 194.121.48.2.48258: S 3078367044:3078367044(0) ack 2285705823 win 17520 
IP 194.121.48.2.48258 > 217.111.27.27.443: . ack 1 win 33580 
IP 194.121.48.2.48258 > 217.111.27.27.443: P 1:115(114) ack 1 win 33580 
IP 217.111.27.27.443 > 194.121.48.2.48258: P 1449:2166(717) ack 115 win 17406
IP 194.121.48.2.48258 > 217.111.27.27.443: . ack 1 win 33580 
IP 217.111.27.27.443 > 194.121.48.2.48258: . 1449:1461(12) ack 115 win 17406 
IP 194.121.48.2.48258 > 217.111.27.27.443: . ack 1 win 33580 
IP 217.111.27.27.443 > 194.121.48.2.48258: . 1449:1461(12) ack 115 win 17406 
IP 194.121.48.2.48258 > 217.111.27.27.443: . ack 1 win 33580
IP 217.111.27.27.443 > 194.121.48.2.48258: P 1461:2166(705) ack 115 win 17406 
IP 194.121.48.2.48258 > 217.111.27.27.443: . ack 1 win 33580 
IP 194.121.48.2.48258 > 217.111.27.27.443: F 115:115(0) ack 1 win 33580 
IP 217.111.27.27.443 > 194.121.48.2.48258: . ack 116 win 17406 
IP 217.111.27.27.443 > 194.121.48.2.48258: FP 1449:2166(717) ack 116 win 17406 
IP 194.121.48.2.48258 > 217.111.27.27.443: R 2285705938:2285705938(0) win 0
IP 217.111.27.27.443 > 194.121.48.2.48258: . 1449:1461(12) ack 116 win 17406 
IP 194.121.48.2.48258 > 217.111.27.27.443: R 2285705938:2285705938(0) win 0

Dabei habe ich hier schon alles unwichtige wie TCP-Optionen herausgenommen. Dennoch ist es nicht leicht zu erkennen wo der Fehler liegt, oder?

IPTables

Mit iptables besitzt Linux die Möglichkeit Netzwerkverkehr direkt zu beeinflussen. Die häufigste Anwendung besteht jedoch nur im Blocken von Ports und sehr häufig betrifft das nur eingehende Verbindungen.

Dazu dienen einige Netfilter-Module im Kernel, diese müssen also entweder im Kernel einkompiliert sein oder als ladbares Modul vorliegen.

Es gibt 5 Stellen an denen Filter wirken können, das sind sogenannte chains, also Ketten:

Es gibt zusätzlich 3 Tabellen die verwendet werden können:

Je nach Tabelle wird an unterschiedlichen Stellen angesetzt.

So verwendet nat die PREROUTING und POSTROUTING chains sowie OUTPUT für das Umschreiben lokal generierter Pakete, die filter Tabelle hingegen verwendet nur INPUT, FOWARD und OUTPUT.

Dabei ist das Schema relativ einfach, es gelten die obigen Zahlen:

  --->[1]--->[ROUTE]--->[3]--->[4]--->
                 |            ^
                 |            |
                 |         [ROUTE]
                 v            |
                [2]          [5]
                 |            ^
                 |            |
                 v            |

Zur Definition:

PREROUTING
Dies betrifft alle eingehenden Pakete, also bevor Routing-Entscheidungen getroffen werden. Danach können die Pakete entweder in die INPUT oder FORWARD chain laufen.
INPUT
Dies bezieht sich nur auf Pakete die auf dem System terminieren, also keine Pakete die noch weitergeleitet werden.
FORWARD
Dies betrifft nur vorbeigehende Pakete.
OUTPUT
Dies beschreibt die von der lokalen Maschine ausgehenden Pakete, dies greift nicht bei weitergeleiteten Paketen.
POSTROUTING
Dies betrifft alle Pakete die die Ethernetkarte verlassen, d.h. nachdem die Routing-Entscheidung getroffen worden ist.

Manipuliert werden diese Tabellen und chains via dem Userland Tool iptables.

Die wichtigsten Optionen sind hier:

-L
Dies listet die aktuell gesetzten Filter auf.
-F
Dies löscht alle Filter.
-P policy
Dies setzt die default policy.

Die default policy beschreibt das Verhalten wenn keine Regel zutrifft. Also entweder alles ablehnen oder akzeptieren. Vorsicht: Wenn die default policy auf DENY steht, dann wird durch iptables -F das Netzwerk komplett gesperrt.

Wird keine table mit -t angegeben, so wird nur die filter Tabelle ausgegeben bzw. verwendet.

Am Ende einer Regel steht immer das Target, dies besagt was mit dem Netzwerkpaket passieren soll.

Die wichtigsten sind:

ACCEPT
Das Paket wird angenommen.
LOG
Das Paket wird lediglich mitprotokolliert.
DENY
Das Paket wird stillschweigend verworfen.
REJECT
In diesem Fall wird das Paket abgelehnt und entweder ein ICMP wird generiert, die Voreinstellung ist port unreachable, oder bei TCP wird ein RST-Flag zurückgesendet.
QUEUE
Hier wird das Paket zur Weiterverarbeitung an den Userspace weitergeleitet
RETURN
Dies bewirkt eine Rückkehr aus der aktuellen chain, d.h. es wird zur nächsten gegangen.
REDIRECT
Dies lenkt den Verkehr auf einen lokalen Port um. Das funktioniert nur mit der nat Tabelle!

Die Optionen

-N chain
Eine neue chain wird angelegt.
-X chain
Die angegebene chain wird gelöscht.

beeinflussen neue chains.

Mit den Optionen

-A chain rule
Eine Regel wird der chain hinzugefügt (add).
-D chain rulenum
Die angegebene Regel wird aus der chain gelöscht (delete).
-I chain {rulenum} rule
Die Regel wird an der angegebenen Stelle in die chain eingefügt. Wird keine Nummer angegeben, so wird die Regel am Anfang der chain eingesetzt (insert).
-R chain rulenum rule
Die Regel an der Stelle rulenum wird durch die angegebene ersetzt (replace).

können die Chains modifiziert werden.

Mit der Option -j, jump, kann in eine neue chain gesprungen werden. Auf diese Weise kann dann z.B. von der INPUT chain in eine eigene verzweigt werden.

Optionen für die Einschränkung der Pakete gilt:

-p protocol
Welches Protokoll das Paket haben? Z.B. tcp, udp, icmp oder all. Mit einem Ausrufezeichen wird dies verneint, d.h. -p ! tcp paßt auf alles außer TCP.
-s address{/mask}
Spezifiziert die Source-Adresse auf welche die Regel wirken soll.
-d address{/mask}
Dies bestimmt auf welche Ziel-Adresse diese Regel wirken soll.
-i interface
Hiermit kann festgelegt werden auf welchem Interface die Regel wirken soll.
-o interface
Dies bestimmt analog das ausgehendes Interface
-f bzw. ! -f
Hiermit werden nur Fragmente, d.h. 2., 3., etc. betrachtet bzw. nur das erste Paket (! -f).
-m {match}
Dies kann verwendet werden um einen Zustand zu prüfen. Dieser kann ESTABLISHED, RELATED, NEW oder INVALID sein. Die Syntax ist dann z.B. -m state --state NEW

ESTABLISHED gehört zu einer bestehenden Verbindung, NEW zu einer neuen, d.h. bei TCP ist nur das SYN-Flag gesetzt. RELATED ist ein indirekt zu der Verbindung gehörendes Paket. Dies kann z.B. der Datenkanal einer FTP-Verbindung sein oder eine zu der Verbindung gehörende ICMP Fehlermeldung. Dies ist oft nicht unwichtig, diese werden wenn nur ESTABLISHED verwendet wird ignoriert, d.h. PMTU kann nur mit ESTABLISHED nicht mehr korrekt funktionieren.

Um das alles ein wenig mit Leben zu füllen ist hier ein Beispiel:

#!/bin/sh
#
# Löschen der alten chains
# default-policy ist ACCEPT
#
iptables -F
#
# Masquerading fuer ppp0, alle über ppp0 ausgehende Pakete bekommen
# die IP-Adresse ppp0 als Absendeadresse 
#
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
#
# Erlauben von SSH, HTTP und HTTPS via ppp0 als input
#
iptables -A INPUT -i ppp0 --protocol tcp --destination-port 22 -j ACCEPT 
iptables -A INPUT -i ppp0 --protocol tcp --destination-port 80 -j ACCEPT 
iptables -A INPUT -i ppp0 --protocol tcp --destination-port 443 -j ACCEPT 
#
# Verbot für neue einkommende oder ungültige Verbindungen
#
iptables -A INPUT -i ppp0 -m state --state NEW,INVALID -j LOG
iptables -A INPUT -i ppp0 -m state --state NEW,INVALID -j DROP

#
# Alles andere ist erlaubt! Alternativ könnte man auch erst mit
#
# iptables -A INPUT -i ppp0 -m --state ESTABLISHED,RELATED -j ACCEPT
#
# alle Pakete akzeptieren und anschließend alles andere droppen
#
# input -A INPUT -i ppp0 -j DROP
#

# Forwarding im Kernel aktivieren 
echo 1 > /proc/sys/net/ipv4/ip_forward

Es gibt aber noch eine Vielzahl von verschiedenen Optionen nach denen gefiltert werden kann.

Interessant sind auch die Möglichkeiten Pakete zu Redirecten, d.h. das Umleiten auf einen lokalen Port oder TCP/IP-Optionen zu verändern. Mit --reject-with kann z.B. auch der ICMP Typ festegelegt werden mit dem eine Verbindung abgewiesen wird.

Portscanner

Ein Portscanner ist in der Lage herauszufinden welche Ports ein Server geöffnet hat. Im einfachsten Fall funktioniert dies durch das Senden von SYN-Paketen und darauf zu Warten ob ein SYN-ACK zurückkommt. Da hier aber immer ein Verbindungszustand zu sehen ist gibt es auch die Möglichkeit des Stealth-Scanning. Aber das ist ein anderes Kapitel.

Dieses Verfahren funktioniert natürlich nur mit TCP, bei UDP ist das Scannen etwas schwieriger da normalerweise keine Antwort erfolgen muß. Hier funktioniert der Trick analog zu TCP, es werden Pakete an alle Ports gesendet, kommt ein ICMP Port unreachable zurück, so ist der Port geschlossen, im anderen Fall wird davon ausgegangen, daß der Port offen ist.

Der bekannteste Vertreter diese Klasse an Programmen ist nmap: http://www.insecure.org/nmap/

Dieser Scanner bietet zusätzlich die Möglichkeit zu bestimmen welches Betriebssystem die Gegenstelle verwendet (buest guess).

Per default werden nur well-known TCP-Ports gescanned, d.h. diejenigen die auch in /etc/services aufgeführt sind, z.B.:

dg4:~# nmap dg6

Starting nmap 3.81 ( http://www.insecure.org/nmap/ ) at 2005-10-25 17:02 CEST
Interesting ports on dg6-tst.genua.de (10.1.22.6):
(The 1639 ports scanned but not shown below are in state: closed)
PORT     STATE SERVICE
7/tcp    open  echo
9/tcp    open  discard
13/tcp   open  daytime
19/tcp   open  chargen
21/tcp   open  ftp
22/tcp   open  ssh
23/tcp   open  telnet
25/tcp   open  smtp
37/tcp   open  time
80/tcp   open  http
111/tcp  open  rpcbind
113/tcp  open  auth
135/tcp  open  msrpc
512/tcp  open  exec
513/tcp  open  login
...

Die Option -sU scanned nach offenen UDP-Ports:

dg4:~# nmap -sU dg6

Starting nmap 3.81 ( http://www.insecure.org/nmap/ ) at 2005-10-25 17:03 CEST
Interesting ports on dg6-tst.genua.de (10.1.22.6):
(The 1461 ports scanned but not shown below are in state: closed)
PORT     STATE         SERVICE
7/udp    open          echo
9/udp    open|filtered discard
13/udp   open          daytime
19/udp   open          chargen
37/udp   open          time
68/udp   open|filtered dhcpclient
69/udp   open|filtered tftp
111/udp  open|filtered rpcbind
123/udp  open|filtered ntp
135/udp  open|filtered msrpc
161/udp  open|filtered snmp
177/udp  open|filtered xdmcp
514/udp  open|filtered syslog
518/udp  open|filtered ntalk

Die Option -O liefert zusätzlich Vermutungen über das Betriebssystem:

   Running: HP HP-UX 10.X
   OS details: HP-UX 10.20 E 9000/777 or A 712/60 with tcp_random_seq = 0

oder

   Running: Sun Solaris 9
   OS details: Sun Solaris 9

Beim Portscanning ist aber Vorsicht geboten, nicht jeder Administrator mag es wenn seine Systeme gescanned werden, daher eixistiert auch der Stealth Modus.

Einen Schritt weiter gehen Programme wie Nessus: http://www.nessus.org/

Diese nennen sich auch prompt Vulnerability Scanner. Dieses Programm verwendet nmap um offene Ports zu finden. Gleichzeitig wird versucht herauszufinden welche Software diesen Port geöffnet hat. Zusammen mit der Versionsnummer werden auch Hinweise auf Sicherheitslücken ausgegeben.

Es ist klar, das kann auch negativ ausgenutzt werden.

Aber manchmal kann ein Portscanner bei unbekannten Geräten durchaus hilfreich sein. Und mitunter wird herausgefunden, daß ein root-kit installiert worden ist. Das ist dann der Fall, wenn nmap offene Ports zeigt die nestat nicht auflistet. Dann wurde vermutlich netstat durch eine modifizierte Version ersetzt um den offenen Port zu verbergen.

Es existieren aber auch root-kits die einen Port erst nach anklopfen öffnen, d.h. wenn ein Paket mit bestimmter Signatur auf dem Netzwerkinterface gesichtet wird öffnet das root-kit einen Port.

Dirk Geschke, dirk@lug-erding.de