Python 在多进程中出现 ssl 问题

20 投票
1 回答
15906 浏览
提问于 2025-04-16 04:13

我想通过一个安全的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 个回答

36

问题在于你在两个进程之间重复使用了同一个连接。SSL加密数据的方式让这个做法行不通——这两个进程需要互相沟通,了解共享的SSL连接的状态。即使你能让它工作,或者如果你不使用SSL,数据到达服务器时也会变得混乱不堪;你根本无法分辨哪些字节是哪个进程发来的。

你需要做的是给每个进程分配一个自己的SSL连接,可以在subproc.do中建立这个连接。或者,你也可以选择不让子进程直接和服务器通信,而是让它们先和主进程沟通,再由主进程通过SSL连接转发数据。

撰写回答