具有中间证书和交叉签名证书的Crossbar SSL / TLS配置

时间:2016-04-27 12:36:38

标签: websocket tls1.2 crossbar thruway

使用最新版本的Crossbar(0.13,从apt-get安装在Ubuntu 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警报握手失败

哪个having spoken with the Thruway team似乎是证书问题 - 在我们的实际网站上,我们使用了某些浏览器所需的intermediate and cross-signed certificate from Gandi,因此需要一些open-ssl实现。

虽然浏览器很乐意只使用密钥和证书建立TLS连接,但Thruway需要一个链。但是,下面使用Gandi提供的两个证书的配置不适用于 Chrome或Thruway。 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"
            ]
        }
    ]
}

还有其他问题可以解决类似于@

的问题
  • This one处理任何TLS错误都会终止WSS连接而没有任何有用错误的事实。
  • This one专门处理握手取消,但在他们的情况下,它是编译时使用的配置不正确的库,在这种情况下,由于apt-get

2 个答案:

答案 0 :(得分:0)

这不是Crossbar的问题。这似乎是WAMP客户端的一个问题 - 高速公路。 Davidwdan是Thruway Github回购的所有者,他说:

  

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

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

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

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

  1. 关注Crossbar的安装教程!不要试图自己做!设置Crossbar还有更多功能可以满足您的需求。 Crossbar的优秀人员为您准备了详细的说明! https://crossbar.io/docs/Installation/
  2. 对于此示例,我在同一台计算机上运行Crossbar和Apache。虽然这不是要求而且无关紧要!
  3. 您要做的第一件事是创建一个新的虚拟主机。我为这个虚拟主机选择了端口4043,但你可以选择你想要的任何东西。这个虚拟主机将用于每个没有通过wss://(使用SSL)连接的WAMP库。以下是WAMP客户的完整列表:http://wamp-proto.org/implementations/。确保ProxyPass指令和ProxyPassReverse指令具有指向CROSSBAR路由器所在机器的IP地址。在我的情况下,由于Apache和Crossbar在同一台机器上运行,我只使用127.0.0.1。还要确保在ProxyPass指令和ProxyPassReverse指令中使用的端口与您在.crossbar / config.json中定义的端口完全相同!您还需要在此虚拟主机上设置SSL证书,您可以看到我在Proxy指令下面添加了该证书。

    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 WON连接的磁带库如果您将路由器配置为使用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"
                }
              }
            }
          }
        }
       ]
      }
     ]
    }  
    

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

    ./横杆/ 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证书时,如果不使用wss://尝试连接到任何WAMP路由器,浏览器将抛出错误。
    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也能正常工作!
    8. 而且......那是所有人!我知道我需要对这个问题给出一个详细的答案,因为我花了5天的时间来计算这一切!

答案 1 :(得分:0)

@ Tay-Bae的回答已经非常有用。但这对我不起作用,客户得到200 OK响应。我要做的就是将WSS通信转发到不支持WSS(Thruway)的内部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>