Gunicorn双向SSL错误“ SSL_ERROR_UNKNOWN_CA_ALERT”

时间:2018-12-11 18:35:47

标签: python ssl gunicorn

我正在通过Gunicorn运行配置了双向SSL的Python3应用。这需要本地证书/密钥来验证应用程序,还需要ca_certs文件来验证客户端。 Gunicorn依赖于Python中的标准ssl模块,尤其是wrap_socket方法。

当我同时使用服务器和客户端身份验证的自签名证书时,该服务会启动并可以很好地响应curl请求。但是,当我使用由另一个CA签名的证书时,会出现错误SSL_ERROR_UNKNOWN_CA_ALERT

具有自签名证书的有效设置:

# Server cert
openssl req \
       -newkey rsa:2048 -nodes -keyout domain.key \
       -x509 -days 365 -out domain.crt

# Client (CA) cert    
openssl req \
       -newkey rsa:2048 -nodes -keyout twoway.key \
       -x509 -days 365 -out twoway.crt

将Gunicorn配置如下:

keyfile = domain.key
certfile = domain.crt
cert_reqs = ssl.CERT_REQUIRED
ca_certs=twoway.crt

卷曲如下:

curl -vk --key twoway.key --cert twoway.crt https://my.service

产生成功的响应:

*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 5000 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-SHA
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd
*  start date: Dec  7 18:35:54 2018 GMT
*  expire date: Dec  7 18:35:54 2019 GMT
*  issuer: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
> GET /manage/info HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: gunicorn/19.9.0
< Date: Tue, 11 Dec 2018 18:26:19 GMT
< Connection: keep-alive
< Content-Type: application/json
< Content-Length: 73

设置失败,带有一系列不同的证书:

将Gunicorn配置如下:

keyfile = my_service_key.key
certfile = my_service_cert.crt
cert_reqs = ssl.CERT_REQUIRED
ca_certs = my_trusted_clients.crt

卷曲如下:

curl -vk --key my_trusted_key.key --cert my_trusted_clients.crt https://my.service

产生错误:

About to connect() to localhost port 5000 (#0)
Initializing NSS with certpath: sql/etc/pki/nssdb
warning: ignoring value of ssl.verifyhost
skipping SSL peer certificate verification
NSS: client certificate from file
    subject: CN=mycn,OU=abc,O=def,...
NSS error -12195
Closing connection #0
SSL connect error
curl: (35) SSL connect error

是否有关于我是否以错误方式配置此配置的想法?为什么自签名证书有效,而其他证书无效?

请注意,此配置以前在使用Stunnel时有效,其中我将verify级别设置为4(“忽略链,仅验证对等证书。”)。如果Python中有类似的东西,我相信这会让我朝正确的方向前进。

1 个答案:

答案 0 :(得分:0)

我认为从Gunicorn 19.9起,这是不可能的。

除了要在服务器上拥有完整的证书链以外,为了验证客户端/对等证书,我相信您将需要能够configure the SSLContext,尤其是能够设置{{3} }(在服务器模式下)。

Gunicorn 19.9(在撰写本文时为master)目前未在连接上使用基于SSLContext的包装器,因此这是不可能的,请参阅ssl.CERT_REQUIRED