Python 3:如何从服务器端记录SSL握手错误
我正在使用HTTPServer作为使用SSL的基本HTTP服务器.我想记录客户端何时启动SSL握手(或者可能是任何时候接受套接字?)以及任何相关的错误.我想我需要扩展一些类或覆盖一些方法,但我不确定哪个或如何正确地实现它.我非常感谢任何帮助.提前致谢!
修剪示例代码: from http.server import BaseHTTPRequestHandler,HTTPServer from socketserver import ThreadingMixIn from threading import Thread import ssl import logging import sys class MyHTTPHandler(BaseHTTPRequestHandler): def log_message(self,format,*args): logger.info("%s - - %s" % (self.address_string(),format%args)) def do_GET(self): self.send_response(200) self.end_headers() self.wfile.write('test'.encode("utf-8")) class ThreadedHTTPServer(ThreadingMixIn,HTTPServer): pass logger = logging.getLogger('myserver') handler = logging.FileHandler('server.log') formatter = logging.Formatter('[%(asctime)s] %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) logger.setLevel(logging.DEBUG) server = ThreadedHTTPServer(('',443),MyHTTPHandler) server.socket = ssl.wrap_socket (server.socket,keyfile='server.key',certfile='server.crt',server_side=True,cert_reqs=ssl.CERT_REQUIRED,ca_certs='client.crt') Thread(target=server.serve_forever).start() try: quitcheck = input("Type 'quit' at any time to quit.n") if quitcheck == "quit": server.shutdown() except (KeyboardInterrupt) as error: server.shutdown() 解决方法
从查看ssl模块开始,大部分相关的魔法都发生在
SSLSocket 课程中.
不幸的是,SSLSocket似乎没有自己的任何日志记录,因此没有简单的方法来打开日志记录级别,设置调试标志或注册任何处理程序. 所以你可以做的是继承SSLSocket,用自己的方法覆盖你感兴趣的方法做一些日志记录,并创建和使用你自己的wrap_socket辅助函数. 子类化SSLSocket 首先,将您的Python的… / lib / python2.7 / ssl.py中的 现在调整你的wrap_socket()副本 >创建一个LoggingSSLSocket实例(我们将在下面实现)而不是SSLSocket def wrap_socket(sock,keyfile=None,certfile=None,server_side=False,cert_reqs=ssl.CERT_NONE,ssl_version=ssl.PROTOCOL_SSLv23,ca_certs=None,do_handshake_on_connect=True,suppress_ragged_eofs=True,ciphers=None): return LoggingSSLSocket(sock=sock,keyfile=keyfile,certfile=certfile,server_side=server_side,cert_reqs=cert_reqs,ssl_version=ssl_version,ca_certs=ca_certs,do_handshake_on_connect=do_handshake_on_connect,suppress_ragged_eofs=suppress_ragged_eofs,ciphers=ciphers) 现在改变你的路线 server.socket = ssl.wrap_socket (server.socket,...) 至 server.socket = wrap_socket(server.socket,...) 为了使用你自己的wrap_socket(). 现在为子类化SSLSocket.通过在代码中添加以下内容,创建一个LoggingSSLSocket类,该类是SSLSocket的子类: class LoggingSSLSocket(ssl.SSLSocket): def accept(self,*args,**kwargs): logger.debug('Accepting connection...') result = super(LoggingSSLSocket,self).accept(*args,**kwargs) logger.debug('Done accepting connection.') return result def do_handshake(self,**kwargs): logger.debug('Starting handshake...') result = super(LoggingSSLSocket,self).do_handshake(*args,**kwargs) logger.debug('Done with handshake.') return result 这里我们重写ssl.SSLSocket的 覆盖方法的通用方法 我使用特定模式来覆盖这些方法,以便更容易应用于您将覆盖的几乎任何方法: def methodname(self,**kwargs): * args,** kwargs确保我们的方法接受任意数量的位置和关键字参数(如果有的话). accept实际上没有采取任何这些,但它仍然有效,因为Python的packing / unpacking of argument lists. logger.debug('Before call to superclass method') 在调用超类方法之前,你有机会做自己的事情. result = super(LoggingSSLSocket,self).methodname(*args,**kwargs) 这是对超类’方法的实际调用.有关其工作原理的详细信息,请参阅docs on 因为某些方法(如 logger.debug('After call.') return result 记录更多细节 如果要在日志记录语句中包含更多信息,则可能必须完全覆盖相应的方法.因此,将它们复制并根据需要进行修改,并确保满足任何缺少的导入. 以下是accept()的示例,其中包括尝试连接的客户端的IP地址和本地端口: def accept(self): """Accepts a new connection from a remote client,and returns a tuple containing that new connection wrapped with a server-side SSL channel,and the address of the remote client.""" newsock,addr = socket.accept(self) logger.debug("Accepting connection from '%s'..." % (addr,)) newsock = self.context.wrap_socket(newsock,do_handshake_on_connect=self.do_handshake_on_connect,suppress_ragged_eofs=self.suppress_ragged_eofs,server_side=True) logger.debug('Done accepting connection.') return newsock,addr (确保在代码顶部的导入中包含套接字导入套接字 – 请参阅 此方法将导致日志输出如下: [2014-10-24 22:01:40,299] Accepting connection from '('127.0.0.1',64152)'... [2014-10-24 22:01:40,300] Done accepting connection. [2014-10-24 22:01:40,301] Accepting connection from '('127.0.0.1',64153)'... [2014-10-24 22:01:40,302] Done accepting connection. [2014-10-24 22:01:40,306] Accepting connection from '('127.0.0.1',64155)'... [2014-10-24 22:01:40,307] Done accepting connection. [2014-10-24 22:01:40,308] 127.0.0.1 - - "GET / HTTP/1.1" 200 - 因为它涉及到遍布各地的相当多的变化,这里是gist containing all the changes to your example code. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |