[Twisted-Python] PyOpenSSL empty socket property
Arn Vollebregt
kpn.arn.vollebregt at gmail.com
Wed Sep 4 02:37:39 MDT 2019
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/twisted-python/attachments/20190904/62fa0936/attachment.html>
More information about the Twisted-Python
mailing list