繁体   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