【问题标题】:Why do I get a "SSL error: called a function you should not call" with Django为什么我会在 Django 中收到“SSL 错误:调用了一个你不应该调用的函数”
【发布时间】:2017-03-09 18:00:32
【问题描述】:

我有一个 Python 3.5/Django 1.10 应用程序,由 Apache/mod_wsgi 通过 SSL 提供服务。它连接到Postgres 9.5.2 数据库(使用psycopg2==2.6.2)并在AlwaysData 的服务器上运行

它大部分时间都可以正常工作,但有时会出现我不理解的错误。

(SSL error: called a function you should not call)

如果我把以下数据库设置:错误似乎每次都会发生

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'db',
        'USER': 'user',
        'PASSWORD': 'password',
        'HOST': 'host',
        'PORT': '',
        'OPTIONS': {
            'sslmode': 'require',
        },
    }
}

好像是在查询数据库时发生的。

# django/db/backends/utils.py line 64
return self.cursor.execute(sql, params)

当 Angular2 应用调用 REST api(使用 django-rest-framework 制作)时会出现问题。

我已激活以下设置:

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

为什么会这样?如何在我的 Django 项目中解决这个问题。

注意:This question 看起来很相似,但我不直接管理 OpenSSL 层,所以它不是很有帮助。

编辑:这是完整的回溯

File "proj/env/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
  39.             response = get_response(request)

File "proj/env/lib/python3.5/site-packages/django/core/handlers/base.py" in _legacy_get_response
  249.             response = self._get_response(request)

File "proj/env/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "proj/env/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "proj/env/lib/python3.5/site-packages/django/views/decorators/csrf.py" in wrapped_view
  58.         return view_func(*args, **kwargs)

File "proj/env/lib/python3.5/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "proj/env/lib/python3.5/site-packages/rest_framework/views.py" in dispatch
  474.             response = self.handle_exception(exc)

File "proj/env/lib/python3.5/site-packages/rest_framework/views.py" in handle_exception
  434.             self.raise_uncaught_exception(exc)

File "proj/env/lib/python3.5/site-packages/rest_framework/views.py" in dispatch
  471.             response = handler(request, *args, **kwargs)

File "proj/apps/costs/apis.py" in get
  296.         data = self.get_spends_stats(cost_items, perimeter, start_date, end_date)

File "proj/apps/costs/apis.py" in get_spends_stats
  306.         for building in buildings:

File "proj/env/lib/python3.5/site-packages/django/db/models/query.py" in __iter__
  256.         self._fetch_all()

File "proj/env/lib/python3.5/site-packages/django/db/models/query.py" in _fetch_all
  1087.             self._result_cache = list(self.iterator())

File "proj/env/lib/python3.5/site-packages/django/db/models/query.py" in __iter__
  54.         results = compiler.execute_sql()

File "proj/env/lib/python3.5/site-packages/django/db/models/sql/compiler.py" in execute_sql
  835.             cursor.execute(sql, params)

File "proj/env/lib/python3.5/site-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)

File "proj/env/lib/python3.5/site-packages/django/db/utils.py" in __exit__
  94.                 six.reraise(dj_exc_type, dj_exc_value, traceback)

File "proj/env/lib/python3.5/site-packages/django/utils/six.py" in reraise
  685.             raise value.with_traceback(tb)

File "proj/env/lib/python3.5/site-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)

Exception Type: OperationalError at /costs/api/benchmark/cost-center/3/38/2016-01/2017-12/
Exception Value: SSL error: called a function you should not call

【问题讨论】:

  • 它可能会有所帮助:我正在为 Postgres 使用 psycopg2==2.6.2
  • 您能在utils.py:64 之后发布堆栈跟踪吗?也许有些东西可能会暗示内层发生了什么......
  • 我已经添加了 traceback 。不幸的是,它没有比utils.py:64
  • 'sslmode': 'require' 选项似乎每次都会导致错误。

标签: python django apache postgresql ssl


【解决方案1】:

在 SSL_shutdown 握手中有一个相关的bug #58956 in Apache + OpenSSL,以完全相同的错误消息结尾,即 2016 年 2 月的fixed by OpenSSL。尝试升级到 1.0.2g 或 1.1.0 或更高版本。


编辑:如果您有一些 1.0.2 版本(可能有更多版本,但您感兴趣的软件包与 1.0.2 相关联),那么 SSL 的升级值得考虑。这里写1.1.0版本只是为了完整性,任何人都可以在以后轻松检查版本,是否与此错误有关。现在没有人可能在生产主机上安装 1.1,而对其进行自制升级可能是个坏主意。

【讨论】:

    【解决方案2】:

    问题似乎通过更改数据库设置解决了

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql',
            'NAME': 'name',
            'USER': 'user',
            'PASSWORD': 'password',
            'HOST': 'host',
            'PORT': '',
            'OPTIONS': {
                'sslmode': 'disable',
            },
        }
    }
    

    如果未设置该选项,则默认使用prefer(请参阅https://www.postgresql.org/docs/9.5/static/libpq-ssl.html),这似乎具有不可预测的行为。

    我猜根本原因是 Apache 和 Postgres 之间的 OpenSSL 不匹配。必须调查。

    当前修复使数据库连接不安全,但这是另一回事。

    【讨论】:

    • 您是否因为尝试我的回答而导致版本不匹配?对不起。我希望它可以很容易地恢复。如果您的操作系统分发系统安装了所有软件包并且您只安装了更新,则不应出现不匹配的情况。 libssl“1.0.2g”末尾的字母“g”对于动态加载器并不重要,您可以通过在具有相同操作系统的机器上重新编译lib SSL来成功替换它。
    • 由于头文件不同,任何不同的版本号都可能需要重新编译应用程序,而且工作量太大。最复杂的是在同一系统上重新编译所有必需的 Apache mod_*。即使这很奇怪,您最多只能重新编译一个,但根据我几年前的经验,这比尝试“简单”地从其他不同发行版复制一些新的小东西要容易。
    • 传统的“mod_wsgi”(不是“express”mod_wsgi)是一个封装到 Apache 模块的 Python。所有 Apache 扩展 (mod_*) 应该一起重新编译,否则您不能使用自动脚本进行重建。 (在我的答案中添加了一个新段落)
    【解决方案3】:

    看起来像 psycopg2 错误(或者更确切地说,as piro pointed out,底层 libpq 的错误)。它似乎违反了所需的调用顺序 - likely not waiting for some event。由于这种情况不定期发生,因此可能是一种竞争条件。

    它甚至提供了关于错误的不完整信息,这是另一个错误。它应该使用ERR_print_errors() 来获取格式为[pid]:error:[error code]:[library name]:[function name]:[reason string]:[file name]:[line]:[optional text message] 的完整消息。

    【讨论】:

    • psycopg 使用 libpq 进行 ssl 通信。对我来说,这似乎是一个 libpq 错误。
    • @piro 好吧,具体负责的代码在这里是次要的。当然,这不会削弱您的提示的有用性。
    • @ivan_pozdeev 当然:我只是针对我认为错误所在的地方进行调查。 libpq 和 psycopg 是不同的项目,由不同的人维护。即使是“打印”提示也可能有用……但对合适的人来说。 psycopg 不会直接调用 openssh 函数,所以如果可以改进一些代码,它应该是 libpq
    猜你喜欢
    • 1970-01-01
    • 2018-05-14
    • 1970-01-01
    • 2019-11-04
    • 2021-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-21
    相关资源
    最近更新 更多