Creare un servizio WSS
Domanda:
Come può Workerman creare un servizio WSS in modo che i client possano connettersi tramite il protocollo WSS, ad esempio in una mini app WeChat?
Risposta:
Il protocollo WSS è in realtà websocket+SSL, ovvero si aggiunge uno strato di SSL al protocollo websocket, simile a https (http+SSL).
Quindi, è sufficiente attivare SSL sulla base del protocollo websocket per supportare il protocollo WSS.
Metodo 1: Utilizzare Nginx/Apache per proxy SSL (raccomandato)
Motivi per la raccomandazione
- Può riutilizzare la porta 443, i client non necessitano di specificare la porta durante la connessione
- Gestione centralizzata dei certificati SSL, configurazione del sito web riutilizzabile
- Funzionalità di bilanciamento del carico
- Include monitoraggio dei log
- Maggiore compatibilità
Principio di comunicazione e flusso
-
Il client avvia una connessione WSS a Nginx/Apache.
-
Nginx/Apache converte i dati del protocollo WSS in dati del protocollo WS e li inoltra alla porta del protocollo websocket di Workerman.
-
Workerman elabora i dati ricevuti secondo la logica aziendale.
-
Quando Workerman invia un messaggio al client, il processo è inverso: i dati sono convertiti tramite Nginx/Apache in protocollo WSS e poi inviati al client.
Configurazione di Nginx di riferimento
Prerequisiti e preparativi:
-
Nginx già installato, versione non inferiore a 1.3.
-
Si presuppone che Workerman stia ascoltando sulla porta 8282 (protocollo websocket).
-
Certificato già richiesto (file pem/crt e file key), presupponendo che sia stato posizionato in /etc/nginx/conf.d/ssl.
-
Si prevede di utilizzare Nginx per aprire la porta 443 offrendo un servizio di proxy WSS (la porta può essere modificata se necessario).
-
Nginx di solito funge da server web per altri servizi; per non influenzare l'uso del sito originale, qui viene utilizzato l'indirizzo
dominio.com/wsscome ingresso per il proxy WSS. Quindi, l'indirizzo di connessione del client sarà wss://dominio.com/wss.
La configurazione di Nginx è simile al seguente:
server {
listen 443;
# Configurazione del dominio omessa...
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 / {} Altre configurazioni del sito...
}
Test
// Il certificato verificherà il dominio, si prega di utilizzare il dominio per connettersi. Si noti che non viene specificata la porta.
ws = new WebSocket("wss://dominio.com/wss");
ws.onopen = function() {
alert("Connessione riuscita");
ws.send('tom');
alert("Invio una stringa al server: tom");
};
ws.onmessage = function(e) {
alert("Messaggio ricevuto dal server: " + e.data);
};
Utilizzare Apache come proxy per WSS
È possibile utilizzare Apache come proxy per inoltrare a Workerman.
Preparativi:
-
GatewayWorker ascolta sulla porta 8282 (protocollo websocket).
-
Certificato SSL già richiesto, presupponendo che sia posizionato in /server/httpd/cert/.
-
Utilizzare Apache per inoltrare la porta 443 alla porta specificata 8282.
-
httpd-ssl.conf è stato caricato.
-
openssl è installato.
Abilitare il modulo proxy_wstunnel_module
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
Configurare SSL e proxy
#extra/httpd-ssl.conf
DocumentRoot "/percorso/del/sito"
ServerName dominio
# Configurazione del proxy
SSLProxyEngine on
ProxyRequests Off
ProxyPass /wss ws://127.0.0.1:8282/wss
ProxyPassReverse /wss ws://127.0.0.1:8282/wss
# Aggiungere supporto per i protocolli SSL, rimuovere i protocolli non sicuri
SSLProtocol all -SSLv2 -SSLv3
# Modificare la suite di cifratura come segue
SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM
SSLHonorCipherOrder on
# Configurazione della chiave pubblica del certificato
SSLCertificateFile /server/httpd/cert/your.pem
# Configurazione della chiave privata del certificato
SSLCertificateKeyFile /server/httpd/cert/your.key
# Configurazione della catena di certificati,
SSLCertificateChainFile /server/httpd/cert/chain.pem
Test
// Il certificato verificherà il dominio, si prega di utilizzare il dominio per connettersi. Si noti che non viene specificata la porta.
ws = new WebSocket("wss://dominio.com/wss");
ws.onopen = function() {
alert("Connessione riuscita");
ws.send('tom');
alert("Invio una stringa al server: tom");
};
ws.onmessage = function(e) {
alert("Messaggio ricevuto dal server: " + e.data);
};
Metodo 2, attivare direttamente SSL con Workerman (non raccomandato)
Attenzione
È possibile scegliere solo tra Nginx/Apache per il proxy SSL e Workerman impostazione SSL; non possono essere attivati contemporaneamente.
Preparativi:
-
Versione di Workerman >=3.3.7.
-
L'estensione openssl deve essere installata in PHP.
-
Certificato già richiesto (file pem/crt e file key) posizionato in qualsiasi directory del disco.
Codice:
<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
// È preferibile utilizzare un certificato richiesto
$context = array(
// Ulteriori opzioni ssl possono essere consultate nel manuale http://php.net/manual/it/context.ssl.php
'ssl' => array(
// Si prega di utilizzare il percorso assoluto
'local_cert' => 'percorso/disco/server.pem', // può essere anche un file crt
'local_pk' => 'percorso/disco/server.key',
'verify_peer' => false,
'allow_self_signed' => true, // Se il certificato è autofirmato, questa opzione deve essere attivata
)
);
// Qui viene impostato il protocollo websocket (porta a piacere, ma deve essere assicurato che non sia occupata da altri programmi)
$worker = new Worker('websocket://0.0.0.0:8282', $context);
// Impostare il transport per abilitare ssl, websocket+ssl ovvero wss
$worker->transport = 'ssl';
$worker->onMessage = function(TcpConnection $con, $msg) {
$con->send('ok');
};
Worker::runAll();
Con il codice di cui sopra, Workerman ha iniziato ad ascoltare il protocollo WSS; il client può connettersi a Workerman tramite il protocollo WSS per comunicazioni sicure in tempo reale.
Test
Aprire il browser Chrome, premere F12 per aprire la console di debugging, inserire nella scheda Console (o inserire il codice qui sotto in una pagina HTML e utilizzarlo con js)
// Il certificato verificherà il dominio, si prega di utilizzare il dominio per connettersi, si noti che deve essere specificata la porta
ws = new WebSocket("wss://dominio.com:8282");
ws.onopen = function() {
alert("Connessione riuscita");
ws.send('tom');
alert("Invio una stringa al server: tom");
};
ws.onmessage = function(e) {
alert("Messaggio ricevuto dal server: " + e.data);
};
Errori comuni
SSL routines:SSL23_GET_CLIENT_HELLO:http request
La causa è che il client utilizza ws://dominio.com per accedere, mentre l'indirizzo corretto dovrebbe essere wss://dominio.com, quindi deve essere utilizzato wss all'inizio.
Questa situazione si verifica principalmente quando la porta era originariamente ws, ma è stata cambiata in wss senza aggiornare alcune pagine client, che continuano ad accedere in modo ws, causando l'errore.
Questo errore può essere ignorato e non influisce sulla normale connessione wss.
Attenzione:
-
Se è necessario utilizzare la porta 443, si prega di utilizzare la prima soluzione basata su proxy Nginx/Apache per implementare wss.
-
La porta wss può essere accessibile solo tramite il protocollo wss, mentre ws non può accedere alla porta wss.
-
I certificati sono generalmente legati ai domini, quindi si prega di utilizzare il dominio per la connessione durante i test e non utilizzare l'IP.
-
Se si verifica un problema di accesso, controllare il firewall del server.
-
Questo metodo richiede PHP versione >=5.6, poiché le mini app WeChat richiedono tls1.2, e le versioni PHP inferiori a 5.6 non supportano tls1.2.
Articoli correlati:
Ottenere l'IP reale del client tramite proxy
Riferimento per le opzioni di contesto SSL di Workerman