Einführung
Sockets sind eine Möglichkeit, die zwischen Programmen auf einem Server oder zwischen Programmen auf verschiedenen Servern die Interprozesskommunikation ermöglicht. Die Kommunikation zwischen Servern basiert auf Netzwerk-Sockets, die das Internetprotokoll (IP) verwenden, um Daten zu senden und zu empfangen.
Netzwerk-Sockets sowohl auf Clients als auch auf Servern werden durch ihre Socket-Adresse identifiziert. Eine Adresse ist eine eindeutige Kombination aus einem Transportprotokoll wie dem Transmission Control Protocol (TCP) oder dem User Datagram Protocol (UDP), einer IP-Adresse und einer Portnummer.
In diesem Tutorial erfahren Sie mehr über die folgenden verschiedenen Arten von Sockets, die für die Interprozesskommunikation verwendet werden:
- Stream-Sockets, die TCP als ihr zugrunde liegendes Transportprotokoll verwenden
- Datagramm-Sockets, die UDP als ihr zugrunde liegendes Transportprotokoll verwenden
- Unix-Domain-Sockets, die lokale Dateien anstelle von Netzwerkschnittstellen und IP-Paketen zum Senden und Empfangen von Daten verwenden.
In jedem Abschnitt dieses Tutorials erfahren Sie auch, wie Sie die jeweiligen Socket-Typen auf einem Linux-System aufzählen können. Sie werden jeden Socket-Typ mit verschiedenen Befehlszeilenwerkzeugen untersuchen.
Voraussetzungen
Die Beispiele in diesem Tutorial wurden auf einem Ubuntu 20.04-Server validiert. Sie können diesem Tutorial folgen, indem Sie die meisten modernen Linux-Distributionen auf einem lokalen Computer oder einem entfernten Server verwenden, solange Sie die entsprechende Version jeder der erforderlichen Tools für Ihre Distribution installiert haben.
Um mit Ubuntu 20.04 zu beginnen, benötigen Sie einen Server, der gemäß unserer Anleitung zum Initialen Server-Setup für Ubuntu 20.04 konfiguriert wurde.
Sie benötigen außerdem einige andere Pakete, um Sockets auf Ihrem System zu untersuchen. Stellen Sie sicher, dass der Paketcache Ihres Systems mit dem Befehl apt update
aktualisiert wird:
Installieren Sie dann die erforderlichen Pakete mit diesem Befehl:
Das Paket iproute2
enthält das Hilfsprogramm ss
, das wir verwenden werden, um Sockets zu inspizieren. Wir werden das Paket netcat-openbsd
verwenden, um netcat zu installieren. Beachten Sie, dass netcat auf der Befehlszeile als nc
abgekürzt wird, wenn es aufgerufen wird. Schließlich werden wir das Paket socat
verwenden, um Beispielsockets zu erstellen.
Was ist ein Stream-Socket?
Stream-Sockets sind verbindungsbasiert, was bedeutet, dass Pakete, die an einen Netzwerk-Socket gesendet und von diesem empfangen werden, vom Betriebssystem des Hosts zur Verarbeitung durch eine Anwendung geliefert werden. Netzwerkbasierte Stream-Sockets verwenden typischerweise das Transmission Control Protocol (TCP), um Daten über eine Netzwerkschnittstelle zu kapseln und zu übertragen.
TCP ist darauf ausgelegt, ein zuverlässiges Netzwerkprotokoll zu sein, das auf einer zustandsbehafteten Verbindung basiert. Daten, die von einem Programm unter Verwendung eines TCP-basierten Stream-Sockets gesendet werden, werden von einem entfernten System erfolgreich empfangen (sofern es keine Routing-, Firewall- oder andere Konnektivitätsprobleme gibt). TCP-Pakete können auf einer physischen Netzwerkschnittstelle in beliebiger Reihenfolge eintreffen. Im Falle des Eintreffens von Paketen in falscher Reihenfolge stellen der Netzwerkadapter und das Betriebssystem des Hosts sicher, dass sie in der richtigen Reihenfolge für die Verarbeitung durch eine Anwendung neu zusammengesetzt werden.
A typical use for a TCP-based stream socket would be for a web server like Apache or Nginx handling HTTP requests on port 80
, or HTTPS on port 443
. For HTTP, a socket address would be similar to 203.0.113.1:80
, and for HTTPS it would be something like 203.0.113.1:443
.
Erstellen von TCP-basierten Stream-Sockets
In folgendem Beispiel verwenden Sie den Befehl socat
(kurz für SOcket CAT
), um einen Webserver zu emulieren, der auf Port 8080 (dem alternativen HTTP-Port) auf eingehende HTTP-Anfragen lauscht. Anschließend werden Sie den Socket mit den Befehlen ss
und nc
untersuchen.
Führen Sie zunächst die folgenden socat
-Befehle aus, um zwei TCP-basierte Sockets zu erstellen, die auf Verbindungen auf Port 8080
lauschen, unter Verwendung von IPv4- und IPv6-Schnittstellen:
- Die
TCP4-LISTEN:8080
undTCP6-LISTEN:8080
Argumente sind der Protokolltyp und die Portnummer, die verwendet werden sollen. Sie sagensocat
, TCP-Sockets auf Port8080
auf allen IPv4- und IPv6-Schnittstellen zu erstellen, und auf jedem Socket auf eingehende Verbindungen zu hören.socat
kann auf einem System auf jedem verfügbaren Port hören, daher ist jeder Port von0
bis65535
ein gültiger Parameter für die Socket-Option. - Die
fork
-Option wird verwendet, um sicherzustellen, dasssocat
nach der Behandlung einer Verbindung weiterläuft, sonst würde es automatisch beendet werden. - Der Pfad
/dev/null
wird anstelle einer Remote-Socket-Adresse verwendet. In diesem Fall sagt essocat
, jegliche eingehende Eingabe in die Datei/dev/null
zu drucken, was sie stillschweigend verwirft. - Die
ipv6only=1
Flagge wird für den IPv6-Socket verwendet, um dem Betriebssystem mitzuteilen, dass der Socket nicht konfiguriert ist, Pakete an IPv4-gemappte IPv6-Adressen zu senden. Ohne diese Flagge würdesocat
sich sowohl an IPv4- als auch an IPv6-Adressen binden. - Das Zeichen
&
weist die Shell an, den Befehl im Hintergrund auszuführen. Diese Flagge stellt sicher, dasssocat
weiterläuft, während Sie andere Befehle aufrufen, um den Socket zu untersuchen.
Sie erhalten eine Ausgabe wie die folgende, die die beiden socat
-Prozess-IDs anzeigt, die im Hintergrund Ihrer Shell-Sitzung ausgeführt werden. Ihre Prozess-IDs werden sich von den hier hervorgehobenen unterscheiden:
Output[1] 434223
[2] 434224
Nun, da Sie zwei socat
-Prozesse im Hintergrund haben, die auf TCP-Port 8080
lauschen, können Sie die Sockets mit den Dienstprogrammen ss
und nc
untersuchen.
Untersuchung von TCP-basierten Stream-Sockets
Um TCP-Sockets auf einem modernen Linux-System mit dem Befehl ss
zu untersuchen, führen Sie ihn mit den folgenden Flaggen aus, um die Ausgabe einzuschränken:
- Die Flaggen
-4
und-6
teilenss
mit, nur IPv4- oder IPv6-Sockets zu untersuchen. Das Weglassen dieser Option zeigt beide Sätze von Sockets an. - Das Flag
t
beschränkt die Ausgabe auf TCP-Sockets. Standardmäßig zeigt dasss
-Tool alle Arten von Sockets an, die auf einem Linux-System verwendet werden. - Das Flag
l
beschränkt die Ausgabe auf horchende Sockets. Ohne dieses Flag würden alle TCP-Verbindungen angezeigt, einschließlich Dinge wie SSH, Clients, die mit einem Webserver verbunden sein könnten, oder Verbindungen, die Ihr System zu anderen Servern haben könnte. - Das Flag
n
stellt sicher, dass Portnummern anstelle von Dienstnamen angezeigt werden.
Führen Sie zunächst den Befehl ss -4 -tln
aus, um die IPv4-TCP-basierten Sockets zu untersuchen, die auf Ihrem System auf Verbindungen warten:
Sie erhalten eine Ausgabe wie die folgende:
OutputState Recv-Q Send-Q Local Address:Port Peer Address:Port Process
. . .
LISTEN 0 1 0.0.0.0:8080 0.0.0.0:*
. . .
Es können weitere Zeilen mit anderen Ports in Ihrer Ausgabe vorhanden sein, je nachdem, welche Dienste auf Ihrem System ausgeführt werden. Der markierte Teil 0.0.0.0:8080
der Ausgabe zeigt an, dass der IPv4 TCP-Socket auf allen verfügbaren IPv4-Schnittstellen am Port 8080
lauscht. Ein Dienst, der nur auf einer bestimmten IPv4-Adresse lauscht, zeigt nur diese IP im markierten Feld an, zum Beispiel 203.0.113.1:8080
.
Führen Sie nun denselben ss
-Befehl erneut aus, aber mit dem -6
-Flag:
Sie erhalten eine Ausgabe wie folgt:
OutputState Recv-Q Send-Q Local Address:Port Peer Address:Port Process
. . .
LISTEN 0 5 [::]:8080 [::]:*
. . .
Es können weitere Zeilen mit anderen Ports in Ihrer Ausgabe vorhanden sein, je nachdem, welche Dienste auf Ihrem System ausgeführt werden. Der markierte Teil [::]:8080
der Ausgabe zeigt an, dass der IPv6 TCP-Socket auf allen verfügbaren IPv6-Schnittstellen am Port 8080
lauscht (wie durch die ::
-Zeichen angegeben, die in der IPv6-Notation für eine Adresse aus Nullen stehen). Ein Dienst, der nur auf einer bestimmten IPv6-Adresse lauscht, zeigt nur diese IP im markierten Feld an, zum Beispiel [2604:a880:400:d1::3d3:6001]:8080
.
Verbindung zu TCP-basierten Stream-Sockets herstellen
Bisher haben Sie gelernt, wie Sie TCP-Sockets auf IPv4- und IPv6-Schnittstellen erstellen und aufzählen können. Da Sie nun zwei Sockets haben, die auf Verbindungen warten, können Sie experimentieren, indem Sie sich mit den Sockets mithilfe des netcat-Dienstprogramms verbinden.
Die Verwendung von Netcat zum Testen von TCP-Verbindungen zu lokalen und entfernten Sockets ist eine sehr nützliche Troubleshooting-Technik, die dabei helfen kann, Konnektivitäts- und Firewall-Probleme zwischen Systemen zu isolieren.
Um eine Verbindung zum IPv4-Socket über die lokale Loopback-Adresse unter Verwendung von Netcat herzustellen, führen Sie den folgenden Befehl aus:
- Die
-4
-Flag teilt Netcat mit, IPv4 zu verwenden. - Die
-v
-Flag wird verwendet, um ausführliche Ausgaben auf Ihrem Terminal anzuzeigen. - Die –
z
-Option stellt sicher, dass Netcat nur eine Verbindung zu einem Socket herstellt, ohne Daten zu senden. - Die lokale Loopback-IP-Adresse
127.0.0.1
wird verwendet, da Ihr System seine eigene eindeutige IP-Adresse hat. Wenn Sie die IP-Adresse Ihres Systems kennen, können Sie auch damit testen. Zum Beispiel könnten Sie, wenn die öffentliche oder private IP-Adresse Ihres Systems 203.0.113.1 ist, diese anstelle der Loopback-IP verwenden.
Sie erhalten eine Ausgabe wie die folgende:
OutputConnection to 127.0.0.1 (127.0.0.1) 8080 port [tcp/http-alt] succeeded!
Die markierte Zeile ist die Ausgabe von Netcat. Sie zeigt an, dass Netcat eine Verbindung zum TCP-Socket hergestellt hat, das auf der Loopback-IP-Adresse 127.0.0.1
IPv4-Adresse an Port 8080
lauscht. Die zweite Zeile können Sie ignorieren, sie stammt vom im Hintergrund laufenden Socat-Prozess in Ihrem Terminal.
Jetzt können Sie denselben Verbindungstest aber unter Verwendung von IPv6 wiederholen. Führen Sie den folgenden Netcat-Befehl aus:
Sie sollten eine Ausgabe wie die folgende erhalten:
OutputConnection to ::1 8080 port [tcp/http] succeeded!
Die markierte Zeile ist die Ausgabe von Netcat. Sie zeigt an, dass Netcat eine Verbindung zum TCP-Socket hergestellt hat, das auf der Loopback-IP-Adresse ::1
IPv6-Adresse an Port 8080
lauscht. Auch hier können Sie die zweite Ausgabezeile ignorieren.
Um Ihre Sockets zu bereinigen, müssen Sie den fg
(Vordergrund) Befehl für jeden socat-Prozess ausführen, den Sie erstellt haben. Dann verwenden Sie CTRL+C
, um jeden socat zu schließen. fg
bringt Prozesse in den Vordergrund Ihres Terminals in umgekehrter Reihenfolge, in der Sie sie gestartet haben. Wenn Sie es ausführen, wird die zweite socat
-Instanz die sein, mit der Sie zuerst interagieren.
Führen Sie fg
aus, um die zweite IPv6 socat-Instanz in den Vordergrund Ihres Terminals zu bringen. Führen Sie dann CTRL+C
aus, um sie zu schließen.
Sie erhalten eine Ausgabe wie folgt:
Outputsocat TCP6-LISTEN:8080,ipv6only=1,fork /dev/null
Drücken Sie CTRL+C
, um den Prozess zu beenden.
Führen Sie jetzt erneut fg
aus, um den ersten IPv4-Socket zu bereinigen. Sie sollten eine Ausgabe wie folgt haben:
Outputsocat TCP4-LISTEN:8080,fork /dev/null
Drücken Sie CTRL+C
, um den Prozess zu beenden.
Sie haben jetzt IPv4- und IPv6-Sockets auf Ihrem System erstellt, untersucht und verbunden. Diese Techniken und Werkzeuge funktionieren auf lokalen Entwicklungssystemen oder entfernten Produktionsservern, also probieren Sie aus, wie jedes Werkzeug verwendet werden kann, um TCP-Sockets zu testen und zu beheben.
Was ist ein Datagramm-Socket?
Datagramm-Sockets sind verbindungslos, was bedeutet, dass Pakete, die von einem Socket gesendet und empfangen werden, von Anwendungen einzeln verarbeitet werden. Netzbasierte Datagramm-Sockets verwenden typischerweise das User Datagram Protocol (UDP), um Daten zu kapseln und zu übertragen.
UDP codiert keine Sequenzinformationen in den Paketköpfen, und es ist keine Fehlerkorrektur in das Protokoll eingebaut. Programme, die datagrammbasierte Netzwerk-Sockets verwenden, müssen ihre eigene Fehlerbehandlung und Datenreihenfolgelogik implementieren, um eine erfolgreiche Datenübertragung sicherzustellen.
UDP-Sockets werden häufig von Domain Name System (DNS)-Servern verwendet. Standardmäßig verwenden DNS-Server den Port 53
zum Senden und Empfangen von Abfragen für Domainnamen. Ein Beispiel für eine UDP-Socket-Adresse eines DNS-Servers wäre ähnlich wie 203.0.113.1:53
.
Hinweis: Obwohl das Protokoll nicht in der für Menschen lesbaren Version der Socket-Adresse enthalten ist, unterscheiden Betriebssysteme Socket-Adressen, indem sie TCP- und UDP-Protokolle als Teil der Adresse einschließen. Daher könnte eine für Menschen lesbare Socket-Adresse wie 203.0.113.1:53
entweder das TCP- oder das UDP-Protokoll verwenden. Tools wie ss
und das ältere Dienstprogramm netstat
werden verwendet, um festzustellen, welcher Art von Socket verwendet wird.
Das Network Time Protocol (NTP) verwendet eine UDP-Socket am Port 123
, um Uhren zwischen Computern zu synchronisieren. Ein Beispiel für eine UDP-Socket für das NTP-Protokoll wäre 203.0.113.1:123
.
Erstellen von Datagramm-Sockets
Wie im vorherigen TCP-Socket-Beispiel werden Sie auch in diesem Abschnitt socat
erneut verwenden, um einen NTP-Server zu emulieren, der auf UDP-Port 123
auf Anfragen hört. Anschließend werden Sie die erstellten Sockets mit den Befehlen ss
und nc
überprüfen.
Zuerst führen Sie die folgenden socat
-Befehle aus, um zwei UDP-Sockets zu erstellen, die auf Verbindungen auf Port 123 lauschen, und zwar unter Verwendung der IPv4- und IPv6-Schnittstellen:
Sie erhalten eine Ausgabe ähnlich der folgenden, die die beiden socat
-Prozess-IDs anzeigt, die im Hintergrund Ihrer Shell-Sitzung ausgeführt werden. Ihre Prozess-IDs werden unterschiedlich sein als die hier hervorgehobenen:
Output[1] 465486
[2] 465487
- Jeder Befehl ist mit
sudo
vorangestellt, da Ports0
bis1024
auf den meisten Systemen reserviert sind.sudo
führt einen Befehl mit Administratorberechtigungen aus, wassocat
ermöglicht, sich an einen beliebigen Port im reservierten Bereich zu binden. - Die Argumente
UDP4-LISTEN:123
undUDP6-LISTEN:123
sind der Protokolltyp und der zu verwendende Port. Sie geben socat an, UDP-basierte Sockets auf Port123
sowohl auf IPv4- als auch auf IPv6-Schnittstellen zu erstellen und auf eingehende Daten zu warten. Wiederum ist jeder Port im gesamten Bereich von 0 bis 65535 ein gültiger Parameter für UDP-Sockets. - Die Argumente
fork
,ipv6only=1
und/dev/null
werden auf die gleiche Weise verwendet wie im vorherigen TCP-Beispiel beschrieben.
Jetzt, da Sie zwei socat
-Prozesse haben, die auf UDP-Port 123
hören, können Sie die Sockets mithilfe der Dienstprogramme ss
und nc
überprüfen.
Untersuchung von Datagramm-Sockets
Um UDP-Sockets auf einem modernen Linux-System mithilfe des Befehls ss
zu untersuchen, führen Sie ihn mit den folgenden -4
, -6
und -uln
-Flags aus, um die Ausgabe einzuschränken:
Das u
-Flag begrenzt die Ausgabe auf UDP-Sockets.
Die anderen Flags sind die gleichen wie die, die im vorherigen TCP-Beispiel verwendet wurden.
Führen Sie zuerst den Befehl ss -4 -uln
aus, um die IPv4-UDP-Sockets zu untersuchen, die auf Ihrem System auf Verbindungen warten:
Sie erhalten eine Ausgabe ähnlich der folgenden:
OutputState Recv-Q Send-Q Local Address:Port Peer Address:Port Process
. . .
UNCONN 0 0 0.0.0.0:123 0.0.0.0:*
. . .
Es können weitere Zeilen mit anderen Ports in Ihrer Ausgabe vorhanden sein, abhängig davon, welche Dienste auf Ihrem System ausgeführt werden. Der markierte Teil 0.0.0.0:123
der Ausgabe zeigt an, dass der IPv4-UDP-Socket auf allen IPv4-Schnittstellen am Port 123
verfügbar ist. Ein Dienst, der nur auf einer bestimmten IPv4-Adresse verfügbar ist, zeigt nur diese IP im markierten Feld an, z. B. 203.0.113.1:123
.
Führen Sie nun denselben ss
-Befehl erneut aus, jedoch mit dem -6
-Flag:
Sie erhalten eine Ausgabe ähnlich der folgenden:
OutputState Recv-Q Send-Q Local Address:Port Peer Address:Port Process
. . .
UNCONN 0 0 [::]:123 [::]:*
. . .
Es können weitere Zeilen mit anderen Ports in Ihrer Ausgabe vorhanden sein, je nachdem, welche Dienste auf Ihrem System ausgeführt werden. Der markierte Teil [::]:123
der Ausgabe zeigt an, dass der IPv6-TCP-Socket auf allen IPv6-Schnittstellen am Port 123
verfügbar ist (wie durch die ::
-Zeichen angegeben). Ein Dienst, der nur auf einer bestimmten IPv6-Adresse verfügbar ist, zeigt nur diese IP im markierten Feld an, zum Beispiel [2604:a880:400:d1::3d3:6001]:123
.
Testen von Datagramm-Sockets
Jetzt, da Sie wissen, wie Sie UDP-Sockets auf IPv4- und IPv6-Schnittstellen erstellen und aufzählen können, können Sie mit dem Verbinden mit ihnen experimentieren. Wie bei TCP-Sockets können Sie mit dem Dienstprogramm netcat UDP-Sockets verwenden.
Um sich mit dem Beispiel-UDP-Socket am Port 123
zu verbinden, den Sie im vorherigen Abschnitt dieses Tutorials erstellt haben, führen Sie den folgenden netcat-Befehl aus:
- Die
-4
-Flag teilt netcat mit, IPv4 zu verwenden. - Die Option
-u
weist netcat an, UDP anstelle von TCP zu verwenden. - Die
-v
-Flagge wird verwendet, um ausführliche Ausgaben auf Ihrem Terminal anzuzeigen. - Die Option
-z
stellt sicher, dass netcat nur eine Verbindung zu einem Socket herstellt, ohne Daten zu senden. - Die lokale Rückkopplung
127.0.0.1
IP-Adresse wird verwendet, da Ihr System seine eigene eindeutige IP-Adresse haben wird. Wenn Sie die IP-Adresse für Ihr System kennen, können Sie auch damit testen. Zum Beispiel, wenn die öffentliche oder private IP-Adresse Ihres Systems203.0.113.1
ist, könnten Sie diese anstelle der Rückkopplungs-IP verwenden.
Sie erhalten eine Ausgabe wie folgt:
OutputConnection to 127.0.0.1 123 port [udp/ntp] succeeded!
Die Ausgabe zeigt an, dass netcat keinen Fehler empfangen hat vom UDP-Socket, der auf der Rückkopplungs-IP 127.0.0.1
IPv4-Adresse am Port 123
lauscht. Dieses Fehlen einer Fehlerantwort wird verwendet, um zu schlussfolgern, dass der Socket unter 127.0.0.1:123
verfügbar ist. Dieses Verhalten unterscheidet sich von TCP-Sockets, die Pakete austauschen müssen, um zu bestätigen, ob ein Socket verfügbar ist.
Hinweis: Wenn der Socket in diesem Beispiel nicht verfügbar wäre, würde das entfernte System eine ICMP-Typ-3-Nachricht (Ziel nicht erreichbar) mit einem Code von 3 zurücksenden, was darauf hinweist, dass der Port auf dem entfernten Host nicht erreichbar ist.
Die Annahme, dass ein Socket verfügbar ist, basierend auf dem Fehlen einer Fehlerantwort, setzt voraus, dass keine Firewalls oder Konnektivitätsprobleme vorhanden sind, die den ICMP-Verkehr blockieren. Ohne das Senden, Empfangen und Überprüfen von Anwendungsdaten über einen UDP-Socket gibt es keine Garantie, dass ein entfernter UDP-Port geöffnet ist und Pakete akzeptiert.
Jetzt können Sie denselben Verbindungstest wiederholen, jedoch unter Verwendung von IPv6. Führen Sie den folgenden netcat-Befehl aus:
Sie sollten eine Ausgabe wie folgt erhalten:
OutputConnection to ::1 123 port [udp/ntp] succeeded!!
Die Ausgabe zeigt an, dass netcat keinen Fehler empfangen hat vom UDP-Socket, der auf der IPv6-Adresse ::1
an Port 123
lauscht. Erneut wird aus diesem Fehlen einer Fehlerantwort geschlossen, dass der Socket unter ::1:123
verfügbar ist.
Um Ihre Sockets zu bereinigen, müssen Sie den Befehl fg
(Vordergrund) für jeden erstellten socat-Prozess ausführen. Anschließend verwenden Sie CTRL+C
, um jeden socat-Prozess zu schließen.
Führen Sie fg
aus, um die zweite IPv6-socat
-Instanz in den Vordergrund Ihres Terminals zu bringen. Führen Sie dann CTRL+C
aus, um sie zu schließen.
Sie erhalten eine Ausgabe wie folgt:
Outputsudo socat UDP6-LISTEN:123,ipv6only=1,fork /dev/null
Drücken Sie CTRL+C
, um den Prozess zu stoppen.
Führen Sie nun erneut fg
aus, um den ersten IPv4-Socket zu bereinigen. Sie erhalten eine Ausgabe wie folgt:
Outputsudo socat UDP4-LISTEN:123,fork /dev/null
Drücken Sie CTRL+C
, um den Prozess zu stoppen.
Sie haben nun IPv4- und IPv6-UDP-Sockets auf Ihrem System erstellt, untersucht und getestet. Versuchen Sie, mit jedem Tool zu experimentieren, um sich mit den Möglichkeiten vertraut zu machen, wie sie zum Testen und Beheben von UDP-Sockets verwendet werden können.
Was ist ein Unix-Domain-Socket?
Programme, die auf demselben Server ausgeführt werden, können auch miteinander kommunizieren, indem sie Unix-Domain-Sockets (UDS) verwenden. Unix-Domain-Sockets können strömungsbasiert oder datagrammbasiert sein. Beim Verwenden von Domain-Sockets werden Daten zwischen Programmen direkt im Kernel des Betriebssystems über Dateien im Dateisystem des Hosts ausgetauscht. Um Daten über Domain-Sockets zu senden oder zu empfangen, lesen und schreiben Programme in ihre gemeinsame Socket-Datei und umgehen dabei vollständig auf Netzwerksockets und Protokolle.
Unix-Domain-Sockets werden weitgehend von Datenbanksystemen verwendet, die nicht mit einer Netzwerkschnittstelle verbunden sein müssen. Zum Beispiel verwendet MySQL auf Ubuntu standardmäßig eine Datei namens /var/run/mysqld/mysql.sock
für die Kommunikation mit lokalen Clients. Clients lesen von und schreiben in den Socket, ebenso wie der MySQL-Server selbst.
PostgreSQL ist ein weiteres Datenbanksystem, das einen Socket für lokale, nicht-netzwerkbezogene Kommunikation verwendet. Typischerweise verwendet es standardmäßig /run/postgresql/.s.PGSQL.5432
als seine Socket-Datei.
Erstellen von Unix-Domain-Sockets
In den vorherigen Abschnitten haben Sie erkundet, wie TCP mit Strom-Sockets und wie UDP mit Datagramm-Sockets verwendet wird. In diesem Abschnitt werden Sie socat
verwenden, um sowohl strombasierte als auch datenbasierte Unix-Domänen-Sockets zu erstellen, ohne TCP oder UDP zu verwenden, um Daten zur Übertragung über Netzwerke zu kapseln. Anschließend werden Sie die erstellten Sockets mithilfe der Befehle ss
und nc
untersuchen. Schließlich werden Sie erfahren, wie Unix-Domänen-Sockets mithilfe von Netcat getestet werden können.
Um zu beginnen, führen Sie die folgenden socat
-Befehle aus, um zwei Socket-Dateien zu erstellen:
- Der erste Befehl weist socat an, einen Socket mit dem Adresstyp
unix-listen
zu erstellen, was einen strombasierten UDS erzeugt. - Der zweite Befehl legt
unix-recvfrom
als den Socket-Typ fest, was einen datenbasierten UDS erzeugt. - Beide Befehle geben einen Dateinamen nach dem Trennzeichen
:
an. Der Dateiname ist die Adresse des Sockets selbst. Im ersten Beispiel für einen Strom wird er/tmp/stream.sock
und im zweiten Beispiel für ein Datagramm/tmp/datagram.sock
sein. Beachten Sie, dass der Name eines Sockets beliebig ist, aber es hilft bei der Fehlerbehebung, wenn er beschreibend ist. - Die Argumente
fork
und/dev/null
werden auf dieselbe Weise verwendet wie in den Abschnitten zu den Beispiel für Strom- und Datagramm-Sockets.
Jetzt, da Sie Ihre beiden UDS-Sockets erstellt haben, können Sie sie mithilfe der Dienstprogramme ss
und nc
untersuchen.
Untersuchung von Unix-Domänen-Sockets
Um alle lauschenden Unix-Domänen-Sockets aufzulisten, führen Sie den Befehl ss -xln
aus. Das x
-Flag stellt sicher, dass nur Domänen-Sockets angezeigt werden.
Sie erhalten eine Ausgabe wie folgt:
OutputNetid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
. . .
u_str LISTEN 0 5 /tmp/stream.sock 436470 * 0
u_dgr UNCONN 0 0 /tmp/datagram.sock 433843 * 0
. . .
Beachten Sie den hervorgehobenen Teil u_str
der Zeile /tmp/stream/sock
. Dieses Feld zeigt an, dass der Socket-Typ ein Strom-basierter UDS ist. Die zweite Zeile zeigt den Typ u_dgr
, was bedeutet, dass der Socket-Typ datagrammbasiert ist.
Da Unix-Domänen-Sockets Dateien sind, können die üblichen Linux-Benutzer- und Gruppenberechtigungen sowie Zugriffssteuerungen verwendet werden, um zu beschränken, wer sich mit dem Socket verbinden kann. Sie können auch Dateisystem-Tools wie ls
, mv
, chown
und chmod
verwenden, um UDS-Dateien zu untersuchen und zu manipulieren. Tools wie SELinux können auch verwendet werden, um UDS-Dateien mit unterschiedlichen Sicherheitskontexten zu kennzeichnen.
Um festzustellen, ob eine Datei ein UDS-Socket ist, verwenden Sie die Dienstprogramme ls
, file
oder stat
. Es ist jedoch wichtig zu beachten, dass keines dieser Tools feststellen kann, ob ein UDS strom- oder datagrammbasiert ist. Verwenden Sie das Tool ss
für die vollständigsten Informationen über einen Unix-Domänen-Socket.
Um einen Socket im Dateisystem zu untersuchen, zeigt das Dienstprogramm stat
die relevantesten Informationen an. Führen Sie es auf den Sockets aus, die Sie zuvor erstellt haben:
Sie erhalten Ausgaben wie folgt:
Output File: /tmp/stream.sock
Size: 0 Blocks: 1 IO Block: 131072 socket
Device: 48h/72d Inode: 1742 Links: 1
Access: (0755/srwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2021-03-01 18:10:25.025755168 +0000
Modify: 2021-03-01 18:10:25.025755168 +0000
Change: 2021-03-01 18:22:42.678231700 +0000
Birth: -
File: /tmp/datagram.sock
Size: 0 Blocks: 1 IO Block: 131072 socket
Device: 48h/72d Inode: 1743 Links: 1
Access: (0755/srwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2021-03-01 18:10:25.025755168 +0000
Modify: 2021-03-01 18:10:25.025755168 +0000
Change: 2021-03-01 18:10:25.025755168 +0000
Birth: -
Bemerken Sie, dass für jede Datei der Typ socket
ist (am äußersten rechten Rand der Ausgabe hervorgehoben) und der Zugriffsmodus ein s
-Zeichen vor den Berechtigungen der Datei hat.
Das Dienstprogramm ls
zeigt auch an, ob eine Datei ein Socket ist. Führen Sie ls -l
aus, um die Dateien zu untersuchen:
Sie erhalten Ausgaben wie folgt. Beachten Sie erneut, dass für Sockets der Dateimodus das s
-Zeichen vor den Dateiberechtigungsfeldern enthält:
Outputsrwxr-xr-x 1 root root 0 Mar 1 18:10 /tmp/datagram.sock
srwxr-xr-x 1 root root 0 Mar 1 18:10 /tmp/stream.sock
Jetzt, da Sie Unix-Domänensockets erstellt und gelernt haben, sie mithilfe des ss
und verschiedener dateisystembasierter Tools zu untersuchen, ist der nächste Schritt, die Sockets mithilfe eines Tools wie netcat zu testen.
Testen von Unix-Domänensockets
Das Dienstprogramm netcat kann verwendet werden, um eine Verbindung zu Unix-Domänensockets herzustellen, sowie zu TCP- und UDP-Sockets, die Sie bereits in diesem Tutorial kennengelernt haben. Um zu den Beispiel-Sockets, die Sie erstellt haben, eine Verbindung herzustellen, müssen Sie beim Ausführen des netcat-Befehls eine zusätzliche -U
-Flag angeben. Diese Flagge sagt netcat, dass es eine Verbindung zu einem UDS herstellen soll, im Gegensatz zu einem TCP- oder UDP-basierten Netzwerksocket.
Zusätzlich verwenden Sie, falls der Socket datagrammbasiert ist, die -u
-Flagge, um netcat anzuweisen, Datagramme zu verwenden, wie wir es im Abschnitt über Datagrammsockets dieses Tutorials gelernt haben.
Lassen Sie uns beginnen, UDS-Sockets zu untersuchen, indem Sie sich mit dem streambasierten Socket mit folgendem Befehl verbinden:
Das -U
sagt netcat, dass es sich um eine Unix-Domain-Socket-Verbindung handelt. Die Option -z
stellt sicher, dass netcat nur eine Verbindung zu einem Socket herstellt, ohne Daten zu senden. /tmp/stream.sock
ist die Adresse des Sockets im Dateisystem.
Sie erhalten keine Ausgabe von netcat, wenn Sie den Befehl ausführen. Wenn jedoch ein Socket nicht verfügbar ist, gibt netcat eine Fehlermeldung wie folgt aus:
Outputnc: unix connect failed: No such file or directory
nc: /tmp/stream.sock: No such file or directory
Die Abwesenheit einer Ausgabe von netcat beim Testen eines streambasierten UDS-Sockets bedeutet daher, dass die Verbindung erfolgreich war.
Wiederholen Sie den Testvorgang, diesmal für den datenorientierten UDS:
Das zusätzliche Flag -u
wird hinzugefügt, um netcat mitzuteilen, dass es sich bei dem entfernten Socket um einen Datagrammsocket handelt. Auch hier erhalten Sie keine Ausgabe, wenn der Test erfolgreich ist.
Wenn keine Socketadresse vorhanden ist, erhalten Sie einen Fehler wie folgt:
Outputnc: unix connect failed: No such file or directory
nc: /tmp/datagram.sock: No such file or directory
Um Ihre Sockets zu bereinigen, müssen Sie den Befehl fg
(Vordergrund) für jeden erstellten socat-Prozess ausführen. Dann verwenden Sie STRG+C
, um jeden socat zu schließen.
Führen Sie fg
aus, um die datenbasierte socat
-Instanz in den Vordergrund Ihres Terminals zu bringen:
Sie erhalten eine Ausgabe wie folgt:
Outputsocat unix-recvfrom:/tmp/datagram.sock,fork /dev/null
Drücken Sie STRG+C
, um sie zu schließen. Sie erhalten keine Ausgabe.
Führen Sie jetzt erneut fg
aus, um den ersten streambasierten UDS-Socket zu bereinigen.
Auch hier sollten Sie eine Ausgabe wie folgt haben:
Outputsocat unix-listen:/tmp/stream.sock,fork /dev/null
Führen Sie CTRL+C
aus, um den Prozess zu beenden. Sie erhalten keine Ausgabe.
Sie haben nun Unix-Datagramm-Sockets auf Ihrem System erstellt, untersucht und getestet. Versuchen Sie, mit Netcat und socat
zu experimentieren, um sich besser damit vertraut zu machen, wie Sie Daten über ein UDS senden und empfangen können, sowie wie Sie Unix-Domänen-Sockets testen und Fehler beheben können.
Schlussfolgerung
In diesem Tutorial haben Sie erkundet, wie verschiedene Arten von Sockets auf einem Linux-System verwendet werden. Sie haben gelernt, wie Stream-basierte Sockets, die in der Regel TCP für die Netzwerkkommunikation verwenden, funktionieren. Sie haben auch gelernt, wie Datagramm-basierte Sockets, die UDP verwenden, um Daten über Netzwerke zu senden, funktionieren. Schließlich haben Sie erkundet, wie Unix-Domänen-Sockets auf einem lokalen Server entweder stream- oder datagrammbasiert sein können.
In jedem Abschnitt haben Sie das Dienstprogramm ss
verwendet, um Informationen über Sockets auf einem Linux-System zu sammeln. Sie haben gelernt, wie die verschiedenen Flaggen, die das ss
-Werkzeug bereitstellt, Ihnen helfen können, seine Ausgabe auf bestimmte Arten von Sockets zu beschränken, wenn Sie Sockets auf einem System untersuchen.
Schließlich haben Sie die Netcat- und Socat-Tools verwendet, um jede der drei verschiedenen Arten von Sockets zu erstellen und eine Verbindung herzustellen, die in diesem Tutorial besprochen wurden. Das Netcat-Dienstprogramm wird häufig verwendet, um eine Verbindung zu Sockets herzustellen, kann jedoch auch Sockets erstellen. Seine Dokumentation (man nc) enthält viele Beispiele dafür, wie es in beiden Modi verwendet werden kann. Das Socat-Dienstprogramm ist ein fortschrittlicheres Tool, das verwendet werden kann, um eine Verbindung zu vielen verschiedenen Arten von Sockets herzustellen, die in diesem Tutorial nicht behandelt werden. Seine Dokumentation (man socat) enthält ebenfalls zahlreiche Beispiele für die verschiedenen Möglichkeiten, wie es verwendet werden kann.
Das Verständnis dessen, was Sockets sind und wie sie funktionieren, ist eine grundlegende Fähigkeit der Systemadministration. Die Werkzeuge und Techniken, mit denen Sie in diesem Tutorial experimentiert haben, werden Ihnen helfen, sich mit Sockets vertrauter zu machen und zu verstehen, wie Sie sie diagnostizieren können, wenn Ihre Server und Anwendungen nicht korrekt miteinander kommunizieren.
Source:
https://www.digitalocean.com/community/tutorials/understanding-sockets