Re: PyOpenSSL empty socket property
Sean DiZazzo <[email protected]> Thu, 5 Sep 2019 23:07:33 -0700
| Newsgroups | gmane.comp.python.twisted |
|---|---|
| Message-ID | <CANzH6etmN2uaeSwHHiNqjypwegHtwBD6mGMLgE8T88KT7+8+6w@mail.gmail.com> |
--===============1979704781669944454== Content-Type: multipart/alternative; boundary="000000000000a8458d0591dc412a" --000000000000a8458d0591dc412a Content-Type: text/plain; charset="UTF-8" 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 <[email protected]> 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 > [email protected] > https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python > --000000000000a8458d0591dc412a Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div dir=3D"ltr">Perhaps this line from OpenSSL.SSL.Connec= tion is a clue.<div><br></div><div>"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."<div><a href=3D"https://www.pyopenssl.o= rg/en/stable/api/ssl.html#OpenSSL.SSL.Connection">https://www.pyopenssl.org= /en/stable/api/ssl.html#OpenSSL.SSL.Connection</a><span style=3D"color:rgb(= 64,64,64);font-family:Lato,proxima-nova,"Helvetica Neue",Arial,sa= ns-serif;font-size:16px;background-color:rgb(252,252,252)"><br></span></div= ></div><input name=3D"virtru-metadata" type=3D"hidden" value=3D"{"emai= l-policy":{"state":"closed","expirationUnit&q= uot;:"days","disableCopyPaste":false,"disablePrint= ":false,"disableForwarding":false,"enableNoauth":f= alse,"persistentProtection":false,"expandedWatermarking"= ;:false,"expires":false,"isManaged":false},"attach= ments":{},"compose-id":"1","compose-window&qu= ot;:{"secure":false}}"></div><br><div class=3D"gmail_quote" style= =3D""><div dir=3D"ltr" class=3D"gmail_attr">On Wed, Sep 4, 2019 at 1:38 AM = Arn Vollebregt <<a href=3D"mailto:[email protected]">kpn.arn.= [email protected]</a>> wrote:<br></div><blockquote class=3D"gmail_quo= te" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204= );padding-left:1ex"><div dir=3D"ltr"><div>Hi,</div><div><br></div><div>I no= ticed that PyOpenSSL SNI callbacks (set with <i>ctx.set_tlsext_servername_c= allback</i>) receive a <i>OpenSSL.SSL.Connection</i> object within Twisted = that have an empty <i>_socket</i> property, while this property <u>is</u> a= ctually set when using <i>PyOpenSSL</i> directly. For my use-case this is a= problem as I want to call <i>conn._socket.getpeername()</i> to determine t= he peer's IP address. So I am wondering: why is this behaviour differen= t? And how do I get the peer IP address?</div><div><br></div><div>---consol= e---</div><div>user:~$ sudo python testTwisted.py &</div><div>[3] 32842= </div><div>user:~$ curl -s --insecure --key clientPrivateKey.pem --cert cli= entCertificate.pem <a href=3D"https://127.0.0.1" target=3D"_blank">https://= 127.0.0.1</a> > /dev/null<br>'sniCallback' called.<br>=C2=A0 =C2= =A0 =C2=A0 =C2=A0 conn._socket: None<br>'verifyCallback' called for= result 0<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 conn._socket: None<br>'verifyC= allback' called for result 1<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 conn._socke= t: None</div><div>user:~$ sudo python testPyOpenSSL.py &<br>[1] 33270</= div><div>user:~$ curl -s --insecure --key clientPrivateKey.pem --cert clien= tCertificate.pem <a href=3D"https://127.0.0.1" target=3D"_blank">https://12= 7.0.0.1</a> > /dev/null<br>'sniCallback' called.<br>=C2=A0 =C2= =A0 =C2=A0 =C2=A0 conn._socket: <socket._socketobject object at 0x7f34c5= bd3130><br><class 'OpenSSL.SSL.Connection'><br>'verify= Callback' called for result 0<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 conn._sock= et: <socket._socketobject object at 0x7f34c5bd3130><br>'verifyCal= lback' called for result 1<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 conn._socket:= <socket._socketobject object at 0x7f34c5bd3130><br>127.0.0.1 - - [29= /Aug/2019 11:45:47] "GET / HTTP/1.1" 200 -</div><div>------<br></= div><div><br></div><div>---testTwisted.py---</div><div>### Generate server = key material ###<br># openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout=20 serverPrivateKey.pem -out serverCertificate.pem -subj=20 "/C=3D''/O=3D''/OU=3D''/CN=3Dserver"<br>#= ## Generate client key material ###<br># openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout=20 clientPrivateKey.pem -out clientCertificate.pem -subj=20 "/C=3D''/O=3D''/OU=3D''/CN=3Dclient"<br>f= rom __future__ import print_function<br>#<a href=3D"https://twistedmatrix.c= om/documents/12.0.0/core/howto/ssl.html" target=3D"_blank">https://twistedm= atrix.com/documents/12.0.0/core/howto/ssl.html</a><br>from OpenSSL import S= SL<br>from twisted.internet import ssl, reactor<br>from twisted.web import = server, resource<br>from twisted.internet.protocol import Factory, Protocol= <br><br>def verifyCallback(conn, cert, errno, depth, result):<br>=C2=A0 =C2= =A0 print('\'verifyCallback\' called for result ' + str(res= ult))<br>=C2=A0 =C2=A0 print('\tconn._socket: ' + str(conn._socket)= )<br>=C2=A0 =C2=A0 return True<br><br>def sniCallback(conn):<br>=C2=A0 =C2= =A0 print('\'sniCallback\' called.')<br>=C2=A0 =C2=A0 print= ('\tconn._socket: ' + str(conn._socket))<br><br>class MainResource(= resource.Resource):<br>=C2=A0 =C2=A0 isLeaf =3D True<br><br>=C2=A0 =C2=A0 d= ef render_GET(self, request):<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 request.respon= seHeaders.addRawHeader("Content-Type", "text/html; charset= =3Dutf-8")<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 return b"<html>&l= t;body>Hello World</body></html>"<br><br>if __name__ = =3D=3D '__main__':<br>=C2=A0 =C2=A0 myContextFactory =3D ssl.Defaul= tOpenSSLContextFactory(<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 'serverPrivateKe= y.pem',<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 'serverCertificate.pem'<= br>=C2=A0 =C2=A0 )<br>=C2=A0 =C2=A0 ctx =3D myContextFactory.getContext()<b= r>=C2=A0 =C2=A0 # <a href=3D"https://www.pyopenssl.org/en/stable/api/ssl.ht= ml#OpenSSL.SSL.Context.set_verify" target=3D"_blank">https://www.pyopenssl.= org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_verify</a><br>=C2=A0 =C2= =A0 ctx.set_verify(SSL.VERIFY_PEER, verifyCallback)<br>=C2=A0 =C2=A0 # <a h= ref=3D"https://pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set= _tlsext_servername_callback" target=3D"_blank">https://pyopenssl.org/en/sta= ble/api/ssl.html#OpenSSL.SSL.Context.set_tlsext_servername_callback</a><br>= =C2=A0 =C2=A0 ctx.set_tlsext_servername_callback(sniCallback)<br><br>=C2=A0= =C2=A0 site =3D server.Site(MainResource())<br>=C2=A0 =C2=A0 reactor.liste= nSSL(443, site, myContextFactory)<br>=C2=A0 =C2=A0 reactor.run()</div><div>= ------</div><div><br></div><div>---testPyOpenSSL.py---</div><div>### Genera= te server key material ###<br># openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout=20 serverPrivateKey.pem -out serverCertificate.pem -subj=20 "/C=3D''/O=3D''/OU=3D''/CN=3Dserver"<br>#= ## Generate client key material ###<br># openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout=20 clientPrivateKey.pem -out clientCertificate.pem -subj=20 "/C=3D''/O=3D''/OU=3D''/CN=3Dclient"<br>f= rom __future__ import print_function<br>import socket, sys, os<br>from Sock= etServer import BaseServer<br>from BaseHTTPServer import HTTPServer<br>from= SimpleHTTPServer import SimpleHTTPRequestHandler<br>from OpenSSL import SS= L<br><br>def verifyCallback(conn, cert, errno, depth, result):<br>=C2=A0 = =C2=A0 print('\'verifyCallback\' called for result ' + str(= result))<br>=C2=A0 =C2=A0 print('\tconn._socket: ' + str(conn._sock= et))<br>=C2=A0 =C2=A0 return True<br><br>def sniCallback(conn):<br>=C2=A0 = =C2=A0 print('\'sniCallback\' called.')<br>=C2=A0 =C2=A0 pr= int('\tconn._socket: ' + str(conn._socket))<br>=C2=A0 =C2=A0 print(= type(conn))<br><br>class SecureHTTPServer(HTTPServer):<br>=C2=A0 =C2=A0 def= __init__(self, server_address, HandlerClass):<br>=C2=A0 =C2=A0 =C2=A0 =C2= =A0 BaseServer.__init__(self, server_address, HandlerClass)<br>=C2=A0 =C2= =A0 =C2=A0 =C2=A0 ctx =3D SSL.Context(SSL.TLSv1_2_METHOD)<br>=C2=A0 =C2=A0 = =C2=A0 =C2=A0 ctx.use_privatekey_file('serverPrivateKey.pem')<br>= =C2=A0 =C2=A0 =C2=A0 =C2=A0 ctx.use_certificate_file('serverCertificate= .pem')<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 # <a href=3D"https://www.pyopenss= l.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_verify" target=3D"_bla= nk">https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.se= t_verify</a><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 ctx.set_verify(SSL.VERIFY_PEER,= verifyCallback)<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 # <a href=3D"https://pyopen= ssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_tlsext_servername_ca= llback" target=3D"_blank">https://pyopenssl.org/en/stable/api/ssl.html#Open= SSL.SSL.Context.set_tlsext_servername_callback</a><br>=C2=A0 =C2=A0 =C2=A0 = =C2=A0 ctx.set_tlsext_servername_callback(sniCallback)<br>=C2=A0 =C2=A0 =C2= =A0 =C2=A0 self.socket =3D SSL.Connection(ctx, socket.socket(self.address_f= amily,self.socket_type))<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 self.server_bind()<= br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 self.server_activate()<br>=C2=A0 =C2=A0 <br>= =C2=A0 =C2=A0 def shutdown_request(self,request):<br>=C2=A0 =C2=A0 =C2=A0 = =C2=A0 request.shutdown()<br><br>class SecureHTTPRequestHandler(SimpleHTTPR= equestHandler):<br>=C2=A0 =C2=A0 def setup(self):<br>=C2=A0 =C2=A0 =C2=A0 = =C2=A0 self.connection =3D self.request<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 self= .rfile =3D socket._fileobject(self.request, "rb", self.rbufsize)<= br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 self.wfile =3D socket._fileobject(self.reque= st, "wb", self.wbufsize)<br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 def d= o_GET(self):<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 self.send_response(200)<br>=C2= =A0 =C2=A0 =C2=A0 =C2=A0 SimpleHTTPRequestHandler.end_headers(self)<br>=C2= =A0 =C2=A0 =C2=A0 =C2=A0 self.wfile.write('<html><body>Hell= o World</body></html>')<br><br>if __name__ =3D=3D '__ma= in__':<br>=C2=A0 =C2=A0 ip,port =3D ('0.0.0.0', 443)<br>=C2=A0 = =C2=A0 httpd =3D SecureHTTPServer((ip, port), SecureHTTPRequestHandler)<br>= =C2=A0 =C2=A0 httpd.serve_forever()</div><div>------</div><div><br></div><d= iv>(Please note that even though these examples are for Python2 (due to oth= er quirks) I am aiming to implement this in Python3.)<br></div><div><br></d= iv><div>Regards,</div><div><br></div><div>Arn</div></div> _______________________________________________<br> Twisted-Python mailing list<br> <a href=3D"mailto:[email protected]" target=3D"_blank">Twist= [email protected]</a><br> <a href=3D"https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-pytho= n" rel=3D"noreferrer" target=3D"_blank">https://twistedmatrix.com/cgi-bin/m= ailman/listinfo/twisted-python</a><br> </blockquote></div></div> --000000000000a8458d0591dc412a-- --===============1979704781669944454== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KVHdpc3RlZC1Q eXRob24gbWFpbGluZyBsaXN0ClR3aXN0ZWQtUHl0aG9uQHR3aXN0ZWRtYXRyaXguY29tCmh0dHBz Oi8vdHdpc3RlZG1hdHJpeC5jb20vY2dpLWJpbi9tYWlsbWFuL2xpc3RpbmZvL3R3aXN0ZWQtcHl0 aG9uCg== --===============1979704781669944454==--