[Twisted-Python] PyOpenSSL empty socket property

Sean DiZazzo sean.dizazzo at gmail.com
Fri Sep 6 00:07:33 MDT 2019


Perhaps this line from OpenSSL.SSL.Connection is a clue.

"socket may be None; in this case, the Connection is created with a memory
BIO: see the bio_read(), bio_write(), and bio_shutdown() methods."
https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Connection

On Wed, Sep 4, 2019 at 1:38 AM Arn Vollebregt <kpn.arn.vollebregt at gmail.com>
wrote:

> Hi,
>
> I noticed that PyOpenSSL SNI callbacks (set with
> *ctx.set_tlsext_servername_callback*) receive a *OpenSSL.SSL.Connection*
> object within Twisted that have an empty *_socket* property, while this
> property *is* actually set when using *PyOpenSSL* directly. For my
> use-case this is a problem as I want to call *conn._socket.getpeername()*
> to determine the peer's IP address. So I am wondering: why is this
> behaviour different? And how do I get the peer IP address?
>
> ---console---
> user:~$ sudo python testTwisted.py &
> [3] 32842
> user:~$ curl -s --insecure --key clientPrivateKey.pem --cert
> clientCertificate.pem https://127.0.0.1 > /dev/null
> 'sniCallback' called.
>         conn._socket: None
> 'verifyCallback' called for result 0
>         conn._socket: None
> 'verifyCallback' called for result 1
>         conn._socket: None
> user:~$ sudo python testPyOpenSSL.py &
> [1] 33270
> user:~$ curl -s --insecure --key clientPrivateKey.pem --cert
> clientCertificate.pem https://127.0.0.1 > /dev/null
> 'sniCallback' called.
>         conn._socket: <socket._socketobject object at 0x7f34c5bd3130>
> <class 'OpenSSL.SSL.Connection'>
> 'verifyCallback' called for result 0
>         conn._socket: <socket._socketobject object at 0x7f34c5bd3130>
> 'verifyCallback' called for result 1
>         conn._socket: <socket._socketobject object at 0x7f34c5bd3130>
> 127.0.0.1 - - [29/Aug/2019 11:45:47] "GET / HTTP/1.1" 200 -
> ------
>
> ---testTwisted.py---
> ### Generate server key material ###
> # openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout
> serverPrivateKey.pem -out serverCertificate.pem -subj
> "/C=''/O=''/OU=''/CN=server"
> ### Generate client key material ###
> # openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout
> clientPrivateKey.pem -out clientCertificate.pem -subj
> "/C=''/O=''/OU=''/CN=client"
> from __future__ import print_function
> #https://twistedmatrix.com/documents/12.0.0/core/howto/ssl.html
> from OpenSSL import SSL
> from twisted.internet import ssl, reactor
> from twisted.web import server, resource
> from twisted.internet.protocol import Factory, Protocol
>
> def verifyCallback(conn, cert, errno, depth, result):
>     print('\'verifyCallback\' called for result ' + str(result))
>     print('\tconn._socket: ' + str(conn._socket))
>     return True
>
> def sniCallback(conn):
>     print('\'sniCallback\' called.')
>     print('\tconn._socket: ' + str(conn._socket))
>
> class MainResource(resource.Resource):
>     isLeaf = True
>
>     def render_GET(self, request):
>         request.responseHeaders.addRawHeader("Content-Type", "text/html;
> charset=utf-8")
>         return b"<html><body>Hello World</body></html>"
>
> if __name__ == '__main__':
>     myContextFactory = ssl.DefaultOpenSSLContextFactory(
>         'serverPrivateKey.pem',
>         'serverCertificate.pem'
>     )
>     ctx = myContextFactory.getContext()
>     #
> https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_verify
>     ctx.set_verify(SSL.VERIFY_PEER, verifyCallback)
>     #
> https://pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_tlsext_servername_callback
>     ctx.set_tlsext_servername_callback(sniCallback)
>
>     site = server.Site(MainResource())
>     reactor.listenSSL(443, site, myContextFactory)
>     reactor.run()
> ------
>
> ---testPyOpenSSL.py---
> ### Generate server key material ###
> # openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout
> serverPrivateKey.pem -out serverCertificate.pem -subj
> "/C=''/O=''/OU=''/CN=server"
> ### Generate client key material ###
> # openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout
> clientPrivateKey.pem -out clientCertificate.pem -subj
> "/C=''/O=''/OU=''/CN=client"
> from __future__ import print_function
> import socket, sys, os
> from SocketServer import BaseServer
> from BaseHTTPServer import HTTPServer
> from SimpleHTTPServer import SimpleHTTPRequestHandler
> from OpenSSL import SSL
>
> def verifyCallback(conn, cert, errno, depth, result):
>     print('\'verifyCallback\' called for result ' + str(result))
>     print('\tconn._socket: ' + str(conn._socket))
>     return True
>
> def sniCallback(conn):
>     print('\'sniCallback\' called.')
>     print('\tconn._socket: ' + str(conn._socket))
>     print(type(conn))
>
> class SecureHTTPServer(HTTPServer):
>     def __init__(self, server_address, HandlerClass):
>         BaseServer.__init__(self, server_address, HandlerClass)
>         ctx = SSL.Context(SSL.TLSv1_2_METHOD)
>         ctx.use_privatekey_file('serverPrivateKey.pem')
>         ctx.use_certificate_file('serverCertificate.pem')
>         #
> https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_verify
>         ctx.set_verify(SSL.VERIFY_PEER, verifyCallback)
>         #
> https://pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_tlsext_servername_callback
>         ctx.set_tlsext_servername_callback(sniCallback)
>         self.socket = SSL.Connection(ctx,
> socket.socket(self.address_family,self.socket_type))
>         self.server_bind()
>         self.server_activate()
>
>     def shutdown_request(self,request):
>         request.shutdown()
>
> class SecureHTTPRequestHandler(SimpleHTTPRequestHandler):
>     def setup(self):
>         self.connection = self.request
>         self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
>         self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
>
>     def do_GET(self):
>         self.send_response(200)
>         SimpleHTTPRequestHandler.end_headers(self)
>         self.wfile.write('<html><body>Hello World</body></html>')
>
> if __name__ == '__main__':
>     ip,port = ('0.0.0.0', 443)
>     httpd = SecureHTTPServer((ip, port), SecureHTTPRequestHandler)
>     httpd.serve_forever()
> ------
>
> (Please note that even though these examples are for Python2 (due to other
> quirks) I am aiming to implement this in Python3.)
>
> Regards,
>
> Arn
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/twisted-python/attachments/20190905/bb7c8453/attachment-0002.html>


More information about the Twisted-Python mailing list