2

openssl ライブラリを使用して、一部のサーバーへの TLS 接続を開いています。ライブラリのドキュメントを読んでいます (はい、まだドキュメントやマニュアル ページを読んでいる人もいます) 。

一般的に、再入不可関数とは何かを理解しています。つまり、内部状態を保持する関数で、同時に2回呼び出したり、実行中に中断したりすると騒乱を引き起こす可能性があります(呼び出し元が期待していることを実行しない関数) .

しかし、SSL_library_init() の特定のケースでは、それが実際に何を意味するのだろうか。

  • SSL_library_init() の呼び出し中に何らかの割り込みが発生すると、SSL ライブラリが正しく初期化されないということですか? したがって、呼び出す前にアクセス可能なすべての割り込みを無効にし、必要な割り込みを後で再度有効にする必要がありますか?

  • それはスレッドセーフではないことを意味し、2 つのスレッドが同時に呼び出すことができないことを確認する必要がありますか? (スレッドセーフが再入可能と正確に同じではない場合でも、可能性が高いように見えます)。

  • プログラムの存続期間中に2回呼び出すべきではないということですか、それともSSL接続が開いている間に呼び出すと大混乱になるのでしょうか?

一方の端がクライアントで、もう一方の端がサーバーであるプロキシで作業しているため、両端が TLS サービスを使用している可能性があります (ただし、一方の端のみの場合もあれば、まったくない場合もあります)。SSL ライブラリをシステム全体のシングルトンとして管理する必要がありますか? この場合、管理は簡単ですが、私が理解しているように、再入の問題ではありません。

一度だけ呼び出されるべき関数の短い言葉がわかりません...

SSL_CTX_new() についても同様の質問があります。ドキュメントには、プログラムの存続期間ごとに 1 回だけ呼び出す必要があると記載されています。これは、サーバーとクライアント (または同じプロセスで実行されているいくつかの独立したサーバーまたはクライアント インスタンス) の両方が同じ SSL_METHOD を使用するように制限しているように見え、正しく感じられないため厄介ですが、この場合でも、ドキュメントの不正確さだけであることを願っています。 .

安全な側にとどまるためにOpenSSLの初期化コードで何をすべきか、何をすべきでないかを説明するのに十分なopenSSLの経験を持っている人はいますか?

4

1 に答える 1

1

私が見ているものに基づいてヒントを与えることができます。CentOS 7 / Django 1.9.3 / Apache 2.4 / mod_ssl / Python 3.4 Web サーバーがあり、ユーザーから https: 接続を受け取ります。リクエストの処理中、サーバーはリクエストを満たすために必要な情報をバックエンドに問い合わせる必要があります。バックエンド クエリは、スタンドアロンで実行すると問題なく動作しますが、次のものが生成されます。

OSError(0, 'Error')
Line 810, /lib64/python3.4/ssl.py

803  def do_handshake(self, block=False):
804      """Perform a TLS/SSL handshake."""
805      self._check_connected()
806      timeout = self.gettimeout()
807      try:
808          if timeout == 0.0 and block:
809              self.settimeout(None)
810          self._sslobj.do_handshake()          # <<<-------

Apache WSGI コンテキストで実行する場合。

実際に mod_ssl が私のエラーを引き起こしている場合、それはライブラリがスレッドセーフであることを意味します (Apache はもちろん複数の Web リクエストを同時に処理できるため) が、リエントラントではありません (SSL を 2 回使用できないためです。たとえば、フロントエンドとバック-接続を終了します -- シングルスレッドで)。

確かに、2 層 Web サーバーは成熟した設計パターンであるため、回避策が必要です。非再入可能性について少し投稿していただきありがとうございます。これは、私の問題の原因である可能性があることを発見した最初の手がかりでした。

参考までに、私のコードは、SSL_CLIENT_CERT から抽出されたユーザーの識別名を受け取り、JSON 形式でユーザー属性を返す RESTful サービスを呼び出します。

import requests, urllib

URL = 'https://example.com/rest/user_info/'

def get_user_info(dn)
    query = URL + urllib.parse.quote(dn)
    return requests.get(query, cert=('server.crt', 'server.key'), verify='ca_bundle.crt').json()

このコードは、Web サーバー (ユーザー apache として WSGI ディレクトリ内) のコマンド ラインから実行すると完全に機能しますが、Apache 自体から呼び出されると失敗します。

于 2016-04-05T18:13:47.477 に答える