WSGIServer listens for TLS connections, how to cleanly handle non-TLS connections?

602 views
Skip to first unread message

Mike Schiffman

unread,
Jul 16, 2019, 9:11:15 PM7/16/19
to gevent: coroutine-based Python network library
Hi guys! Still quite new to gevent. I built a Flask app and am serving it via:


server = WSGIServer(('0.0.0.0', port), flaskapp, keyfile = api_private_key_file, certfile = api_certificate_file)
...
server.serve_forever()

When I hit the WSGI server from a client speaking TLS, all is well. When I hit it from a client not using TLS, I get the following Traceback:

Traceback (most recent call last):
  File "src/gevent/greenlet.py", line 766, in gevent._greenlet.Greenlet.run
  File "/usr/local/lib/python3.5/dist-packages/gevent/baseserver.py", line 26, in _handle_and_close_when_done
    return handle(*args_tuple)
  File "/usr/local/lib/python3.5/dist-packages/gevent/server.py", line 201, in wrap_socket_and_handle
    with _closing_socket(self.wrap_socket(client_socket, **self.ssl_args)) as ssl_socket:
  File "/usr/local/lib/python3.5/dist-packages/gevent/_ssl3.py", line 693, in wrap_socket
    ciphers=ciphers)
  File "/usr/local/lib/python3.5/dist-packages/gevent/_ssl3.py", line 267, in __init__
    raise x
  File "/usr/local/lib/python3.5/dist-packages/gevent/_ssl3.py", line 263, in __init__
    self.do_handshake()
  File "/usr/local/lib/python3.5/dist-packages/gevent/_ssl3.py", line 587, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: HTTP_REQUEST] http request (_ssl.c:720)
2019-07-17T01:02:07Z <Greenlet at 0x7fdfa8d12448: _handle_and_close_when_done(<bound method StreamServer.wrap_socket_and_handle , <bound method StreamServer.do_close of <WSGIServer, (<gevent._socket3.socket [closed]  object, fd=-1, )> failed with SSLError

How can I make WSGIServer cleanly handle (in a "no thank you" sort of way) non TLS incoming connection requests?

Jason Madden

unread,
Jul 17, 2019, 9:48:33 AM7/17/19
to gev...@googlegroups.com

> On Jul 16, 2019, at 20:11, Mike Schiffman <themikes...@gmail.com> wrote:
>
>
> When I hit the WSGI server from a client speaking TLS, all is well. When I hit it from a client not using TLS, I get the following Traceback:
>
> Traceback (most recent call last):
> File "src/gevent/greenlet.py", line 766, in gevent._greenlet.Greenlet.run
> File "/usr/local/lib/python3.5/dist-packages/gevent/baseserver.py", line 26, in _handle_and_close_when_done
> return handle(*args_tuple)
> File "/usr/local/lib/python3.5/dist-packages/gevent/server.py", line 201, in wrap_socket_and_handle
> with _closing_socket(self.wrap_socket(client_socket, **self.ssl_args)) as ssl_socket:
> File "/usr/local/lib/python3.5/dist-packages/gevent/_ssl3.py", line 693, in wrap_socket
> ciphers=ciphers)
> File "/usr/local/lib/python3.5/dist-packages/gevent/_ssl3.py", line 267, in __init__
> raise x
> File "/usr/local/lib/python3.5/dist-packages/gevent/_ssl3.py", line 263, in __init__
> self.do_handshake()
> File "/usr/local/lib/python3.5/dist-packages/gevent/_ssl3.py", line 587, in do_handshake
> self._sslobj.do_handshake()
> ssl.SSLError: [SSL: HTTP_REQUEST] http request (_ssl.c:720)
> 2019-07-17T01:02:07Z <Greenlet at 0x7fdfa8d12448: _handle_and_close_when_done(<bound method StreamServer.wrap_socket_and_handle , <bound method StreamServer.do_close of <WSGIServer, (<gevent._socket3.socket [closed] object, fd=-1, )> failed with SSLError
>
> How can I make WSGIServer cleanly handle (in a "no thank you" sort of way) non TLS incoming connection requests?


This happens with many servers (gunicorn examples: [1][2]). The underlying SSL library is, rightly, strict in what it accepts. The server has been told to expect TLS traffic, and TLS traffic isn't what it gets, so rather than risk any further tainted communications, it shuts down.

If you wanted not to report this as an error you could subclass WSGIServer and override `wrap_socket_and_handle` to catch and ignore the exception (though that's not a documented public API at the moment, so it could change). Or you could customize the hub's `NOT_ERROR` property to include `SSLError` (though that's a pretty broad stroke).

I like to put an SSL proxy such as stunnel[4] in front of a WSGI server and offload all the SSL interactions to it.

[1] https://github.com/benoitc/gunicorn/issues/1574
[2] https://github.com/benoitc/gunicorn/issues/2078
[3] http://www.gevent.org/api/gevent.hub.html#gevent.hub.Hub.NOT_ERROR
[4] https://www.stunnel.org
Reply all
Reply to author
Forward
0 new messages