我正在使用SSL和自签名证书在Python 2.7.5 virtualenv中运行Tornado 4.0.2,并且以下SSLError会反复出现:
SSLError: [Errno 1] _ssl.c:1419: error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca
以下几个问题:
我假设这些例外是由于客户对我的自签名证书感到不满。这是对的吗?
假设是这种情况 - 我不关心这个异常,我不想在日志中看到它。 (这是一个内部网络服务器 - 我们永远不会为CA付费。所有连接都必须是不受信任的。)为了尝试自己捕获异常,我尝试按如下方式对IOLoop进行子类化:
class MyIOLoop(IOLoop):
def handle_callback_exception(callback):
print "Exception in callback", callback
if __name__ == "__main__":
app = Application(urls, compress_response = True)
ioloop=MyIOLoop.instance()
http_server = httpserver.HTTPServer(app, ssl_options={"certfile": "cert.pem", "keyfile": "key.pem" }, io_loop=ioloop )
http_server.listen(8888)
ioloop.start()
但这没有帮助 - 我仍然得到完整的堆栈跟踪。
我自己需要做些什么来处理(即忽略)此类异常?我已尝试在ssl_options中设置cert_reqs" : ssl.CERT_NONE
,但这也没有帮助。
答案 0 :(得分:1)
我也asked this question on the Tornado mailing list,得到了以下回复:
此错误来自HTTP1ServerConnection,而不是IOLoop(我想 错误使得它一直到IOLoop这些都是不常见的 天)。你是对的,这意味着客户拒绝了 连接,因为它不信任您的证书。这可以说是有道理的 在这种情况下记录某些东西很有用(你想知道是否这样 开始发生了很多),但它最多应该是一行而不是 完整的堆栈跟踪。把它当作更像是也可能更好 ECONNRESET并且不记录任何内容。
我们目前没有公开任何有用的方法来自定义此日志记录, 但您可以在日志记录模块中自行选择。你可以附上一个 过滤到记录器并阻止exc_info [0]为SSLError的条目 例如,exc_info [1]有正确的错误代码。
我最终按照建议为Tornado的记录器添加了一个过滤器。一个轻微的障碍是record.exc_info
有时是None
,但在这种情况下,我能够从record.args
中获取足够的信息来决定是否要过滤它。
答案 1 :(得分:0)
从helgridly's own answer开始:错误can't be caught,但您可以filter日志。
tornado.general
记录器例如:
def ssl_log_filter(record):
if record.exc_info is not None:
e = record.exc_info[1]
elif len(record.args) >= 3 and isinstance(record.args[2], Exception):
e = record.args[2]
else:
e = None
if isinstance(e, SSLEOFError):
return False
if isinstance(e, SSLError):
if e.reason in {'NO_SHARED_CIPHER'}:
return False
return True
logging.getLogger('tornado.general').addFilter(ssl_log_filter)
上面的代码仅适用于Python 3.2+。对于旧版本,请改为子类Filter
。