wss servisi oluşturma

Soru:

Workerman ile client'ların wss protokolü üzerinden bağlantı kurarak iletişim kurmasını sağlayacak bir wss servisi nasıl oluşturulur? Örneğin, bir WeChat mini programında sunucuya nasıl bağlanılır?

Cevap:

wss protokolü aslında websocket+SSL'dir, yani websocket protokolüne bir SSL katmanı eklenmiştir, bu da https'e benzer (http+SSL).
Bu nedenle yalnızca websocket protokolü temel alınarak SSL açıldığında wss protokolü desteklenebilir.

Yöntem 1: nginx/apache ile SSL proxy kullanma (önerilir)

Öneri Sebepleri

  • 443 portunu yeniden kullanabilme, client bağlantısı sırasında port belirtmeye gerek kalmaz
  • SSL sertifikalarını merkezi olarak yönetebilir, web sitesi yapılandırmasını tekrar kullanabilir
  • Yük dengelemesi yapabilir
  • Kendi log izleme özelliği vardır
  • Daha iyi uyumluluk sağlar

İletişim Prensibi ve Süreci

  1. Client wss bağlantısını nginx/apache'e başlatır.

  2. nginx/apache wss protokolündeki verileri ws protokolündeki verilere çevirir ve Workerman'ın websocket protokol portuna iletir.

  3. Workerman, veriyi aldıktan sonra iş mantığı işlemlerini gerçekleştirir.

  4. Workerman, client'a mesaj gönderdiğinde, bu ters süreçtir; veri nginx/apache üzerinden wss protokolüne dönüştürülür ve client'a gönderilir.

nginx yapılandırma referansı

Ön koşullar ve hazırlık çalışmaları:

  1. nginx yüklü olmalıdır, sürümü 1.3 veya daha yeni olmalıdır.

  2. Workerman'ın 8282 portunu (websocket protokolü) dinlediğini varsayalım.

  3. Sertifika (pem/crt dosyası ve anahtar dosyası) zaten başvurulmuş olmalı, bunu /etc/nginx/conf.d/ssl altında varsayalım.

  4. Nginx, 443 portunu wss proxy hizmeti sunmak için yapılandırılacaktır (port ihtiyaca göre değiştirilebilir).

  5. Nginx genelde diğer hizmetleri çalıştıran bir web sunucusu olarak çalıştığı için mevcut siteyi etkilememek için wss proxy girişi olarak adres alanadım.com/wss kullanılarak yapılandırılacaktır. Yani client bağlantı adresi wss://alanadım.com/wss olacaktır.

Nginx yapılandırması aşağıdaki gibidir:

server {
  listen 443;
  # Alan adı yapılandırması atlandı...

  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 / {} Sitelerin diğer yapılandırmaları...
}

Test

// Sertifika, alan adını kontrol eder lütfen alan adı üzerinden bağlantı kurun. Port yazılmadığına dikkat edin
ws = new WebSocket("wss://alanadım.com/wss");

ws.onopen = function() {
    alert("Bağlantı başarılı");
    ws.send('tom');
    alert("Sunucuya bir dize gönderildi: tom");
};
ws.onmessage = function(e) {
    alert("Sunucudan alınan mesaj: " + e.data);
};

Apache ile wss proxy kullanma

Ayrıca apache kullanarak wss proxy ile Workerman'a iletilmesini sağlayabilirsiniz.

Hazırlık çalışmaları:

  1. GatewayWorker 8282 portunu (websocket protokolü) dinlemelidir.

  2. SSL sertifikası alındı, varsayalım ki /server/httpd/cert/ altında duruyor.

  3. Apache, 443 portunu belirtilen 8282 portuna yönlendirecek şekilde ayarlanmalı.

  4. httpd-ssl.conf yüklenmiş olmalıdır.

  5. openssl yüklü olmalıdır.

proxy_wstunnel_module modülünü etkinleştirin

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so

SSL ve proxy yapılandırması

#extra/httpd-ssl.conf
DocumentRoot "/web/klasör"
ServerName alanadım

# Proxy Yapılandırması
SSLProxyEngine on

ProxyRequests Off
ProxyPass /wss ws://127.0.0.1:8282/wss
ProxyPassReverse /wss ws://127.0.0.1:8282/wss

# Güvensiz protokolleri kaldırarak SSL protokol desteği ekleyin
SSLProtocol all -SSLv2 -SSLv3
# Şifreleme kümesini şu şekilde değiştirin
SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM
SSLHonorCipherOrder on
# Sertifika açık anahtar ayarı
SSLCertificateFile /server/httpd/cert/your.pem
# Sertifika özel anahtar ayarı
SSLCertificateKeyFile /server/httpd/cert/your.key
# Sertifika zinciri ayarı,
SSLCertificateChainFile /server/httpd/cert/chain.pem

Test

// Sertifika, alan adını kontrol eder lütfen alan adı üzerinden bağlantı kurun. Port yok
ws = new WebSocket("wss://alanadım.com/wss");

ws.onopen = function() {
    alert("Bağlantı başarılı");
    ws.send('tom');
    alert("Sunucuya bir dize gönderildi: tom");
};
ws.onmessage = function(e) {
    alert("Sunucudan alınan mesaj: " + e.data);
};

Yöntem 2: Workerman ile doğrudan SSL açma (önerilmez)

Dikkat
Nginx/apache SSL proxy ile Workerman SSL ayarları iki seçenekten birini kullanılabilir, aynı anda açılamaz.

Hazırlık Çalışmaları:

  1. Workerman sürümü >=3.3.7 olmalıdır.

  2. PHP'de openssl eklentisi yüklü olmalıdır.

  3. Sertifika (pem/crt dosyası ve anahtar dosyası) disk üzerinde herhangi bir dizinde mevcut olmalıdır.

Kod:

<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

// Sertifika mümkünse alınan sertifika olmalıdır
$context = array(
    // Daha fazla ssl seçeneği için kılavuza bakınız http://php.net/manual/zh/context.ssl.php
    'ssl' => array(
        // Lütfen mutlak yolu kullanın
        'local_cert'        => 'disk_yolu/server.pem', // crt dosyası da olabilir
        'local_pk'          => 'disk_yolu/server.key',
        'verify_peer'       => false,
        'allow_self_signed' => true, // Eğer kendi kendine imzalı bir sertifikaysa bu seçeneği açmalısınız
    )
);
// Burada websocket protokolü ayarlanmakta (port herhangi biri olabilir, ancak başka bir program tarafından kullanılmadığından emin olmalısınız)
$worker = new Worker('websocket://0.0.0.0:8282', $context);
// Transport'u SSL ile açın, websocket+ssl yani wss
$worker->transport = 'ssl';
$worker->onMessage = function(TcpConnection $con, $msg) {
    $con->send('ok');
};

Worker::runAll();

Yukarıdaki kodla Workerman wss protokolünü dinlemiş olur, client'lar wss protokolü üzerinden bağlanarak güvenli anlık iletişim sağlar.

Test

Chrome tarayıcısını açın, F12 tuşuna basarak geliştirme konsolunu açın, Console bölümüne aşağıdaki kodu yazın (veya aşağıdaki kodu bir html sayfasına koyup js ile çalıştırın)

// Sertifika, alan adını kontrol eder lütfen alan adı üzerinden bağlanın, burada port numarasına dikkat edin
ws = new WebSocket("wss://alanadım.com:8282");
ws.onopen = function() {
    alert("Bağlantı başarılı");
    ws.send('tom');
    alert("Sunucuya bir dize gönderildi: tom");
};
ws.onmessage = function(e) {
    alert("Sunucudan alınan mesaj: " + e.data);
};

Yaygın Hatalar
SSL routines:SSL23_GET_CLIENT_HELLO:http request
Sebebi client'ın ws://alanadım.com kullanarak erişmesidir, doğru erişim adresi wss://alanadım.com olmalıdır, yani wss ile başlamalıdır.
Bu sorun çoğunlukla port önceden ws için tanımlandığında ve aniden wss olarak değiştirildiğinde bazı client sayfalarının yenilenmemesiyle появляется. Bu hata göz ardı edilebilir, normal wss bağlantısını etkilemez.

Dikkat:

  1. 443 portunu kullanmanız gerekiyorsa, yukarıdaki ilk yöntem olan nginx/apache proxy yöntemini kullanın.

  2. wss portuna yalnızca wss protokolü üzerinden erişilebilir, ws ile erişilemez.

  3. Sertifika genelde alan adıyla ilişkilendirildiği için test sırasında client lütfen alan adı üzerinden bağlantı kurun, ip üzerinden bağlanmayın.

  4. Erişim problemi varsa, lütfen sunucu güvenlik duvarını kontrol edin.

  5. Bu yöntem, PHP sürümü >=5.6 gerektirir çünkü WeChat mini programı tls1.2 gerektirir, PHP 5.6'dan daha eski sürümler tls1.2 desteklemez.

İlgili makaleler:
Proxy üzerinden client’ın gerçek ip'sini alma
Workerman SSL bağlamı seçenekleri referansı