NginX SSL 不适用于 Python 请求,但适用于浏览器

NginX SSL 不适用于 Python 请求,但适用于浏览器

我有一个小型 Web 服务器,其中装有 Python (v3.6)、Flask (v1.1.1) 和 NginX (v1.16.1)。我已从 获取并设置了 SSL 证书sslforfree.com。当我使用任何浏览器访问页面时,一切正常,但我无法使用 Python 脚本和请求库访问它:

import requests
print(requests.get('https://www.some-project.com'))
Traceback (most recent call last):
  File "/anaconda3/lib/python3.6/site-packages/urllib3/contrib/pyopenssl.py", line 441, in wrap_socket
    cnx.do_handshake()
  File "/anaconda3/lib/python3.6/site-packages/OpenSSL/SSL.py", line 1907, in do_handshake
    self._raise_ssl_error(self._ssl, result)
  File "/anaconda3/lib/python3.6/site-packages/OpenSSL/SSL.py", line 1639, in _raise_ssl_error
    _raise_current_error()
  File "/anaconda3/lib/python3.6/site-packages/OpenSSL/_util.py", line 54, in exception_from_error_queue
    raise exception_type(errors)
OpenSSL.SSL.Error: [('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/anaconda3/lib/python3.6/site-packages/urllib3/connectionpool.py", line 601, in urlopen
    chunked=chunked)
  File "/anaconda3/lib/python3.6/site-packages/urllib3/connectionpool.py", line 346, in _make_request
    self._validate_conn(conn)
  File "/anaconda3/lib/python3.6/site-packages/urllib3/connectionpool.py", line 850, in _validate_conn
    conn.connect()
  File "/anaconda3/lib/python3.6/site-packages/urllib3/connection.py", line 326, in connect
    ssl_context=context)
  File "/anaconda3/lib/python3.6/site-packages/urllib3/util/ssl_.py", line 329, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "/anaconda3/lib/python3.6/site-packages/urllib3/contrib/pyopenssl.py", line 448, in wrap_socket
    raise ssl.SSLError('bad handshake: %r' % e)
ssl.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/anaconda3/lib/python3.6/site-packages/requests/adapters.py", line 449, in send
    timeout=timeout
  File "/anaconda3/lib/python3.6/site-packages/urllib3/connectionpool.py", line 639, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "/anaconda3/lib/python3.6/site-packages/urllib3/util/retry.py", line 388, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='www.some-project.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",),))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/aivanf/Desktop/some-project/py-API/test.py", line 55, in <module>
    main()
  File "/Users/aivanf/Desktop/some-project/py-API/test.py", line 49, in main
    print(requests.get(MAIN_URL))
  File "/anaconda3/lib/python3.6/site-packages/requests/api.py", line 75, in get
    return request('get', url, params=params, **kwargs)
  File "/anaconda3/lib/python3.6/site-packages/requests/api.py", line 60, in request
    return session.request(method=method, url=url, **kwargs)
  File "/anaconda3/lib/python3.6/site-packages/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/anaconda3/lib/python3.6/site-packages/requests/sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "/anaconda3/lib/python3.6/site-packages/requests/adapters.py", line 514, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='www.some-project.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",),))

我尝试在不同的计算机上执行相同的操作,以更新 OpenSSL 和根证书,但没有任何帮助... 问题出在哪里?为什么所有浏览器都可以正常使用该网站,但 Python 却不行?如何解决?

此外,https://sslforfree.com虽然它的证书与我的非常相似,但访问它本身却运行良好。因此,我猜问题出在我的 NginX 配置上:

这是我的 NginX 配置:

ssl_certificate /var/www/ssl/ca.crt;
ssl_certificate_key /var/www/ssl/private.key;

# Redirect @ to www
server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name  some-project.com;
    rewrite ^ https://www.some-project.com$request_uri?;
}

# Redirect www HTTP to HTTPS
server {
    listen 80;
    server_name  www.some-project.com;
    rewrite ^ https://www.some-project.com$request_uri? permanent;
}

server {
    listen 443 ssl;
    server_name  www.some-project.com;

    include /etc/nginx/vhosts-includes/*.conf;

    # Static Content
    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /var/www/some-project/;
    }

    location / {
        default_type "text/html";
        alias /var/www/some-project/static/;
    }
}

server {
    listen 443 ssl;
    server_name  api.some-project.com;

    # Reverse Proxy
    location / {
        proxy_pass http://localhost:5926;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-Ip $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

答案1

使用了“错误”的证书,因为 Nginx 需要完整的链 + 密钥。通过组合域和 CA 捆绑证书解决了这个问题。

相关内容