簡體   English   中英

使用 Cro 保護 websockets

[英]Secure websockets with Cro

簡要說明:我使用 Cro 和 websocket 在 inte.net 服務器上創建了一個服務。使用 Cro 示例非常簡單。 當頁面用作本地主機時,從 HTML 頁面發送和接收數據時沒有問題。 使用 https 提供頁面時,無法建立 websocket。 wss協議如何與Cro一起使用?

更新:安裝cro並運行cro stub:secure后,service.p6 有更多代碼未在文檔中明確顯示。

更多細節:我在 inte.net 服務器上運行了一個 docker 文件,Cro 設置為監聽 35145,所以 docker 命令是docker --rm -t myApp -p 35145:35145

服務文件包含

use Cro::HTTP::Log::File;
use Cro::HTTP::Server;
use Cro::HTTP::Router;
use Cro::HTTP::Router::WebSocket;

my $host = %*ENV<RAKU_WEB_REPL_HOST> // '0.0.0.0';
my $port = %*ENV<RAKU_WEB_REPL_PORT> // 35145;
my Cro::Service $http = Cro::HTTP::Server.new(
    http => <1.1>,
    :$host,
    :$port,
    application => routes(),
    after => [
        Cro::HTTP::Log::File.new(logs => $*OUT, errors => $*ERR)
    ]
    );
$http.start;
react {
    whenever signal(SIGINT) {
        say "Shutting down...";
        $http.stop;
        done;
    }
}
sub routes() {
    route {
        get -> 'raku' {
            web-socket :json, -> $incoming {
                supply whenever $incoming -> $message {
                    my $json = await $message.body;
                    if $json<code> {
                        my $stdout, $stderr;
                        # process code 
                        emit({ :$stdout, :$stderr })
                    }
                }
            }
        }
    }
}

在 HTML 中,我有一個帶有 id raku-code的 textarea 容器。 js 腳本在 DOM 准備好后觸發的處理程序中具有以下內容(我在腳本的其他地方設置了 websocketHost 和 websocketPort):

const connect = function() {
    // Return a promise, which will wait for the socket to open
    return new Promise((resolve, reject) => {
        // This calculates the link to the websocket.
        const socketProtocol = (window.location.protocol === 'https:' ? 'wss:' : 'ws:');
        const socketUrl = `${socketProtocol}//${websocketHost}:${websocketPort}/raku`;
        socket = new WebSocket(socketUrl);

        // This will fire once the socket opens
        socket.onopen = (e) => {
            // Send a little test data, which we can use on the server if we want
            socket.send(JSON.stringify({ "loaded" : true }));
            // Resolve the promise - we are connected
            resolve();
        }

        // This will fire when the server sends the user a message
        socket.onmessage = (data) => {
            let parsedData = JSON.parse(data.data);
            const resOut = document.getElementById('raku-ws-stdout');
            const resErr = document.getElementById('raku-ws-stderr');
            resOut.textContent = parsedData.stdout;
            resErr.textContent = parsedData.stderr;
        }

當設置了帶有此 JS 腳本的 HTML 文件並在本地提供服務時,我可以將數據發送到在 inte.net 服務器上運行的 Cro 應用程序,Cro App(在 docker 圖像中運行)處理並返回放置在正確的 HTML 容器。 使用 Firefox 和開發人員工具,我可以看到 ws 連接已創建。

但是,當我通過 Apache 強制通過 https 訪問同一文件時,Firefox 發出無法創建“wss”連接的錯誤。 此外,如果我在 JS 腳本中強制使用“ws”連接,Firefox 會阻止創建非安全連接。

a) 如何更改 Cro 編碼以允許 wss? 從 Cro 文檔看來我需要添加一個 Cro::TLS 偵聽器,但不清楚在哪里實例化偵聽器。 b) 如果這是在 docker 文件中,我是否需要在圖像中包含秘密加密密鑰,這不是我想做的事情? c) 有沒有辦法把Cro應用放在Apache服務器后面,這樣websocket就可以被Apache解密/加密了?

雖然不是純 cro 解決方案,但您可以在(無 ssl/https)http/web 套接字端口 - localhost 上運行您的 cro 應用程序,然后有一個 Nginx 服務器(配置為服務 https/ssl 流量)來處理傳入的公共https/ ssl 請求並使用 nginx 反向代理機制(這通常也稱為 ssl 終止)將它們作為普通的 http 流量繞過您的應用程序,這樣您就無需在 cro 端處理 https/ssl。 這里唯一的障礙可能是 web sockets 協議是否由 Nginx 代理很好地處理。 我從來沒有嘗試過,但根據 Nginx 文檔,你應該沒問題 - https://www.nginx.com/blog/websocket-nginx/

如何更改 Cro 編碼以允許 wss? 從 Cro 文檔看來我需要添加一個 Cro::TLS 偵聽器,但不清楚在哪里實例化偵聽器。

只需將所需的 arguments 傳遞給 Cro::HTTP::Server ,它就會為您設置監聽器。

如果這是在 docker 文件中,我是否需要在圖像中包含秘密加密密鑰,這不是我想做的事情?

不。您可以將它們保存在一個卷中,或從主機綁定安裝它們。

有沒有辦法將Cro應用程序放在Apache服務器后面,以便websocket被Apache解密/加密?

是的,與任何其他應用程序一樣。 使用mod_proxyProxyPass命令。 其他前端,如 nginx、haproxy 或 envoy 也可以完成這項工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM