【WebSocket】RatchetをSSL/wss化【Nginxリバースプロキシ】

2022年11月15日

WebSocket通信をSSL化したいけどRatchetでは80番ポートしか使えない、色々調べてみた結果、Nginxのリバースプロキシ機能を使うことで実装することができました。

WebSocket - php - Ratchet
WebSocket – php – Ratchet

WebSocketサーバーへのアクセスをリバースプロキシサーバーが代わりに受けて、

パケット内のWebScoketヘッダ情報を認識しヘッダ情報はそのままWebScoketとして、ポート番号は変換してWebSocketサーバーへ転送する仕組みになっています。

関連記事
【WebSocket】PHP/Ratchetを使ってチャットページを作ってみた
【WebSocket】NginxでRatchetをSSL/wss化
関連記事 Nginx系インストール
1.ConoHa VPS のSSHセキュリティを強化する
2.【CentOS stream 9】 Nginxをインストール
3.【CentOS stream 9】 Maria DBをインストール
4.【CentOS stream 9】 phpをインストール
5.【CentOS stream 9】 Nginxでphp、phpMyAdminを使う
6.【CentOS stream 9】 composerをインストール
7.【CentOS stream 9】 Nginxに let's encrypt SSL証明書インストール
チャットページ – 絵文字機能

SSL対応 wss化 実装手順

実装したサーバー環境です。

  • ConoHa VPS
  • CentOS Stream release 9
  • Nginx version: nginx/1.20.1
  • PHP 8.1.6
  • 10.5.13-MariaDB MariaDB Server

その後に書いている実装では「 wss://リバースプロキシサーバー/chat」へのアクセスを、 「ws://WebSocketサーバー:8080」に転送するようにしています。

index.htmlを編集

基本的な実装手順はこちらを参考にしてください。
【WebSocket】PHP/Ratchetを使ってチャットページを作ってみた

index.htmlまたはindex.phpの記述を「ws」から「wss」に変更し、

ポート番号「8080」を削除、

「/chat」を追記する

 var conn = new WebSocket('ws://VPSのIPアドレス:8080/'); 

↓変更後

var conn = new WebSocket('wss://VSPの IPアドレス/chat');

Nginxの設定

参考記事
【CentOS stream 9】 Nginxをインストールする

nginxの設定ファイル「/etc/nginx/nginx.conf」を修正

# vi /etc/nginx/nginx.conf

wss://リバースプロキシサーバー/chat」への通信を「localhost:8080」に転送(リバースプロキシ)するように記述

37行目あたりから(いくつかの個人メモもそのまま載せています)

    upstream test{
    server localhost:8080;
 # server 192.168.0.2:8080 weight=1;     #バックエンドへのバランシングを行う場合 weightを省略すると weight=1となり ラウンドロビンで50%/50%の振り分け、待機系にする場合はbackupと記述
 # Keep-Alive     #バックエンドへのKeep-Aliveを行う
    
        }
    server { #http通信はhttpsへリダイレクトさせる
        listen       80;
        listen       [::]:80;
        server_name  _;
        return 301 https://$host$request_uri;
        }
    server {
        listen          443 ssl;
        listen          [::]:443 ssl;
        server_name  _;
        root         /usr/share/nginx/html;

        #SSLサーバー証明書の設定
        ssl_certificate /etc/nginx/localhost.crt;
        ssl_certificate_key /etc/nginx/localhost.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_session_tickets  off;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

         location /chat {
   #    proxy_pass http://127.0.0.1:8080; # upstreamを使わず、こちらの書き方でも可
        proxy_pass http://test;
        proxy_http_version 1.1; # webソケットに必要なkeep-Aliveを使用するため、HTTP1.1プロトコルバージョンを明示的に指定
        proxy_set_header Upgrade $http_upgrade;
   #    proxy_set_header Connection $connection_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_redirect off;
   #   proxy_connect_timeout 60s; #接続タイムアウト
        proxy_read_timeout 86400s; #受信処理が滞った場合のタイムアウト
        proxy_send_timeout 86400s; #送信処理が滞った場合のタイムアウト
        keepalive_timeout 86400s;
        # prevents 502 bad gateway error
        proxy_buffers 8 32k;
        proxy_buffer_size 64k;

        #リクエストヘッダの追加、バックエンドへ追加のヘッダ情報を引き渡す
        proxy_set_header X-Real-IP $remote_addr; 
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        reset_timedout_connection on;
}

参考サイト : nginx.org WebSocket proxying

NginxのリバースプロキシでWebソケットを通す際の設定 – Qiita

SSLの設定

mod_sslをインストールします。

# dnf install mod_ssl

 〜〜〜〜〜
Install  2 Packages

Total download size: 158 k
Installed size: 367 k
Is this ok [y/N]:y

途中でyを入力

〜〜〜〜

Installed:
  mod_ssl-1:2.4.51-8.el9.x86_64             sscg-3.0.0-5.el9.x86_64

Complete!

最後にComplete!と表示されます。

SSL証明書の作成

【CentOS stream 9】 Nginxに let's encrypt SSL証明書インストール

参考サイトNginxでオレオレ証明書作成するときの手順メモ

# cd /etc/nginx/

# openssl genrsa -out localhost.key 2048

# openssl req -new -key localhost.key -out localhost.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]://エンター
State or Province Name (full name) []://エンター
Locality Name (eg, city) [Default City]://エンター
Organization Name (eg, company) [Default Company Ltd]://エンター
Organizational Unit Name (eg, section) []://エンター
Common Name (eg, your name or your server's hostname) []://エンター
Email Address []://エンター

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []://エンター
An optional company name []://エンター

# openssl rsa -in localhost.key -out localhost.key
writing RSA key

# openssl x509 -req -days 3650 -in localhost.csr -signkey localhost.key -out localhost.crt

nginxの再起動

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

# systemctl restart nginx.service

WebSocketサーバー(chat-server.php)の起動

# nohup php ratchet/bin/chat-server.php & 

参考サイト:WebSocket wssについて

リバースプロキシの設定方法(NginxとApacheでの設定手順)

Ratchetでweb socketを使ってみたよ.d0131.pub

How to setup WSS for Ratchet WebSocket Server on Nginx or Apache | by Anand Singh | Medium

ws to wss · Issue #161 · ratchetphp/Ratchet · GitHub

An Issue with connecting: SSL + WebSocket(http://socketo.me) + Nginx · Issue #705 · ratchetphp/Ratchet · GitHub

php – Symfony Ratchet WSS | programmierfrage.com

php,SSL,WebSocketNginx,php,WebSocket

Posted by sei