Search code examples
openssldockersockjs-tornado

OpenSSL error on Tornado server


I configure my Tornado server with:

ssl_options = { 
    "certfile": os.path.join("/tls.crt"),
    "keyfile": os.path.join("/tls.key")
}   
http = tornado.httpserver.HTTPServer(application, ssl_options=ssl_options)

tls.crt and tls.key are wildcarded for my domain, which I use successfully in another app in my stack behind HAPROXY, the latter terminating TLS.

The server on startup reports OpenSSL version:

OpenSSL 1.0.1k 8 Jan 2015

Browser

However, when fetch / from the browser (which eventually says "This web page is not available"), this appears in the Tornado STDOUT:

 [E 150228 15:05:52 ioloop:588] Exception in callback (<socket._socketobject object at 0x7ff342d37050>, <function null_wrapper at 0x7ff342d418c0>)
     Traceback (most recent call last):
       File "/usr/local/lib/python2.7/site-packages/tornado/ioloop.py", line 840, in start
         handler_func(fd_obj, events)
       File "/usr/local/lib/python2.7/site-packages/tornado/stack_context.py", line 275, in null_wrapper
         return fn(*args, **kwargs)
       File "/usr/local/lib/python2.7/site-packages/tornado/netutil.py", line 223, in accept_handler
         callback(connection, address)
       File "/usr/local/lib/python2.7/site-packages/tornado/tcpserver.py", line 225, in _handle_connection
         do_handshake_on_connect=False)
       File "/usr/local/lib/python2.7/site-packages/tornado/netutil.py", line 459, in ssl_wrap_socket
         context = ssl_options_to_context(ssl_options)
       File "/usr/local/lib/python2.7/site-packages/tornado/netutil.py", line 436, in ssl_options_to_context
         context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))
     SSLError: [SSL] PEM lib (_ssl.c:2506)

cURL

Curling the endpoint shows:

* About to connect() to example.org port 443 (#0)
*   Trying 54.154.175.173... connected
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* Unknown SSL protocol error in connection to example.org:443 
* Closing connection #0
curl: (35) Unknown SSL protocol error in connection to example.org:443

openssl s_client

openssl s_client -connect example.org:443

Just hangs on:

CONNECTED(00000003)

I've cloned https://github.com/openssl/openssl.git and checked out the 1.0.1k tag, but can't find _ssl.c, so pointers here will be a good start.

I've also pointed CryptoNark at my domain, but just get empty output.

The host OS is AWS AMI ami-6330b7141. The Docker container for the app is python:2.7 version 31ff30c97af1.

UPDATE

The line in _ssl.c seems to be part of Python 3 backported stuff by @benjamin-peterson I'll try with latest Python 3.4.


Solution

  • After looking at the error line in _ssl.c, the problem was in fact with the certificate (the error message PEM lib was probably indicative enough of that).

    I set it via an environment variable, after doing this on the original certificate file:

    awk 1 ORS='\\n' star.example.org.cert
    

    Then in my Python app:

     with open('/tls.crt', 'w') as crt:
         crt.write(os.environ.get('SSL_CRT'));
    

    Problem is, those newlines remained as \n, so I moved this step up to a Bash script:

    if [ -n "$SSL_CRT" ]; then
        rm /tls.crt
        echo "SSL certificate provided!"
        echo -e "${SSL_CRT}" > /tls.crt
    else
        echo "No SSL certificate provided"
    fi
    python app.py
    

    It works now. A face-palm moment indeed.