kubernetes 强制gunicorn仅接受SSL/TLS连接的特定密码

wlzqhblo  于 5个月前  发布在  Kubernetes
关注(0)|答案(1)|浏览(65)

我在Kubernetes集群中运行了一个容器化的gunicorn服务器。我只希望gunicorn服务器响应使用TLS_AES_256_GCM_SHA384密码套件连接的用户。我不知道如何有效地传递--cipher参数来限制所有非TLS_AES_256_GCM_SHA384密码。
如果我在启动gunicorn时没有指定这样的密码

gunicorn --workers=2 \
--bind=0.0.0.0:443 \
--timeout 600 \
--error-logfile gunicorn.log \
--log-level debug \
--certfile ./cert.pem \
--keyfile ./key.pem \
--ssl-version=5 \
main_server:app

字符串
我可以使用curl连接到服务器

$ curl --insecure --tls13-ciphers TLS_AES_256_GCM_SHA384 -v https://192.168.49.2/serve
*   Trying 192.168.49.2:443...
* TCP_NODELAY set
* Connected to 192.168.49.2 (192.168.49.2) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLS 1.3 cipher selection: TLS_AES_256_GCM_SHA384
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: O=Acme Co; CN=Kubernetes Ingress Controller Fake Certificate
*  start date: Dec  5 17:21:58 2023 GMT
*  expire date: Dec  4 17:21:58 2024 GMT
*  issuer: O=Acme Co; CN=Kubernetes Ingress Controller Fake Certificate
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55cc709790c0)
> GET /serve HTTP/2
> Host: 192.168.49.2
> user-agent: curl/7.68.0
> accept: */*
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200 
< date: Wed, 06 Dec 2023 16:37:41 GMT
< content-type: text/html; charset=utf-8
< content-length: 37
< 
* Connection #0 to host 192.168.49.2 left intact
<h1><center>Hello World!</center><h1>


此外,协商实际上选择了我想要的默认密码(使用上面的TLSv1.3 / TLS_AES_256_GCM_SHA384的SSL连接),所以我知道服务器和curl都支持它。
如果我以gunicorn开头指定密码,如下所示:

gunicorn --workers=2 \
--bind=0.0.0.0:443 \
--timeout 600 \
--error-logfile gunicorn.log \
--log-level debug \
--certfile ./cert.pem \
--keyfile ./key.pem \
--ssl-version=5 \
--ciphers="TLS_AES_256_GCM_SHA384" \
main_server:app


Gunicorn服务器的日志给了我给予:

[2023-12-06 17:51:39 +0000] [8] [DEBUG] Error processing SSL request.

[2023-12-06 17:51:39 +0000] [8] [WARNING] Invalid request from ip=10.244.0.5: ('No cipher can be selected.',)


curl返回:

$ curl --insecure --tls13-ciphers TLS_AES_256_GCM_SHA384 -v https://192.168.49.2/serve
*   Trying 192.168.49.2:443...
* TCP_NODELAY set
* Connected to 192.168.49.2 (192.168.49.2) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLS 1.3 cipher selection: TLS_AES_256_GCM_SHA384
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: O=Acme Co; CN=Kubernetes Ingress Controller Fake Certificate
*  start date: Dec  5 17:21:58 2023 GMT
*  expire date: Dec  4 17:21:58 2024 GMT
*  issuer: O=Acme Co; CN=Kubernetes Ingress Controller Fake Certificate
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x559bae1090c0)
> GET /serve HTTP/2
> Host: 192.168.49.2
> user-agent: curl/7.68.0
> accept: */*
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 502 
< date: Wed, 06 Dec 2023 17:51:39 GMT
< content-type: text/html
< content-length: 150
< 
<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host 192.168.49.2 left intact


我试过用双引号、单引号和不加引号的方式来发出密码。我试过用等号和空格加上密码名。
我知道Kubernetes入口和服务网络是好的,否则当我不指定确切的密码时,事情就无法工作。
我已经看了https://venafi.com/blog/what-are-cipher-suites/https://docs.gunicorn.org/en/20.1.0/settings.htmlhttps://github.com/benoitc/gunicorn/issues/2579How to disable SSLv3.0 and use TLS1.0 in Gunicorn,和其他一些地方试图找到一个例子,如何强制这一点,但还没有能够弄清楚到底是怎么回事.我可以告诉我最混乱的格式为密码.
我正在寻找一个答案,它将告诉我如何启动gunicorn,以便它只在请求用户尝试使用TLS_AES_256_GCM_SHA384密码连接时才会响应。

juzqafwq

juzqafwq1#

好吧,我想通了。对于那些试图做类似事情的人来说,这里发生了很多事情。

  1. gunicorn在后台依赖于OpenSSL。传递给gunicorn的基于SSL的命令行参数然后在后台调用OpenSSL时使用。
  2. OpenSSL致力于支持TLS 1.3,这意味着它必须支持所有的TLS 1.3密码套件。此外,OpenSSL不会接受限制TLS 1.3密码的命令行参数。这是OpenSSL以前的SSL/TLS版本行为的变化
  3. Kubernetes Ingress正在终止来自curl的SSL连接,而不是将其传递到我的容器,这意味着无论我对我的容器做什么,我都不能限制初始连接。
    去解决问题并强制我想要的密码套件。
  4. Gunicorn -不需要在这里做任何事情。
  5. OpenSSL -我修改了OpenSSL配置文件,只允许我想要的密码。serverfault有一个问题,答案显示了如何做到这一点https://serverfault.com/questions/1033439/how-do-i-disable-just-one-cipher-out-of-openssl-tlsv1-3-list,他们引用了一篇博客文章,提供了更多细节https://dawnbringer.net/blog/1083/TLS%20All%20The%20Things!%20Perfect%20ssl-labs%20score%20for%20Nginx,但底线是,你需要添加以下部分到openssl.conf文件。
    [system_default_sect]
    MinProtocol = TLSv1.2
    CipherString = DEFAULT@SECLEVEL=2
    密码套件= TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
    选项=服务器首选项,优先级ChaCha
    需要在任何有openssl.cnf文件的地方进行修改,对于我的Ubuntu发行版,该文件是/etc/ssl/openssl.cnf和/lib/usr/ssl/openssl. cnf。我强烈建议阅读OpenSSL配置文件格式文档,因为它有助于说明不明显的配置要求。https://www.openssl.org/docs/man1.1.1/man5/config.html
    1.为了让SSL握手通过Ingress传递到我的容器,我必须更新Ingress控制器并添加标志--enable-ssl-passthrough。请注意,这是控制器而不是部署。
    部署必须具有以下注解
nginx.ingress.kubernetes.io/backend-protocol: "https"
   nginx.ingress.kubernetes.io/ssl-passthrough: "true"
   nginx.ingress.kubernetes.io/force-ssl-redirect: "true"

字符串
最后,SSL passthrough要求Ingress Deployment有一个主机集。我只是在curl命令中使用了IP地址。为了解决这个问题,我在/etc/hosts中添加了一个记录作为Ingress的IP,然后使用我为/etc/host记录编写的主机名作为Ingress Deployment的主机。

相关问题