Erstellen eines wss-Dienstes
Frage:
Wie erstelle ich mit Workerman einen wss-Dienst, sodass der Client über wss kommunizieren kann, beispielsweise in einer WeChat Mini-Programm, das eine Verbindung zum Server herstellt.
Antwort:
Das wss-Protokoll ist im Grunde websocket+SSL, was bedeutet, dass eine SSL-Schicht über das websocket-Protokoll gelegt wird, ähnlich wie https (http+SSL). Daher ist es notwendig, einfach die SSL -Unterstützung für das websocket-Protokoll zu aktivieren, um das wss-Protokoll zu unterstützen.
Methode 1: Nutzung von nginx/apache zur Proxyierung von SSL (empfohlen)
Empfehlungsdetails
- Der Port 443 kann wiederverwendet werden, sodass der Client beim Verbinden keinen Port angeben muss.
- SSL-Zertifikate werden zentral verwaltet und Website-Konfigurationen können wiederverwendet werden.
- Lastenausgleich ist möglich.
- Die Protokollüberwachung ist integriert.
- Bessere Kompatibilität.
Kommunikationsprinzip und Ablauf
-
Der Client initiiert eine wss-Verbindung zu nginx/apache.
-
Nginx/apache konvertiert die wss-Protokolldaten in ws-Protokolldaten und leitet sie an den websocket-Protokollport von Workerman weiter.
-
Workerman verarbeitet die Daten mit der Geschäftslogik.
-
Wenn Workerman eine Nachricht an den Client sendet, erfolgt der Prozess umgekehrt: Die Daten werden durch nginx/apache in das wss-Protokoll konvertiert und an den Client gesendet.
Nginx Konfigurationsreferenz
Voraussetzungen und Vorbereitungen:
-
Nginx ist bereits installiert, Version nicht älter als 1.3.
-
Angenommen, Workerman lauscht auf dem 8282 Port (websocket-Protokoll).
-
Ein Zertifikat wurde beantragt (pem/crt-Datei und key-Datei), angenommen, es wurde im Verzeichnis /etc/nginx/conf.d/ssl abgelegt.
-
Es wird beabsichtigt, nginx zu verwenden, um Port 443 anzubieten, um den wss-Proxy-Dienst bereitzustellen (der Port kann je nach Bedarf geändert werden).
-
Nginx wird üblicherweise als Webserver betrieben, um andere Dienste auszuführen. Um die Verwendung der ursprünglichen Website nicht zu beeinträchtigen, wird hier die Adresse
domain.com/wssals Proxy-Eingang zum wss verwendet. Das bedeutet, dass die Client-Verbindungsadresse wss://domain.com/wss ist.
Die nginx-Konfiguration sieht ungefähr wie folgt aus:
server {
listen 443;
# Domain-Konfiguration weggelassen...
ssl on;
ssl_certificate /etc/ssl/server.pem;
ssl_certificate_key /etc/ssl/server.key;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_protocols SSLv3 SSLv2 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
location /wss
{
proxy_pass http://127.0.0.1:8282;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Real-IP $remote_addr;
}
# location / {} Weitere Konfigurationen der Website...
}
Test
// Das Zertifikat prüft die Domain, bitte verwenden Sie die Domäne für die Verbindung. Beachten Sie, dass kein Port angegeben wird.
ws = new WebSocket("wss://domain.com/wss");
ws.onopen = function() {
alert("Verbindung erfolgreich");
ws.send('tom');
alert("Gesendet an den Server: ein String: tom");
};
ws.onmessage = function(e) {
alert("Nachricht vom Server erhalten: " + e.data);
};
Verwendung von Apache zur WSS-Proxyierung
Es besteht auch die Möglichkeit, Apache als wss-Proxy zu verwenden und an Workerman weiterzuleiten.
Vorbereitungen:
-
GatewayWorker hört auf Port 8282 (websocket-Protokoll).
-
Ein SSL-Zertifikat wurde beantragt, angenommen, es wurde im Verzeichnis /server/httpd/cert/ abgelegt.
-
Apache wird verwendet, um Port 443 auf den angegebenen Port 8282 weiterzuleiten.
-
httpd-ssl.conf ist geladen.
-
openssl ist installiert.
Aktivieren Sie das Modul proxy_wstunnel_module
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
SSL und Proxy konfigurieren
#extra/httpd-ssl.conf
DocumentRoot "/Webseite/Verzeichnis"
ServerName domain.com
# Proxy Konfiguration
SSLProxyEngine on
ProxyRequests Off
ProxyPass /wss ws://127.0.0.1:8282/wss
ProxyPassReverse /wss ws://127.0.0.1:8282/wss
# SSL-Protokoll unterstützender Protokolle, unsichere Protokolle entfernen
SSLProtocol all -SSLv2 -SSLv3
# Ändern Sie die Cipher-Suite wie folgt
SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM
SSLHonorCipherOrder on
# Zertifikat öffentliche Schlüssel Konfiguration
SSLCertificateFile /server/httpd/cert/your.pem
# Zertifikat private Schlüssel Konfiguration
SSLCertificateKeyFile /server/httpd/cert/your.key
# Zertifikat-Kettenkonfiguration
SSLCertificateChainFile /server/httpd/cert/chain.pem
Test
// Das Zertifikat prüft die Domain, bitte verwenden Sie die Domäne für die Verbindung. Beachten Sie, dass kein Port angegeben wird.
ws = new WebSocket("wss://domain.com/wss");
ws.onopen = function() {
alert("Verbindung erfolgreich");
ws.send('tom');
alert("Gesendet an den Server: ein String: tom");
};
ws.onmessage = function(e) {
alert("Nachricht vom Server erhalten: " + e.data);
};
Methode 2: Direktes Öffnen von SSL mit Workerman (nicht empfohlen)
Achtung
Nginx/Apache zur Proxyierung von SSL oder Workerman zur Einrichtung von SSL sind sich gegenseitig ausschließend und können nicht gleichzeitig aktiviert sein.
Vorbereitungen:
-
Workerman Version >= 3.3.7.
-
PHP hat die openssl-Erweiterung installiert.
-
Ein Zertifikat wurde beantragt (pem/crt-Datei und key-Datei), das sich an einem beliebigen Ort auf der Festplatte befindet.
Code:
<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
// Das Zertifikat sollte nach Möglichkeit ein beantragtes Zertifikat sein.
$context = array(
// Weitere SSL-Optionen siehe Handbuch http://php.net/manual/de/context.ssl.php
'ssl' => array(
// Bitte verwenden Sie den absoluten Pfad
'local_cert' => 'Pfad/zur/Festplatte/server.pem', // kann auch eine crt-Datei sein
'local_pk' => 'Pfad/zur/Festplatte/server.key',
'verify_peer' => false,
'allow_self_signed' => true, // muss aktiviert sein, wenn es sich um ein selbstsigniertes Zertifikat handelt
)
);
// Hier wird das websocket-Protokoll eingestellt (beliebiger Port, muss jedoch verfügbar sein).
$worker = new Worker('websocket://0.0.0.0:8282', $context);
// Setzen Sie den Transport auf SSL, websocket+ssl ist also wss.
$worker->transport = 'ssl';
$worker->onMessage = function(TcpConnection $con, $msg) {
$con->send('ok');
};
Worker::runAll();
Mit dem obigen Code hört Workerman auf dem wss-Protokoll, und der Client kann eine Verbindung über das wss-Protokoll herstellen, um sichere Echtzeitkommunikation zu erreichen.
Test
Öffnen Sie den Chrome-Browser, drücken Sie F12, um die Entwicklerkonsole zu öffnen, geben Sie in der Konsole Folgendes ein (oder fügen Sie den folgenden Code in eine HTML-Seite ein und führen Sie ihn mit JS aus):
// Das Zertifikat prüft die Domain, bitte verwenden Sie die Domäne für die Verbindung, beachten Sie, dass hier eine Portnummer angegeben ist.
ws = new WebSocket("wss://domain.com:8282");
ws.onopen = function() {
alert("Verbindung erfolgreich");
ws.send('tom');
alert("Gesendet an den Server: ein String: tom");
};
ws.onmessage = function(e) {
alert("Nachricht vom Server erhalten: " + e.data);
};
Häufige Fehler
SSL routines:SSL23_GET_CLIENT_HELLO:http request
Der Grund ist, dass der Client mit ws://domain.com aufgerufen wird, was zu diesem Fehler führt. Die richtige Adresse sollte wss://domain.com sein, die mit wss beginnt. Dieses Problem tritt häufig auf, weil der ursprüngliche Port ws war und nach der Umstellung auf wss einige Client-Seiten nicht aktualisiert wurden und weiterhin ws aufgerufen werden, was zu einem Fehler führt. Dieser Fehler kann ignoriert werden, da er die normale wss-Verbindung nicht beeinträchtigt.
Hinweis:
-
Wenn der Port 443 unbedingt verwendet werden muss, verwenden Sie bitte die obige erste Methode, um wss über nginx/apache zu realisieren.
-
Der wss-Port kann nur über das wss-Protokoll aufgerufen werden, ws kann nicht auf den wss-Port zugreifen.
-
Zertifikate sind in der Regel an Domains gebunden, sodass der Client bitte die Domain verwenden soll, wenn getestet wird, und nicht die IP.
-
Wenn der Zugriff fehlschlägt, überprüfen Sie bitte die Firewall des Servers.
-
Diese Methode setzt PHP-Versionen >= 5.6 voraus, da WeChat Mini-Programme tls1.2 erfordern und PHP-Versionen unter 5.6 tls1.2 nicht unterstützen.
Verwandte Artikel:
Echte IP des Clients über Proxy abrufen
Referenz zu SSL-Kontextoptionen von Workerman