Проблема Python ssl с многопроцессорной обработкой

Я хочу отправить данные от клиента на сервер в сокет TLS TCP из нескольких подпроцессов клиента, поэтому я использую один и тот же ssl-сокет со всеми подпроцессами. Коммуникация работает с одним подпроцессом, но если я использую несколько подпроцессов, TLS-сервер вылетает с ошибкой ssl.SSLError (SSL3_GET_RECORD: дешифрование или неудачная запись mac).

Более конкретно: Не зависит от того, какой процесс сначала вызывает метод SSLSocket.write(), но этот процесс является единственным с этого момента, на котором можно его вызвать. Если другой процесс вызывает write(), сервер приведет к описанному выше исключением.

Я использовал этот базовый код:

tlsserver.py

import socket, ssl

def deal_with_client(connstream):
    data = connstream.read()
    while data:
        print data
        data = connstream.read()
    connstream.close()

bindsocket = socket.socket()
bindsocket.bind(('127.0.0.1', 9998))
bindsocket.listen(5)

while True:
    newsocket, fromaddr = bindsocket.accept()
    connstream = ssl.wrap_socket(newsocket,
                                server_side=True,
                                certfile="srv.crt",
                                keyfile="srv.key",
                                ssl_version=ssl.PROTOCOL_TLSv1)
    deal_with_client(connstream)

tlsclient.py

import socket, ssl
import multiprocessing

class SubProc:
    def __init__(self, sock):
        self.sock = sock

    def do(self):
        self.sock.write("Test")

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

ssl_sock = ssl.wrap_socket(s)
ssl_sock.connect(('127.0.0.1', 9998))

print "Connected to", repr(ssl_sock.getpeername())

for x in (1,2):
    subproc = SubProc(ssl_sock)
    proc = multiprocessing.Process(target=subproc.do)

И это обратная трассировка:

Traceback (most recent call last):
  File "tlsserver.py", line 21, in <module>
    deal_with_client(connstream)
  File "tlsserver.py", line 7, in deal_with_client
    data = connstream.read()
  File "/usr/lib64/python2.6/ssl.py", line 136, in read
    return self._sslobj.read(len)
ssl.SSLError: [Errno 1] _ssl.c:1325: error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad record mac

Ответ 1

Проблема заключается в том, что вы повторно используете одно и то же соединение для обоих процессов. Способ шифрования данных SSL делает это неудачным - два процесса должны были бы связываться друг с другом о состоянии общего SSL-соединения. Даже если вы это сделаете, или если вы не используете SSL, данные будут поступать на сервер, все перепутались; у вас не было бы реального способа определить, какие байты были получены из этого процесса.

Что вам нужно сделать, так это предоставить каждому процессу собственное SSL-соединение, установив соединение в subproc.do. В качестве альтернативы, не имеют подпроцессов, которые вообще взаимодействуют с сервером, а скорее общаются с основным процессом и имеют основное управление процессом по SSL-соединению.