简体   繁体   English

使用 Cro 保护 websockets

[英]Secure websockets with Cro

Briefly : I created a service on an inte.net server using Cro and websocket. Very simple using Cro examples.简要说明:我使用 Cro 和 websocket 在 inte.net 服务器上创建了一个服务。使用 Cro 示例非常简单。 No problem when sending and receiving data from an HTML page when the page is served as localhost.当页面用作本地主机时,从 HTML 页面发送和接收数据时没有问题。 When the page is served using https, the websocket cannot be established.使用 https 提供页面时,无法建立 websocket。 How is the wss protocol be used with Cro? wss协议如何与Cro一起使用?

Update : After installing cro and running cro stub:secure , the service.p6 has some more code not explicit in the documentation.更新:安装cro并运行cro stub:secure后,service.p6 有更多代码未在文档中明确显示。

More detail : I have a docker file running on the inte.net server, Cro is set to listen on 35145, so the docker command is docker --rm -t myApp -p 35145:35145更多细节:我在 inte.net 服务器上运行了一个 docker 文件,Cro 设置为监听 35145,所以 docker 命令是docker --rm -t myApp -p 35145:35145

The service file contains服务文件包含

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 })
                    }
                }
            }
        }
    }
}

In the HTML I have a textarea container with an id raku-code .在 HTML 中,我有一个带有 id raku-code的 textarea 容器。 The js script has the following (I set websocketHost and websocketPort elsewhere in the script) in a handler that fires after the DOM is ready: 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;
        }

When an HTML file with this JS script is set up, and served locally I can send data to the Cro app running on an inte.net server, and the Cro App (running in a docker image) processes and returns data which is placed in the right HTML container.当设置了带有此 JS 脚本的 HTML 文件并在本地提供服务时,我可以将数据发送到在 inte.net 服务器上运行的 Cro 应用程序,Cro App(在 docker 图像中运行)处理并返回放置在正确的 HTML 容器。 Using Firefox and the developer tools, I can see that the ws connection is created.使用 Firefox 和开发人员工具,我可以看到 ws 连接已创建。

But when I serve the same file via Apache which forces access via https, Firefox issues an error that the 'wss' connection cannot be created.但是,当我通过 Apache 强制通过 https 访问同一文件时,Firefox 发出无法创建“wss”连接的错误。 In addition, if I force a 'ws' connection in the JS script, Firefox prevents the creation of a non-secure connection.此外,如果我在 JS 脚本中强制使用“ws”连接,Firefox 会阻止创建非安全连接。

a) How do I change the Cro coding to allow for wss? a) 如何更改 Cro 编码以允许 wss? From the Cro documentation it seems I need to add a Cro::TLS listener, but it isn't clear where to instantiate the listener.从 Cro 文档看来我需要添加一个 Cro::TLS 侦听器,但不清楚在哪里实例化侦听器。 b) If this is to be in a docker file, would I need to include the secret encryption keys in the image, which is not something I would like to do? b) 如果这是在 docker 文件中,我是否需要在图像中包含秘密加密密钥,这不是我想做的事情? c) Is there a way to put the Cro app behind the Apache server so that the websocket is decrypted/encrypted by Apache? c) 有没有办法把Cro应用放在Apache服务器后面,这样websocket就可以被Apache解密/加密了?

Though is not a pure cro solution, but you can run your cro app on (none ssl/https) http/web socket port - localhost and then have an Nginx server (configured to serve https/ssl trafic) to handle incoming public https/ssl requests and bypass them as a plain http traffic to your app using nginx reverse proxy mechanism (this is also often referred as an ssl termination), that way you remove a necessity to handle https/ssl on cro side.虽然不是纯 cro 解决方案,但您可以在(无 ssl/https)http/web 套接字端口 - localhost 上运行您的 cro 应用程序,然后有一个 Nginx 服务器(配置为服务 https/ssl 流量)来处理传入的公共https/ ssl 请求并使用 nginx 反向代理机制(这通常也称为 ssl 终止)将它们作为普通的 http 流量绕过您的应用程序,这样您就无需在 cro 端处理 https/ssl。 The only hurdle here might be if a web sockets protocol is handled well by Nginx proxy.这里唯一的障碍可能是 web sockets 协议是否由 Nginx 代理很好地处理。 I've never tried that but probably you should be fine according to the Nginx docs - https://www.nginx.com/blog/websocket-nginx/我从来没有尝试过,但根据 Nginx 文档,你应该没问题 - https://www.nginx.com/blog/websocket-nginx/

How do I change the Cro coding to allow for wss?如何更改 Cro 编码以允许 wss? From the Cro documentation it seems I need to add a Cro::TLS listener, but it isn't clear where to instantiate the listener.从 Cro 文档看来我需要添加一个 Cro::TLS 侦听器,但不清楚在哪里实例化侦听器。

Just pass the needed arguments to Cro::HTTP::Server , it will set up the listener for you.只需将所需的 arguments 传递给 Cro::HTTP::Server ,它就会为您设置监听器。

If this is to be in a docker file, would I need to include the secret encryption keys in the image, which is not something I would like to do?如果这是在 docker 文件中,我是否需要在图像中包含秘密加密密钥,这不是我想做的事情?

No. You can keep them in a volume, or bind-mount them from the host machine.不。您可以将它们保存在一个卷中,或从主机绑定安装它们。

Is there a way to put the Cro app behind the Apache server so that the websocket is decrypted/encrypted by Apache?有没有办法将Cro应用程序放在Apache服务器后面,以便websocket被Apache解密/加密?

Yes, same as with any other app.是的,与任何其他应用程序一样。 Use mod_proxy and a ProxyPass command.使用mod_proxyProxyPass命令。 Other frontends such as nginx, haproxy, or envoy will also do the job.其他前端,如 nginx、haproxy 或 envoy 也可以完成这项工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM