Skip to content

Instantly share code, notes, and snippets.

@nguyenhoang2009
Forked from thanhpk/nginx_websocket.md
Created September 22, 2022 10:00
Show Gist options
  • Save nguyenhoang2009/5ea759ddab1bf10d48998a9f06c50f44 to your computer and use it in GitHub Desktop.
Save nguyenhoang2009/5ea759ddab1bf10d48998a9f06c50f44 to your computer and use it in GitHub Desktop.

Revisions

  1. @thanhpk thanhpk created this gist Jun 1, 2016.
    229 changes: 229 additions & 0 deletions nginx_websocket.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,229 @@
    Set up nginx proxy to nodejs websocket
    * * *
    Tài liệu này trình bày hai cách cấu hình, `https ở nginx -> wss nodejs` hoặc từ `https ở nginx -> ws` ở nodejs

    Để điều hướng request từ cổng 443 vào websocket server (demo bằng nodejs)

    * Yêu cầu, chạy nginx 1.4 trên ubuntu

    # From https to wss
    * nginx nghe cổng 443, toàn bộ request `wss://domain.com/ws` sẽ được chuyển về `wss://127.0.0.1:2910`
    tức là cả nginx và nodejs websocket server đều chạy https

    file websocketserver.js
    ```
    import * as https from 'https';
    import * as fs from 'fs';
    import * as websocket from 'websocket';
    export class WS {
    private httpserver;
    public constructor(keypath:string, certpath:string) {
    var option = {
    key: fs.readFileSync(keypath),
    cert: fs.readFileSync(certpath)
    };
    this.httpserver = https.createServer(option, function (req, res) {
    res.writeHead(404);
    res.end();
    });
    }
    public run() {
    var me = this;
    this.httpserver.listen(2910, function () {
    console.log('Websocket server / OK / ' + 2910);
    });
    var wsServer = new websocket.server({
    httpServer: me.httpserver,
    autoAcceptConnections: false
    });
    function originIsAllowed(origin:string) {
    // put logic here to detect whether the specified origin is allowed.
    return true;
    }
    wsServer.on('request', function (request) {
    if (!originIsAllowed(request.origin)) {
    // Make sure we only accept requests from an allowed origin
    request.reject();
    console.log((new Date()) + 'Connection from origin ' + request.origin + ' rejected.');
    return;
    }
    console.log('new coming');
    var connection = request.accept('proto', request.origin);
    connection.on('message', function (message) {
    console.log('received: ' + message);
    });
    connection.on('close', function (reasonCode, description) {
    console.log('closed');
    });
    });
    }
    }
    new WS('./key.pem', './cert.cert').run();
    ```
    cấu hình nginx
    ```
    upstream websocket {
    server 127.0.0.1:2910;
    }
    server {
    charset utf-8;
    listen 443;
    server_name domain.com;
    ssl on;
    ssl_certificate /etc/ssl/certs/chained.pem;
    ssl_certificate_key /etc/ssl/private/domain.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-G\
    CM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES\
    128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
    ssl_session_cache shared:SSL:50m;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_prefer_server_ciphers on;
    access_log /home/thanhpk/tmp/meotrics-access443.log;
    error_log /home/thanhpk/tmp/meotrics-error443.log;
    location /ws {
    proxy_pass https://websocket;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    }
    }
    ```
    nginx sẽ gửi request tới https://127.0.0.1:2910/ws, tuy nhiên sẽ bị chặn lại bởi key và cert của nodejs chưa đăng ký -> cần tự xác thực một certificate dùng trong server.

    Gõ lệnh sau đây ở ubuntu

    ```
    openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.crt -days 100 -nodes
    ```

    Nhập thông tin cho certificate, chú ý, khi nhập _Common Name (eg, your name or your FQDN of the server)_ phải điền `127.0.0.1`. Nếu bỏ qua bước này, sinh lại certificate và nhập lại.

    Sau khi sinh, sẽ có 2 file key.pem và cert.crt
    vào terminal gõ
    ```
    apt-get install ca-certificates
    cp cert.crt /usr/share/ca-certificates
    dpkg-reconfigure ca-certificates
    ```
    Chọn ask, rồi tìm và tích chọn _cert.crt_ để báo cho hệ thống biết _cert.crt_ là một cert hợp lệ.

    Cuối cùng, chạy nodejs server bằng cách gõ `node websocketserver.js` vào terminal. Thử lại bằng cách vào trình duyệt Chrome, bật cửa số console, gõ

    ```
    var ws = new WebSocket('wss://domain.com/ws', 'proto');
    ```
    Cửa số terminal chạy nodejs sẽ hiển thị thông tin kết nối.

    # From https to ws
    nginx chạy https:443 còn nodejs chạy ws bình thường, khi cấu hình kiểu này, ko cần bước tự ký nữa

    file websocketserver.js
    ```
    import * as http from 'http';
    import * as fs from 'fs';
    import * as websocket from 'websocket';
    export class WS {
    private httpserver;
    public constructor() {
    this.httpserver = https.createServer(function (req, res) {
    res.writeHead(404);
    res.end();
    });
    }
    public run() {
    var me = this;
    this.httpserver.listen(2910, function () {
    console.log('Websocket server / OK / ' + 2910);
    });
    var wsServer = new websocket.server({
    httpServer: me.httpserver,
    autoAcceptConnections: false
    });
    function originIsAllowed(origin:string) {
    // put logic here to detect whether the specified origin is allowed.
    return true;
    }
    wsServer.on('request', function (request) {
    if (!originIsAllowed(request.origin)) {
    // Make sure we only accept requests from an allowed origin
    request.reject();
    console.log((new Date()) + 'Connection from origin ' + request.origin + ' rejected.');
    return;
    }
    console.log('new coming');
    var connection = request.accept('proto', request.origin);
    connection.on('message', function (message) {
    console.log('received: ' + message);
    });
    connection.on('close', function (reasonCode, description) {
    console.log('closed');
    });
    });
    }
    }
    new WS().run();
    ```
    cấu hình nginx
    ```
    upstream websocket {
    server 127.0.0.1:2910;
    }
    server {
    charset utf-8;
    listen 443;
    server_name domain.com;
    ssl on;
    ssl_certificate /etc/ssl/certs/chained.pem;
    ssl_certificate_key /etc/ssl/private/domain.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-G\
    CM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES\
    128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
    ssl_session_cache shared:SSL:50m;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_prefer_server_ciphers on;
    access_log /home/thanhpk/tmp/meotrics-access443.log;
    error_log /home/thanhpk/tmp/meotrics-error443.log;
    location /ws {
    proxy_pass http://websocket;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    }
    }
    ```
    chạy nodejs server bằng cách gõ
    node websocketserver.js,

    vào trình duyệt, bật cửa số console, gõ
    var ws = new WebSocket('wss://domain.com/ws', 'proto');