TLS/SSL 套接字 python 服务器

Posted

技术标签:

【中文标题】TLS/SSL 套接字 python 服务器【英文标题】:TLS/SSL socket python server 【发布时间】:2020-04-21 16:36:23 【问题描述】:

我正在尝试使用socketssl 模块使用Python3 构建一个简单的HTTPS 服务器。 我有一个由 OpenSSL 生成的自签名证书和一个私钥文件,我尝试将它们与 ssl 模块一起使用,但每次尝试时,我都会收到“ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:1076)”错误。 我的代码是

import socket
import ssl
    context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
    context.load_cert_chain(certfile='cert.pem', keyfile='my_key.key')
    context.verify_mode = ssl.CERT_NONE
    sock = socket.socket()
    sock.bind(('', 443))
    sock.listen(5)
    while True:
        new_conn, addr = sock.accept()
        ssl_conn = context.wrap_socket(new_conn, server_side=True)
        print(ssl_conn.recv(1024).decode())     # this is where i get the error

我得到的错误是:

  File "C:\AllInOne\PortableApps\Python374\lib\ssl.py", line 1139, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:1076)

有谁知道为什么会发生这种情况或如何解决?

【问题讨论】:

【参考方案1】:
    # Generate server.pem with the following command:
#    mkdir .ssh
#    openssl req -new -x509 -keyout .ssh/key.pem -out .ssh/cert.pem -days 365 -nodes
# run as follows:
#    python3 simple-https-server.py
# then in your browser, visit:
#    https://localhost:4443

import http.server
from http.server import HTTPServer, BaseHTTPRequestHandler, SimpleHTTPRequestHandler
import ssl
import sys

#This class will handles any incoming request from the browser
class myHandler(BaseHTTPRequestHandler):
        #Handler for the GET requests
        def do_GET(self):
                print(self.requestline)
                #print(self.rfile.read(content_length))
                self.send_response(200)
                self.send_header('Content-type','text/html')
                self.end_headers()
                # Send the html message
                self.wfile.write("Hello World !".encode())
                return

try:
        separator = "-" * 80
        server_address = ('', 4443)
        # server_address = ('localhost', 4443)
        httpd = http.server.HTTPServer(server_address, myHandler)
        # httpd = http.server.HTTPServer(server_address, http.server.SimpleHTTPRequestHandler)
        httpd.socket = ssl.wrap_socket(httpd.socket,
                            server_side=True,
                            certfile=".ssh/cert.pem",
                            keyfile=".ssh/key.pem",
                            ssl_version=ssl.PROTOCOL_TLS)        
        print(separator)
        print("Server running on https://localhost:4443")
        print(separator)

        # Wait forever for incoming htto requests
        httpd.serve_forever()

except KeyboardInterrupt:
        print ('^C received, shutting down the web server')
        server.socket.close()

【讨论】:

【参考方案2】:
ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:1076)

客户端向您的服务器发出信号,表明它不信任您的证书。这是预期的,因为这不是由受信任的 CA 颁发的证书,并且您没有让客户端明确信任此证书。如果客户端不抱怨,那将是不安全的,因为中间的每个人都可以使用假证书将自己标识为受信任的服务器。

【讨论】:

有没有办法让它工作?我不介意客户端的浏览器显示警告。我找到了使用http.server 模块的代码,并允许我使用自签名证书而不会出错。 This is the link to said code 有没有办法只禁用这个日志? @roocell:此日志仅显示客户端不信任服务器。服务器端的“禁用日志”不会神奇地让客户端信任服务器——它所做的只是不再显示为什么你有问题但问题仍然存在并且问题不想与服务器通信。 @josh:您引用的代码不会使客户端使用自签名证书信任服务器。您现有的代码应该已经在浏览器中产生警告,您必须明确接受。

以上是关于TLS/SSL 套接字 python 服务器的主要内容,如果未能解决你的问题,请参考以下文章

TLS(SSL)

ssl.SSLZeroReturnError: TLS/SSL 连接已关闭 (EOF) (_ssl.c:661)

openssl

HTTPS原理解析-转

踮起仰望 HTTPS原理

踮起仰望 HTTPS原理