Créer un service wss
Question :
Comment Workerman peut-il créer un service wss pour que les clients puissent se connecter via le protocole wss, par exemple dans une application WeChat Mini Program ?
Réponse :
Le protocole wss est en fait websocket + SSL, c'est donc le protocole websocket avec une couche SSL ajoutée, similaire à https (http + SSL). Ainsi, il suffit d'activer SSL sur le protocole websocket pour supporter le protocole wss.
Méthode 1 : Utiliser nginx/apache pour proxy SSL (Recommandé)
Raisons de la recommandation
- Peut réutiliser le port 443, le client n'a pas besoin de spécifier le port lors de la connexion
- Gestion centralisée des certificats SSL, peut réutiliser la configuration du site
- Peut être utilisé pour la répartition de charge
- Inclut la surveillance des journaux
- Meilleure compatibilité
Principe et processus de communication
-
Le client initie la connexion wss vers nginx/apache
-
nginx/apache convertit les données du protocole wss en données du protocole ws et les transmet au port du protocole websocket de Workerman
-
Workerman reçoit les données et effectue le traitement de la logique métier
-
Lorsque Workerman envoie un message au client, c'est l'inverse : les données sont converties par nginx/apache en protocole wss et envoyées au client
Configuration nginx de référence
Conditions préalables et préparation :
-
nginx déjà installé, version supérieure ou égale à 1.3
-
Supposons que Workerman écoute sur le port 8282 (protocole websocket)
-
Un certificat a déjà été demandé (fichiers pem/crt et fichier key) supposé placé dans /etc/nginx/conf.d/ssl
-
Préparation à utiliser nginx pour ouvrir le port 443 et fournir un service proxy wss (le port peut être modifié selon les besoins)
-
Nginx fonctionne généralement comme un serveur de site Web pour d'autres services et, afin de ne pas affecter l'utilisation du site d'origine, l'adresse
domain.com/wssest utilisée comme point d'entrée pour le proxy wss. Cela signifie que l'adresse de connexion du client est wss://domain.com/wss
Configuration nginx similaire à ceci :
server {
listen 443;
# Configuration du nom de domaine omise...
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 / {} Autres configurations du site...
}
Test
// Le certificat vérifiera le nom de domaine, veuillez utiliser un nom de domaine pour vous connecter. Notez qu'il ne faut pas spécifier le port
ws = new WebSocket("wss://domain.com/wss");
ws.onopen = function() {
alert("Connexion réussie");
ws.send('tom');
alert("Envoyer une chaîne au serveur : tom");
};
ws.onmessage = function(e) {
alert("Message reçu du serveur : " + e.data);
};
Utiliser apache pour proxy wss
Vous pouvez également utiliser apache comme proxy wss pour le transmettre à Workerman.
Préparation :
-
GatewayWorker écoute sur le port 8282 (protocole websocket)
-
Un certificat ssl a déjà été demandé, supposé placé sous /server/httpd/cert/
-
Utiliser apache pour transférer le port 443 vers le port spécifié 8282
-
httpd-ssl.conf a été chargé
-
OpenSSL est installé
Activer le module proxy_wstunnel_module
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
Configurer SSL et le proxy
#extra/httpd-ssl.conf
DocumentRoot "/répertoire/site"
ServerName domaine
# Configuration du Proxy
SSLProxyEngine on
ProxyRequests Off
ProxyPass /wss ws://127.0.0.1:8282/wss
ProxyPassReverse /wss ws://127.0.0.1:8282/wss
# Ajouter le support des protocoles SSL, en supprimant les protocoles non sécurisés
SSLProtocol all -SSLv2 -SSLv3
# Modifier les suites de chiffrement comme suit
SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM
SSLHonorCipherOrder on
# Configuration de la clé publique du certificat
SSLCertificateFile /server/httpd/cert/your.pem
# Configuration de la clé privée du certificat
SSLCertificateKeyFile /server/httpd/cert/your.key
# Configuration de la chaîne de certificats
SSLCertificateChainFile /server/httpd/cert/chain.pem
Test
// Le certificat vérifiera le nom de domaine, veuillez utiliser un nom de domaine pour vous connecter. Notez qu'il n'y a pas de port
ws = new WebSocket("wss://domain.com/wss");
ws.onopen = function() {
alert("Connexion réussie");
ws.send('tom');
alert("Envoyer une chaîne au serveur : tom");
};
ws.onmessage = function(e) {
alert("Message reçu du serveur : " + e.data);
};
Méthode 2, activer SSL directement avec Workerman (non recommandé)
Attention
nginx/apache proxy SSL et Workerman réglage SSL ne peuvent pas être activés simultanément, choisissez l'un ou l'autre.
Préparation :
-
Version de Workerman >= 3.3.7
-
PHP avec l'extension openssl installée
-
Certificat déjà demandé (fichiers pem/crt et key) placé dans n'importe quel répertoire sur le disque
Code :
<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
// Mieux vaut utiliser un certificat demandé
$context = array(
// Pour plus d'options ssl, veuillez consulter le manuel http://php.net/manual/zh/context.ssl.php
'ssl' => array(
// Veuillez utiliser un chemin absolu
'local_cert' => 'chemin/vers/le/certificat/server.pem', // Peut aussi être un fichier crt
'local_pk' => 'chemin/vers/le/certificat/server.key',
'verify_peer' => false,
'allow_self_signed' => true, // Cette option doit être activée si c'est un certificat auto-signé
)
);
// Ici, le protocole websocket est défini (port arbitraire, mais doit être libre)
$worker = new Worker('websocket://0.0.0.0:8282', $context);
// Définir le transport pour activer ssl, websocket+ssl c'est wss
$worker->transport = 'ssl';
$worker->onMessage = function(TcpConnection $con, $msg) {
$con->send('ok');
};
Worker::runAll();
Avec ce code, Workerman écoutera le protocole wss et le client pourra se connecter à Workerman via le protocole wss pour réaliser une communication instantanée sécurisée.
Test
Ouvrez le navigateur chrome, appuyez sur F12 pour ouvrir la console de débogage, entrez dans l'onglet Console (ou mettez le code ci-dessous dans une page html pour l'exécuter avec js)
// Le certificat vérifiera le nom de domaine, veuillez utiliser un nom de domaine pour vous connecter, notez qu'un numéro de port est spécifié ici
ws = new WebSocket("wss://domain.com:8282");
ws.onopen = function() {
alert("Connexion réussie");
ws.send('tom');
alert("Envoyer une chaîne au serveur : tom");
};
ws.onmessage = function(e) {
alert("Message reçu du serveur : " + e.data);
};
Erreurs courantes
SSL routines:SSL23_GET_CLIENT_HELLO:http request
La raison en est que le client essaie d'accéder via ws://domain.com, ce qui est incorrect. L'adresse d'accès correcte doit être wss://domain.com, c'est-à-dire qu'elle doit commencer par wss. Ce problème se produit le plus souvent lorsque le port était initialement ws et a été soudainement changé en wss alors que certaines interfaces clientes n'ont pas été actualisées, continuant à accéder via ws, ce qui entraîne une erreur. Cette erreur peut être ignorée, elle n'affecte pas la connexion normale wss.
Remarques :
-
Si vous devez absolument utiliser le port 443, veuillez utiliser la première méthode avec le proxy nginx/apache pour réaliser le wss.
-
Le port wss ne peut être accessible que via le protocole wss, le ws ne peut pas accéder au port wss.
-
Les certificats sont généralement liés au nom de domaine, donc pour les tests, veuillez vous connecter via le nom de domaine, ne pas utiliser l'ip.
-
Si des problèmes d'accès se produisent, vérifiez le pare-feu du serveur.
-
Cette méthode nécessite PHP version >= 5.6, car l'application WeChat Mini Program nécessite tls1.2, et les versions inférieures à PHP 5.6 ne supportent pas tls1.2.
Articles connexes :
Obtenir l'IP réelle du client via un proxy
Options de contexte SSL de Workerman