【问题标题】:Python 3.7.7 SSL socketserver ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote hostPython 3.7.7 SSL socketserver ConnectionResetError: [WinError 10054] 现有连接被远程主机强行关闭
【发布时间】:2020-05-02 09:07:05
【问题描述】:

我在win10系统上用python写了一个简单的客户端-服务器应用程序。我正在使用 Python 3.7.7。

当客户端连接到服务器时,我收到以下错误:

Sending data
Traceback (most recent call last):
  File "Client.py", line 23, in <module>
    ssock.send(b'this is a test\n')
  File "D:\SecureServer\Python37\lib\ssl.py", line 1003, in send
    return self._sslobj.write(data)
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host

为方便起见,我为客户端和服务器使用相同的证书/密钥。

帮助将不胜感激。 谢谢。

这是代码。

服务器:

import socketserver
import ssl


class RequestServer(socketserver.ThreadingMixIn, socketserver.TCPServer):

    allow_reuse_address = True
    request_queue_size = 10
    daemon_threads = True

    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
        super().__init__(server_address, RequestHandlerClass, False)

        ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
        ctx.verify_mode = ssl.CERT_REQUIRED
        client_certs = './certs/ca-chain.cert.pem'
        ctx.load_verify_locations(cafile=client_certs)
        server_cert = './certs/www.example.com.cert.pem'
        server_key = './certs/www.example.com.key.pem'
        ctx.load_cert_chain(certfile=server_cert, keyfile=server_key, password=None)

        self.socket = ctx.wrap_socket(self.socket, server_side=True)
        if (bind_and_activate):
            self.server_bind()
            self.server_activate()


class RequestHandler(socketserver.StreamRequestHandler):
    def handle(self):
        print("connection from {}:{}".format(self.client_address[0], self.client_address[1]))

        try:
            common_name = self._get_certificate_common_name(self.request.getpeercert())
            if (common_name is None or common_name != "www.example.com"):
                print("rejecting {}".format(common_name))
                self.wfile.write('{"accepted": false}\n'.encode())
                return
            data = self.rfile.readline().strip()
            print("data: {}".format(data))
            self.wfile.write('{"accepted": true}\n'.encode())
        except BrokenPipeError:
            print("broken pipe from {}:{}".format(self.client_address[0], self.client_address[1]))

    def _get_certificate_common_name(self, cert):
        if (cert is None):
            return None

        for sub in cert.get("subject", ()):
            for key, value in sub:
                if (key == "commonName"):
                    return value

server = RequestServer(("127.0.0.1", 3278), RequestHandler)
server.serve_forever()

这是客户端:

import socket
import ssl


if __name__ == '__main__':

    ctx = ssl.create_default_context()
    ctx.verify_mode = ssl.CERT_REQUIRED
    ctx.check_hostname = True

    certs_folder = './certs/'
    server_certs = certs_folder + 'ca-chain.cert.pem'
    ctx.load_verify_locations(cafile=server_certs)
    client_cert = certs_folder + 'www.example.com.cert.pem'
    client_key = certs_folder + 'www.example.com.key.pem'
    ctx.load_cert_chain(certfile=client_cert, keyfile=client_key, password=None)

    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        print(sock)
        with ctx.wrap_socket(sock, server_side=False, server_hostname="www.example.com") as ssock:
            ssock.connect(("127.0.0.1", 3278))
            print("SSL established. Peer: {}".format(ssock.getpeercert()))
            ssock.send(b'this is a test\n')  # this is line 23

【问题讨论】:

    标签: python windows ssl socketserver


    【解决方案1】:

    经过深入分析,我发现了一些错误:

    1) 客户端证书不能是服务器证书;我为客户端和服务器使用了相同的证书。解决方案:创建一个适当的客户端证书。

    2) SSL 套接字由于 SSL 3-Way 握手而阻塞,因此,如果客户端在发送数据后关闭套接字,服务器将失去连接。必须管理数据传输。

    【讨论】:

      猜你喜欢
      • 2018-01-02
      • 2020-04-20
      • 2015-02-28
      • 2015-05-24
      • 2016-10-20
      • 2020-10-09
      • 2020-07-24
      • 2023-03-03
      • 2021-03-31
      相关资源
      最近更新 更多