【问题标题】:WebSocket connection to 'wss://mydomain.com:3001/' failed: Error in connection establishment: net::ERR_CONNECTION_CLOSEDWebSocket 连接到“wss://mydomain.com:3001/”失败:连接建立错误:net::ERR_CONNECTION_CLOSED
【发布时间】:2015-12-04 05:59:27
【问题描述】:

rails 2.3.18 和 ruby​​ 0.9.2 中的 em-websocket 配置

应用程序托管在 https: 和 http: sebsocket 上工作在 staging(http://) 域上,但是当我们将其转移到 https:// 时,websocket 在同一时间后自动关闭。并且在webconsole中遇到如下错误

WebSocket connection to 'wss://my_domain.com:3001/' failed: Error in connection establishment: net::ERR_CONNECTION_CLOSED

websocket.ym

 production:
   host: '0.0.0.0'
   port: 3001
   secure: true
   tls_options:
     private_key_file: filename.com.key
     cert_chain_file: filename.com.crt

websockets-app/app.rb

em-websocet 配置文件位置

“application_directory/websockets-app/app.rb”,它包含以下配置

require 'thin'
require 'em-websocket'
require 'yaml'
require 'active_support/core_ext/hash'

env          = ENV['WS_ENV'] || :development
logfile      = File.open('../log/websocket.log', 'a')
logfile.sync = true
WS_LOGGER    = Logger.new(logfile)
CONFIG       = YAML.load_file('../config/websocket.yml').with_indifferent_access[env]
EM.run do
    WS_LOGGER.info("Starting WebSockets server on port #{CONFIG[:port]}")
    @channel = EM::Channel.new
    WS_LOGGER.info("ENV:- #{env}")
    WS_LOGGER.info("CHANNEL:-----+#{@channel.inspect}")
  #EM::WebSocket.start(:host => '0.0.0.0', :port => '3001') do |ws|
  EM::WebSocket.start(CONFIG) do |ws|
    WS_LOGGER.info("Socket started----")
    WS_LOGGER.info("Socket inspect#{ws.inspect}")

    ws.onopen do |handshake|
    WS_LOGGER.info("HANDSHAKE:---WS open now!!")
    WS_LOGGER.info("handshake.secure? ..... #{handshake.secure?}")
      sid = @channel.subscribe { |msg| ws.send msg }
    WS_LOGGER.info("<#{sid}> WebSocket connection open")

      ws.onclose do
    @channel.unsubscribe(sid)
    WS_LOGGER.info("<#{sid}> Connection closed")
      end

      ws.onmessage do |msg|
    @channel.push msg
    WS_LOGGER.info("<#{sid}> Received Message: #{msg}")
      end
   end
  end
end

在生产模式下启动 websocket

WS_ENV=production bundle exec thin start -R app.rb &

检查日志

Starting WebSockets server on port 3001
I, [2015-12-03T20:50:25.588306 #4861]  INFO -- : ENV:- production
I, [2015-12-03T20:50:25.588341 #4861]  INFO -- : CHANNEL:-----+#   <EventMachine::Channel:0x315e908 @uid=0, @subs={}>
I, [2015-12-03T20:50:53.723973 #4861]  INFO -- : Socket started----
I, [2015-12-03T20:50:53.724169 #4861]  INFO -- : Socket inspect#<EventMachine::WebSocket::Connection:0x315dee0 @secure=true, @tls_options=
{"private_key_file"=>"filename.com.key", "cert_chain_file"=>"filename.com.crt"}, @debug=false, @signature=4, @close_timeout=nil, @handler=nil, @secure_proxy=false, @options=   {"port"=>3001, "secure"=>true, "tls_options"=>{"private_key_file"=>"filename.com.key", "cert_chain_file"=>"filename.com.crt"}, "host"=>"0.0.0.0"}>

用Javascript创建webSocket实例###

host = "wss://mydomain.com:3001"; socket = new WebSocket(host);

【问题讨论】:

  • 这是在 http 中的完美工作
  • 服务器日志说什么?
  • @dan,当我们使用以下命令“WS_ENV=production bundle exec thin start -R app.rb &”启动它时,它表示套接字从端口号 3001 开始,其余是检查的元素,即在 CONFIG 哈希中传递给“EM::WebSocket.start(CONFIG)”
  • 并在 https:// 环境中关闭了一段时间,但在 http:// 中运行良好
  • 您要签入什么服务器日志?

标签: javascript ruby-on-rails ruby


【解决方案1】:

为什么使用 SSL/TLS 应该失败(留给代理)

大多数代理和生产应用程序“包装器”(即 Heroku Dynos)在将任何 SSL 数据转发到处理应用程序之前对其进行解密。

即,当使用 nginx 作为 SSL 连接的代理时,证书和加密通常由 nginx 管理并且数据以明文形式发送到本地应用程序

您的问题的答案应该是为您的应用使用明文并让本地代理处理 SSL/TLS 加密。

为了证明我的观点:

由于我不喜欢 em-websocket(我偏向于我自己的宠物项目),这里有一个快速的 Plezi 应用程序,有和没有自签名 SSL 证书。

在正常的生产环境(即 nginx、apache、Heroku 等)中运行此应用程序应显示应用程序在不安全时可使用 httpshttp 访问,并且在应用程序无法访问时本身需要加密连接。

GEMFILE:

gem 'plezi'

app.rb:

#!/usr/bin/env ruby
require 'plezi'
class MyDemo
  # Http demo
  def index
     request.ssl? ? "Hello World (SSL/TLS)" : "Hello World (clear)"
  end
  # Websocket echo
  def on_message data
     write data # writes to the websocket
  end
end
route '/', MyDemo

使用明文运行应用程序:

./app.rb -p $PORT
# or static port, i.e.
# ./app.rb -p 3000

为加密连接运行应用程序:

./app.rb -p $PORT ssl
# or static port, i.e.
# ./app.rb -p 3000 ssl

如果您正确设置了生产代理或 Heroku Dyno(或您正在使用的任何东西),该应用程序应该适用于 httphttpswswss,仅当它是明文形式时模式,并且在 SSL 模式下总是会失败。

附言

可以在应用程序中设置 SSL 密钥和证书,以避免使用自签名证书,以防万一您想知道或认为这是问题所在。将以下行添加到您的应用中:

Plezi.ssl_context.cert = IO.binread("filename.com.crt")
Plezi.ssl_context.key = IO.binread("filename.com.key")

另外,我是 Plezi 的作者,所以在涉及 em-websockets 的地方我有点偏颇……

【讨论】:

    猜你喜欢
    • 2016-03-11
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-18
    • 2019-08-30
    • 2014-12-19
    相关资源
    最近更新 更多