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

  1. Der Client initiiert eine wss-Verbindung zu nginx/apache.

  2. Nginx/apache konvertiert die wss-Protokolldaten in ws-Protokolldaten und leitet sie an den websocket-Protokollport von Workerman weiter.

  3. Workerman verarbeitet die Daten mit der Geschäftslogik.

  4. 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:

  1. Nginx ist bereits installiert, Version nicht älter als 1.3.

  2. Angenommen, Workerman lauscht auf dem 8282 Port (websocket-Protokoll).

  3. Ein Zertifikat wurde beantragt (pem/crt-Datei und key-Datei), angenommen, es wurde im Verzeichnis /etc/nginx/conf.d/ssl abgelegt.

  4. 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).

  5. 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/wss als 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:

  1. GatewayWorker hört auf Port 8282 (websocket-Protokoll).

  2. Ein SSL-Zertifikat wurde beantragt, angenommen, es wurde im Verzeichnis /server/httpd/cert/ abgelegt.

  3. Apache wird verwendet, um Port 443 auf den angegebenen Port 8282 weiterzuleiten.

  4. httpd-ssl.conf ist geladen.

  5. 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:

  1. Workerman Version >= 3.3.7.

  2. PHP hat die openssl-Erweiterung installiert.

  3. 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:

  1. Wenn der Port 443 unbedingt verwendet werden muss, verwenden Sie bitte die obige erste Methode, um wss über nginx/apache zu realisieren.

  2. Der wss-Port kann nur über das wss-Protokoll aufgerufen werden, ws kann nicht auf den wss-Port zugreifen.

  3. Zertifikate sind in der Regel an Domains gebunden, sodass der Client bitte die Domain verwenden soll, wenn getestet wird, und nicht die IP.

  4. Wenn der Zugriff fehlschlägt, überprüfen Sie bitte die Firewall des Servers.

  5. 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