WebSocket 连接到自签名服务器

Posted

技术标签:

【中文标题】WebSocket 连接到自签名服务器【英文标题】:WebSocket connection to self signed server 【发布时间】:2014-10-31 22:17:09 【问题描述】:

我想连接到我的 websocket 服务器,我基本上需要通过 https。

from tornado.options import define, options
from imaplib import Commands
define("port", default=443, help="run on the given port", type=int)

class WebSocketHandler(tornado.websocket.WebSocketHandler):
def __init__(self, *args, **kwargs):
    super(WebSocketHandler, self).__init__(*args, **kwargs);
    pass;
def open(self):
    print 'new connection'
    self.write_message("connected")

def on_message(self, message):
    print 'message received %s' % message
    self.write_message('message received %s' % message)

def on_close(self):
    print 'connection closed'

def check_origin(self, origin):
    return True;

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
       handlers=[
           (r"/ws", WebSocketHandler)
       ]
    )
    data_dir = "/home/pi/projects/WebSocketOverHttps/";
    httpServer = tornado.httpserver.HTTPServer(app, ssl_options = 
       "certfile": os.path.join(data_dir, "cert.crt"),
       "keyfile": os.path.join(data_dir, "key.key"),
    );
    httpServer.listen(options.port)
    print "Listening on port:", options.port
    tornado.ioloop.IOLoop.instance().start()

问题是我的浏览器显示:“与 'wss://192.168.1.8/ws' 的 WebSocket 连接失败:WebSocket 打开握手被取消”

我尝试做的事情是: 1)通过双击证书文件将证书添加到系统(win 8.1 PRO x64) 2)在同一系统上将证书添加到谷歌浏览器(通过浏览器的设置)

当我重新实现它以使用 http 而不是 https 时,我能够连接到该服务器,因此与机器的物理连接看起来没问题。

我的证书是自签名的,由命令生成:

sudo openssl req -x509 -nodes -days 365000 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt

这是我尝试连接到它的方式:

var socket = new WebSocket("wss://192.168.1.8:443/ws");

【问题讨论】:

你有什么版本的 Chrome? IIRC,他们在一个版本中添加了“拒绝自签名证书”修复,后来添加了“在 wss 和 https 之间共享可接受的自签名证书”,在这两者之间基本上没有办法指定可接受的自签名证书wss(全局忽略证书错误是唯一真正的解决方法)。 另外,我认为这个问题与您的代码无关。您可能想尝试 (a) 搜索没有 python 和 tornado 标记的类似问题,以及 (b) 看看是否可以使用通用 wss 服务器(例如 netcat 的 ws 代理)重现问题。 "38.0.2125.111 m" 是我的 Chrome 版本 这可能与***.com/questions/24949576/… 重复。我知道您说您手动将证书添加到 chrome,但我不确定这是否与您访问使用证书的页面时接受证书相同。 @BenDarnell,你说得对。我会把它作为我自己问题的答案。 【参考方案1】:

正如@BenDarnell 所发布的,我们必须通过浏览到此服务器的页面来接受此证书。然后您的浏览器将通知该站点不受信任。让您的浏览器使用这个不受信任的证书,仅此而已。这是您需要放入代码中的代码:

class MainHandler(tornado.web.RequestHandler):
  def get(self):
    loader = tornado.template.Loader(".")
    self.write(loader.load("index.html").generate());

app = tornado.web.Application(
handlers=[
   (r"/ws", WebSocketHandler),
   (r"/", MainHandler)
])

data_dir = "/home/pi/projects/Something";
ssl_options_dict = 
    "certfile": os.path.join(data_dir, "cert.crt"),
    "keyfile": os.path.join(data_dir, "key.key"),
;

httpServer = tornado.httpserver.HTTPServer(app, ssl_options = ssl_options_dict);

【讨论】:

以上是关于WebSocket 连接到自签名服务器的主要内容,如果未能解决你的问题,请参考以下文章

nv-websocket-client 自签名证书

如何在NodeJS中代理websocket连接到其他websockets

Chrome 无法连接到 websocket 服务器(操作码 -1)“握手被取消”

在 Node JS 中为 WebSocket (ws) 使用自签名 CA 证书

在节点JS中为WebSocket(ws)使用自签名CA证书

WebSocket 连接到“ws://chattestarpit.herokuapp.com/”失败:WebSocket 握手期间出错:意外响应代码:503