2

使用最新版本的Crossbar(0.13,从apt-getUbuntu 14.04 安装)我无法使用 SSL 和中间证书建立连接。

ca_certificates如果我在密钥中没有属性的情况下设置服务器,tls则服务器运行良好,并且可以通过wss协议使用 Google Chrome 建立连接。但是尝试使用thruway建立连接失败并出现以下错误:

无法连接:无法完成 SSL/TLS 握手:stream_socket_enable_crypto():SSL 操作失败,代码为 1。OpenSSL 错误消息:错误:14094410:SSL 例程:ssl3_read_bytes:sslv3 警报握手失败

与Thruway团队交谈似乎是证书问题 - 在我们的实时站点上,我们使用来自 Gandi 的中间和交叉签名证书,这是某些浏览器所需的,因此是一些 open-ssl 实现所必需的。

似乎虽然浏览器很乐意只使用密钥和证书建立 TLS 连接,但 Thruway 需要一个链。然而,以下使用 Gandi 提供的两个证书的配置不适用于ChromeThruway。Chrome 显示错误:

失败:WebSocket 打开握手被取消

使用.crossbar/config.json下面的文件时。那么,这是我的配置、我的证书还是 Open-SSL 堆栈的其他部分的问题?

(下面的文件已被更改,以删除任何潜在的敏感信息,因此可能看起来由于其他原因无法正常工作。如果连接正常,则底层身份验证和其他组件工作正常,因此请保留有关 TLS 实施的答案/评论。注释不是有效的 JSON,但包含在内,因此读者可以看到正在使用的证书文件)

{
    "version": 2,
    "controller": {},
    "workers": [
        {
            "type": "router",
            "realms": [
                {
                    "name": "test",
                    "roles": [
                        {
                            "name": "web",
                            "authorizer": "test.utils.permissions",
                            "disclose": {
                                "caller": true,
                                "publisher": true
                            }
                        },
                        {
                            "name": "no",
                            "permissions": []
                        }
                    ]
                }
            ],
            "transports": [
                {
                    "type": "websocket",
                    "endpoint": {
                        "type": "tcp",
                        "port": 9001,
                        "interface": "127.0.0.1"
                    },
                    "auth": {
                        "wampcra": {
                            "type": "static",
                            "users": {
                                "authenticator": {
                                    "secret": "authenticator-REDACTED",
                                    "role": "authenticator"
                                }
                            }
                        }
                    }
                },
                {
                    "type": "web",
                    "endpoint": {
                        "type": "tcp",
                        "port": 8089,
                        "tls": {
                            "key": "../ssl/key.pem",
                            "certificate": "../ssl/cert.pem",
                            "ca_certificates": [
                                "../ssl/gandi.pem", // https://www.gandi.net/static/CAs/GandiProSSLCA2.pem
                                "../ssl/gandi-cross-signed.pem" // https://wiki.gandi.net/en/ssl/intermediate#comodo_cross-signed_certificate
                            ],
                            "dhparam": "../ssl/dhparam.pem"
                        }
                    },
                    "paths": {
                        "/": {
                            "type": "static",
                            "directory": "../web"
                        },
                        "ws": {
                            "type": "websocket",
                            "url": "wss://OUR-DOMAIN.com:8089/ws",
                            "auth": {
                                "wampcra": {
                                    "type": "dynamic",
                                    "authenticator": "test.utils.authenticate"
                                }
                            }
                        }
                    }
                }
            ]
        },
        {
            "type": "guest",
            "executable": "/usr/bin/env",
            "arguments": [
                "php",
                "../test.php",
                "ws://127.0.0.1:9001",
                "test",
                "authenticator",
                "authenticator-REDACTED"
            ]
        }
    ]
}

还有其他问题可以解决与此类似的问题@

  • 这一个处理任何 TLS 错误都会终止 WSS 连接而没有有用错误的事实。
  • 这个专门处理握手取消,但在他们的情况下,它是编译中使用的配置不正确的库,在这种情况下与 Crossbar 无关,因为已从apt-get
4

2 回答 2

1

这不是 Crossbar 的问题。这似乎是 WAMP 客户端的问题 - Thruway。Davidwdan 是 Thruway Github repo 的所有者,他说:

“Thruway 的 Ratchet 传输提供商不直接支持 SSL。您需要在它前面放置某种代理。”

您可以在https://github.com/voryx/Thruway/issues/163找到有关 Davidwdan 和其他人对此有何评论的更多信息。

现在来解决问题。请注意,以下内容仅适用于 Apache 用户。如果你在 Nginx 上运行,这个想法几乎是一样的。

在我们开始之前需要注意几件事。

  1. 按照 Crossbar 的教程进行安装!不要试图自己做!设置 Crossbar 还有更多内容。Crossbar 的优秀人员为您制定了详细的说明!https://crossbar.io/docs/Installation/
  2. 对于这个例子,我让 Crossbar 和 Apache 在同一台机器上运行。虽然这不是要求,也无所谓!

您要做的第一件事是创建一个新的虚拟主机。我为这个虚拟主机选择了端口 4043,但是你可以选择任何你想要的。这个虚拟主机将适用于通过 wss://(使用 SSL)连接没有问题的每个 WAMP 库。以下是 WAMP 客户端的完整列表:http ://wamp-proto.org/implementations/. 确保 ProxyPass 指令和 ProxyPassReverse 指令的 IP 地址指向 CROSSBAR 路由器所在的机器。就我而言,由于 Apache 和 Crossbar 在同一台机器上运行,我只使用 127.0.0.1。还要确保 ProxyPass 指令和 ProxyPassReverse 指令中使用的端口与您在 .crossbar/config.json 中定义的端口完全相同!您还需要在此虚拟主机上设置 SSL 证书,您可以看到我在代理指令下方添加了该证书。

Listen 4043

<VirtualHost *:4043>
ServerName example.org
ProxyRequests off
SSLProxyEngine on
ProxyPass /ws/ ws://127.0.0.1:8000/
ProxyPassReverse /ws/ ws://127.0.0.1:8000/

## Custom fragment
SSLEngine on
SSLCertificateFile /path/to/server_cert.pem
SSLCertificateKeyFile /path/to/server_key.pem
SSLCertificateChainFile /path/to/server_ca.pem
</VirtualHost>

接下来,确保您的 Crossbar 路由器未设置 SSL!这是超级重要的。如果您将路由器配置为使用 SSL,则 Thruway 或任何其他无法通过 SSL 连接的库将无法使用路由器!下面是一个可以使用的 Crossbar config.json 文件。

{
 "version": 2,
 "controller": {},
 "workers": [
 {
  "type": "router",
  "realms": [
    {
      "name": "production_realm",
      "roles": [
        {
          "name": "production_role",
          "permissions": [
            {
              "uri": "",
              "match": "prefix",
              "allow": {
                "call": true,
                "register": true,
                "publish": true,
                "subscribe": true
              }
            }
          ]
        }
      ]
    }
  ],
  "transports": [
    {
      "type": "websocket",
      "endpoint": {
        "type": "tcp",
        "port": 8000
        },
        "options": {
            "allowed_origins": ["http://*","https://*"]
      },
      "auth": {
        "ticket": {
          "type": "static",
          "principals": {
            "production_user": {
              "ticket": "tSjlwueuireladgte",
              "role": "production_role"
            }
          }
        }
      }
    }
   ]
  }
 ]
}  

请注意上面定义的端口号如何与虚拟主机中定义的端口号匹配。

./crossbar/config.json:

"endpoint": {
        "type": "tcp",
        "port": 8000
        },

虚拟主机:

ProxyPass /ws/ ws://127.0.0.1:8000/
ProxyPassReverse /ws/ ws://127.0.0.1:8000/

此外,如果您阅读其他教程,有些人会告诉您确保在虚拟主机文件中使用 ProxyPreserveHost 指令。不要听他们的!这会产生很多意想不到的结果。启用此指令后,此选项会将 Host: 行从传入请求传递到代理主机,而不是 ProxyPass 行中指定的主机名!甚至 Apache 都说要远离这个指令https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxypreservehost。如果您确实启用了它,您将收到类似于以下的错误:

failing WebSocket opening handshake ('missing port in HTTP Host header 
'example.org' and server runs on non-standard port 8000 (wss = 
False)')

最后但同样重要的是,确保已安装并启用以下所有 Apache 库。在最近的 Apache 安装中,默认情况下会安装以下所有库,只需启用即可:

$ sudo a2enmod proxy
$ sudo a2enmod proxy_http
$ sudo a2enmod proxy_balancer
$ sudo a2enmod lbmethod_byrequests
$ sudo a2enmod proxy_wstunnel

确保打开虚拟主机文件正在侦听的端口以及交叉开关路由器正在侦听的端口。就我而言:

$ sudo ufw allow 4043
$ sudo ufw allow 8000

最后重新启动 Apache,以便您的所有更改生效。

$ sudo service apache2 restart

最后但并非最不重要的一点是,我想快速解释一下为什么必须完成所有这些操作:

  1. 当您在服务器上设置 SSL 证书时,浏览器将在尝试连接到任何 WAMP 路由器而不使用 wss:// 时抛出错误。
  2. 通常对此的解决方案是配置您的 WAMP 路由器以使用已在您的服务器上设置的 SSL 证书。
  3. 唯一的问题是 Thruway.php(我知道的唯一一个可以与 WAMP 一起使用的好 php 客户端)不能很好地与 wss:// 配合使用。甚至 GitHub 上 Thruway.php 的创建者也说它不起作用。
  4. 此问题的解决方案是使用反向代理。
  5. 首先,您需要设置您的 WAMP 路由器并确保它没有使用 SSL 证书。
  6. 接下来,您需要设置一个反向代理,以便将 wss:// 请求转换为 ws://。这将允许您的浏览器连接到 WAMP 路由器而不会抱怨。
  7. 由于 WAMP 路由器未设置为使用 SSL,因此 Thruway.php 也可以正常工作!

好吧....这就是所有人!我知道我需要对这个问题给出一个详细的答案,因为我花了 5 天时间才弄清楚这一切!

于 2017-12-02T18:23:37.417 回答
0

@Tay-Bae 的回答已经非常有用了。但这对我不起作用,客户得到了 200 OK 响应。我需要做的就是将 WSS 流量转发到不支持 WSS(高速公路)的内部 WS 客户端。查看论坛后,我偶然发现了这个答案:https ://serverfault.com/a/846936 。他们添加了一个重写部分,似乎需要重新路由请求。我认为 ProxyPassReverse 应该这样做,但事实并非如此。所以这是我的工作配置:

Listen 4043
<VirtualHost *:4043>
        ServerName mydomain.net
        ProxyRequests off
        SSLProxyEngine on
        ProxyPass /ws/ ws://127.0.0.1:8080/
        ProxyPassReverse /ws/ ws://127.0.0.1:8080/

        ## Custom fragment
        SSLEngine on
        SSLCertificateFile /etc/letsencrypt/live/mydomaine.net/cert.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.net/privkey.pem
        SSLCertificateChainFile /etc/letsencrypt/live/mydomain.net/chain.pem

        <IfModule mod_rewrite.c>
                RewriteEngine on
                RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
                RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
                RewriteRule .* ws://localhost:8080%{REQUEST_URI} [P]
        </IfModule>

        LogLevel debug
        ErrorLog ${APACHE_LOG_DIR}/error_thruway.log
        CustomLog ${APACHE_LOG_DIR}/access_thruway.log combined
</VirtualHost>
于 2019-07-10T12:26:50.580 回答