Gunicorn 23 schannel: failed to receive handshake, SSL/TLS connection failed
I am trying to configure TLS support for my Gunicorn and Django app. Reviewing https://docs.gunicorn.org/en/stable/settings.html and configure the gunicorn.conf.py file or using the CLI for TLS cert/key/cacerts does not work.
I think the settings documentation could be improved showing what config file varaibles are needed and an example to get TLS 1.2 working and TLS 1.3 ssl_context working.
Is their an example out their to go by? My requirements are that traffic between the Nginx reverse proxy and Gunicorn use TLS. I have a 3rd party CA signed certificate, dir below.
Below is the curl trace and gunicorn.conf.py file.
#!/usr/bin/python
# /home/djangoweb, gunicorn -c cloudmonitor/gunicorn.conf.py --error-logfile -,
# tail -f /home/djangoweb/logs/httpd_error.log
import multiprocessing
#
wsgi_app = "cloudmonitor.wsgi:application"
bind = "192.168.46.69:9450"
daemon = 'True'
default_proc_name = 'gunicorn_httpd'
reload = 'True'
#
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = 'sync'
worker_connections = 1000
timeout = 30
keepalive = 2
#
errorlog = '/home/djangoweb/logs/httpd_error.log'
accesslog = '/home/djangoweb/logs/httpd_access.log'
#
ssl_version = 'TLS_SERVER'
cert_reqs = "2"
certfile = '/home/djangoweb/certs/star.mydomain.com.pem'
keyfile = '/home/djangoweb/certs/private/star.mydomain.key'
cacert = '/home/djangoweb/certs/cacerts/DigiCertCA.crt'
def ssl_context(conf, default_ssl_context_factory):
import ssl
context = default_ssl_context_factory()
context.minimum_version = ssl.TLSVersion.TLSv1_3
return context
do_handshake_on_connect = 'true'
curl -v --trace - https://server01.mydomain.com:9450/dashboard
Warning: --trace overrides an earlier trace/verbose option
== Info: Host server01.mydomain.com:9450 was resolved.
== Info: IPv6: (none)
== Info: IPv4: 192.168.46.69
== Info: Trying 192.168.46.69:9450...
== Info: Connected to inap-aws-cm01.mydomain.com (192.168.46.69) port 9450
== Info: schannel: disabled automatic use of client certificate
== Info: ALPN: curl offers http/1.1
== Info: schannel: failed to receive handshake, SSL/TLS connection failed
== Info: Closing connection
== Info: schannel: shutting down SSL/TLS connection with server01.mydomain.com port 9450
curl: (35) schannel: failed to receive handshake, SSL/TLS connection failed
ls -la /home/djangoweb/certs/
total 24
drwxr-xr-x 4 django django 4096 Aug 16 00:21 .
drwx------ 13 django django 4096 Aug 16 01:07 ..
drwxr-xr-x 2 django django 4096 Aug 16 00:20 cacerts
drwxr-xr-x 2 django django 4096 Aug 16 00:22 private
-rw-r--r-- 1 django django 7831 Aug 16 00:21 star.mydomain.com.pem
total 12
drwxr-xr-x 2 django django 4096 Aug 16 00:22 .
drwxr-xr-x 4 django django 4096 Aug 16 00:21 ..
-rw------- 1 600 600 3272 Aug 16 00:21 star.mydomain.com.key
ls -la /home/djangoweb/certs/cacerts/
total 40
drwxr-xr-x 2 django django 4096 Aug 16 00:20 .
drwxr-xr-x 4 django django 4096 Aug 16 00:21 ..
-rw-r--r-- 1 django django 30720 Aug 16 00:19 DigiCertCA.crt
Are you certain you meant to configure cert_reqs, your curl test is not using client auth. Also, reread the logs emitted by Gunicorn. If you have not seen the warning telling you ssl_version is deprecated and ignored, maybe you missed something else there?
Are you certain you meant to configure
cert_reqs, your curl test is not using client auth. Also, reread the logs emitted by Gunicorn. If you have not seen the warning telling youssl_versionis deprecated and ignored, maybe you missed something else there?
I am trying to configure mTLS actually between Ngnix reverse proxy and Gunicorn. I assume the cert_reqs would be needed and both sides need the TLS CA certificate installed.
Yes, you are correct on the Curl command used. I changed it to just a Curl request without options. But when trying to hit the proxied "/dashboard/" via 9443 it has a 301 redirect but the TLS connection fails.
curl https://server01.mydomain.com:9443/dashboard
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.14.1</center>
</body>
</html>
curl https://server01.mydoamin.com:9450/dashboard curl: (35) schannel: failed to receive handshake, SSL/TLS connection failed
Are we assuming that Gunicorn does not support mTLS (mutual TLS) to secure the backend instead of terminating the TLS connection a Nginx and the plaintext talking to the app?
When I go to https://192.168.46.69:9450/dashboard using Incognito directly and bypass proxy, the Gunicorn TLS config is still not working. Browser is still saying connection not secure.
I tried to comment out all lines in the gunicorn.conf.py and use the cli
gunicorn --certfile /home/djangoweb/certs/star.mydomain.com.pem --keyfile /home/djangoweb/certs/private/star.mydoamin.com.key -c cloudmonitor/gunicorn.conf.py --error-logfile -
2024/08/16 11:54:54 [error] 4169609#0: *1 peer closed connection in SSL handshake (104: Connection reset by peer) while SSL handshaking to upstream, client: 10.206.10.11, server: server01.oversightsystems.com, request: "GET /dashboard/ HTTP/1.1", upstream: "https://192.168.46.69:9450/dashboard/", host: "server01.mydomain:9443"
For sanity, I may try my Django app with uwsgi to see if I can reproduce the issue or not.
Hi , Iam facing one issue with my gunicorn.config.py file trying to use ssl_context hook for defining the certfile and keyfile and password in load_cert_chain try to run the application with gunicorn.config.py but my application is running in http only ssl context is not getting read bind= host+':6001' workers=1 loglevel='info' worker_class = 'uvicorn.workers.UvicornWorker'
def ssl_context(conf, default_ssl_context_factory): context= default_ssl_context_factory() context. load_cert_chain(certfile=certfile, keyfile=keyfile, password=password) return context
iam getting certt and keyfile and keypassword from . env file and my gunicorn version is 23.0.0 when I declare the certfile and keyfile alone without ssl_context it is asking for Pem pass in the terminal I need to enter manually
Can any one help me to figure out this, my keyfile is password protected
#gunicorn @benoitc